form/form_test.go

178 lines
3.7 KiB
Go

package form_test
import (
"errors"
"net/url"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"source.toby3d.me/toby3d/form"
)
type (
TestResult struct {
Skip any `form:"-"`
PtrStruct *Struct `form:"ptrStruct"`
PtrStructs *Structs `form:"ptrStructs"`
NullStruct NullStruct `form:"nullstruct,omitempty"`
Struct Struct `form:"struct"`
Empty string `form:"empty"`
String string `form:"string"`
NotFormTag string `json:"notFormTag"`
ArrayStruct []Struct `form:"arrayStruct[]"`
ArrayPtrStruct []*Struct `form:"arrayPtrStruct[]"`
Ints []int `form:"ints[]"`
Structs Structs `form:"structs"`
Bytes []byte `form:"bytes"`
Uint uint `form:"uint"`
Int int `form:"int"`
Float float32 `form:"float"`
Bool bool `form:"bool"`
}
Struct struct {
uid string `form:"-"`
}
Structs []Struct
NullStruct struct {
uid string `form:"-"`
}
)
func TestUnmarshal(t *testing.T) {
t.Parallel()
t.Run("valid", func(t *testing.T) {
t.Parallel()
args, err := url.ParseQuery(`skip=dontTouchMe` +
`&bool=true` +
`&string=hello+world` +
`&int=42` +
`&uint=420` +
`&float=4.2` +
// `&interface=a1b2c3` + // TODO(toby3d)
`&struct=abc` +
`&ptrStruct=123` +
`&arrayStruct[]=abc` +
`&arrayStruct[]=123` +
`&arrayPtrStruct[]=321` +
`&arrayPtrStruct[]=bca` +
`&ints[]=240` +
`&ints[]=420` +
`&bytes=sampletext` +
`&notFormTag=dontParseMe` +
`&structs=123+abc` +
`&ptrStructs=bca+321`)
if err != nil {
t.Fatal(err)
}
in := new(TestResult)
if err := form.Unmarshal([]byte(args.Encode()), in); err != nil {
t.Fatal(err)
}
out := TestResult{
Skip: nil,
Bool: true,
Float: 4.2,
Int: 42,
// Interface: []byte("a1b2c3"), // TODO(toby3d)
PtrStruct: &Struct{uid: "123"},
String: "hello world",
Struct: Struct{uid: "abc"},
Uint: 420,
ArrayStruct: []Struct{
{uid: "abc"},
{uid: "123"},
},
ArrayPtrStruct: []*Struct{
{uid: "321"},
{uid: "bca"},
},
Ints: []int{240, 420},
Empty: "",
Bytes: []byte("sampletext"),
NotFormTag: "",
NullStruct: NullStruct{uid: ""},
Structs: Structs{
{uid: "123"},
{uid: "abc"},
},
PtrStructs: &Structs{
{uid: "bca"},
{uid: "321"},
},
}
opts := []cmp.Option{
cmp.AllowUnexported(Struct{}, NullStruct{}),
}
if !cmp.Equal(&out, in, opts...) {
t.Errorf("Unmarshal(%s, &in)\n%+s", args.Encode(), cmp.Diff(&out, in, opts...))
}
})
t.Run("invalid", func(t *testing.T) {
t.Parallel()
args, err := url.ParseQuery("arrayStruct[]=wtf")
if err != nil {
t.Fatal(err)
}
in := new(TestResult)
if err := form.Unmarshal([]byte(args.Encode()), in); err == nil {
t.Errorf("Unmarshal(%s, &in) = %#+v, want error", args.Encode(), err)
}
})
}
func (s *Structs) UnmarshalForm(v []byte) error {
for _, f := range strings.Fields(string(v)) {
*s = append(*s, Struct{uid: f})
}
return nil
}
func (s Structs) GoString() string {
out := make([]string, len(s))
for i := range s {
out[i] = s[i].uid
}
return "Structs(" + strings.Join(out, ", ") + ")"
}
func (s *Struct) UnmarshalForm(v []byte) error {
src := string(v)
switch src {
case "123", "abc", "321", "bca":
s.uid = string(v)
return nil
}
return errors.New("Struct: dough!")
}
func (ns *NullStruct) UnmarshalForm(v []byte) error {
if src := string(v); src != "" {
ns.uid = src
return nil
}
return errors.New("NullStruct: dough!")
}
func (s Struct) GoString() string { return "Struct(" + s.uid + ")" }