package form_test import ( "errors" "testing" "github.com/google/go-cmp/cmp" http "github.com/valyala/fasthttp" "source.toby3d.me/toby3d/form" ) type ( TestResult struct { ArrayStruct []Struct `form:"arrayStruct[]"` ArrayPtrStruct []*Struct `form:"arrayPtrStruct[]"` Bytes []byte `form:"bytes"` // TODO(toby3d) Ints []int `form:"ints[]"` Struct Struct `form:"struct"` NullStruct NullStruct `form:"nullstruct,omitempty"` PtrStruct *Struct `form:"ptrStruct"` Skip any `form:"-"` // Interface any `form:"interface"` // TODO(toby3d) Empty string `form:"empty"` NotFormTag string `json:"notFormTag"` String string `form:"string"` Float float32 `form:"float"` Uint uint `form:"uint"` Int int `form:"int"` Bool bool `form:"bool"` } Struct struct { uid string `form:"-"` } NullStruct struct { uid string `form:"-"` } ) func TestUnmarshal(t *testing.T) { t.Parallel() t.Run("valid", func(t *testing.T) { t.Parallel() args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Parse(`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` + `¬FormTag=dontParseMe`) var in TestResult if err := form.Unmarshal(args.QueryString(), &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: ""}, } opts := []cmp.Option{ cmp.AllowUnexported(Struct{}, NullStruct{}), } if !cmp.Equal(out, in, opts...) { t.Errorf("Unmarshal(%s, &in)\n%+s", args.QueryString(), cmp.Diff(out, in, opts...)) } }) t.Run("invalid", func(t *testing.T) { t.Parallel() args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Parse("arrayStruct[]=wtf") var in TestResult if err := form.Unmarshal(args.QueryString(), &in); err == nil { t.Errorf("Unmarshal(%s, &in) = %#+v, want error", args.QueryString(), err) } }) } 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 + ")" }