package binder import ( "errors" "mime/multipart" "reflect" "testing" "github.com/stretchr/testify/require" ) func Test_EqualFieldType(t *testing.T) { t.Parallel() var out int require.False(t, equalFieldType(&out, reflect.Int, "key")) var dummy struct{ f string } require.False(t, equalFieldType(&dummy, reflect.String, "key")) var dummy2 struct{ f string } require.False(t, equalFieldType(&dummy2, reflect.String, "f")) var user struct { Name string Address string `query:"address"` Age int `query:"AGE"` } require.True(t, equalFieldType(&user, reflect.String, "name")) require.True(t, equalFieldType(&user, reflect.String, "Name")) require.True(t, equalFieldType(&user, reflect.String, "address")) require.True(t, equalFieldType(&user, reflect.String, "Address")) require.True(t, equalFieldType(&user, reflect.Int, "AGE")) require.True(t, equalFieldType(&user, reflect.Int, "age")) var user2 struct { User struct { Name string Address string `query:"address"` Age int `query:"AGE"` } `query:"user"` } require.True(t, equalFieldType(&user2, reflect.String, "user.name")) require.True(t, equalFieldType(&user2, reflect.String, "user.Name")) require.True(t, equalFieldType(&user2, reflect.String, "user.address")) require.True(t, equalFieldType(&user2, reflect.String, "user.Address")) require.True(t, equalFieldType(&user2, reflect.Int, "user.AGE")) require.True(t, equalFieldType(&user2, reflect.Int, "user.age")) } func Test_ParseParamSquareBrackets(t *testing.T) { t.Parallel() tests := []struct { err error input string expected string }{ { err: nil, input: "foo[bar]", expected: "foo.bar", }, { err: nil, input: "foo[bar][baz]", expected: "foo.bar.baz", }, { err: errors.New("unmatched brackets"), input: "foo[bar", expected: "", }, { err: errors.New("unmatched brackets"), input: "foo[bar][baz", expected: "", }, { err: errors.New("unmatched brackets"), input: "foo]bar[", expected: "", }, { err: nil, input: "foo[bar[baz]]", expected: "foo.bar.baz", }, { err: nil, input: "", expected: "", }, { err: nil, input: "[]", expected: "", }, { err: nil, input: "foo[]", expected: "foo", }, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { t.Parallel() result, err := parseParamSquareBrackets(tt.input) if tt.err != nil { require.Error(t, err) require.EqualError(t, err, tt.err.Error()) } else { require.NoError(t, err) require.Equal(t, tt.expected, result) } }) } } func Test_parseToMap(t *testing.T) { t.Parallel() inputMap := map[string][]string{ "key1": {"value1", "value2"}, "key2": {"value3"}, "key3": {"value4"}, } // Test map[string]string m := make(map[string]string) err := parseToMap(m, inputMap) require.NoError(t, err) require.Equal(t, "value2", m["key1"]) require.Equal(t, "value3", m["key2"]) require.Equal(t, "value4", m["key3"]) // Test map[string][]string m2 := make(map[string][]string) err = parseToMap(m2, inputMap) require.NoError(t, err) require.Len(t, m2["key1"], 2) require.Contains(t, m2["key1"], "value1") require.Contains(t, m2["key1"], "value2") require.Len(t, m2["key2"], 1) require.Len(t, m2["key3"], 1) // Test map[string]any m3 := make(map[string]any) err = parseToMap(m3, inputMap) require.ErrorIs(t, err, ErrMapNotConvertable) } func Test_FilterFlags(t *testing.T) { t.Parallel() tests := []struct { input string expected string }{ { input: "text/javascript; charset=utf-8", expected: "text/javascript", }, { input: "text/javascript", expected: "text/javascript", }, { input: "text/javascript; charset=utf-8; foo=bar", expected: "text/javascript", }, { input: "text/javascript charset=utf-8", expected: "text/javascript", }, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { t.Parallel() result := FilterFlags(tt.input) require.Equal(t, tt.expected, result) }) } } func TestFormatBindData(t *testing.T) { t.Parallel() t.Run("string value with valid key", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "name", "John", false, false) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(data["name"]) != 1 || data["name"][0] != "John" { t.Fatalf("expected data[\"name\"] = [John], got %v", data["name"]) } }) t.Run("unsupported value type", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "age", 30, false, false) // int is unsupported if err == nil { t.Fatal("expected an error, got nil") } }) t.Run("bracket notation parsing error", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "invalid[", "value", false, true) // malformed bracket notation if err == nil { t.Fatal("expected an error, got nil") } }) t.Run("handling multipart file headers", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]*multipart.FileHeader) files := []*multipart.FileHeader{ {Filename: "file1.txt"}, {Filename: "file2.txt"}, } err := formatBindData(out, data, "files", files, false, false) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(data["files"]) != 2 { t.Fatalf("expected 2 files, got %d", len(data["files"])) } }) t.Run("type casting error", func(t *testing.T) { t.Parallel() out := struct{}{} data := map[string][]int{} // Incorrect type to force a casting error err := formatBindData(out, data, "key", "value", false, false) require.Equal(t, "unsupported value type: string", err.Error()) }) } func TestAssignBindData(t *testing.T) { t.Parallel() t.Run("splitting enabled with comma", func(t *testing.T) { t.Parallel() out := struct { Colors []string `query:"colors"` }{} data := make(map[string][]string) assignBindData(&out, data, "colors", "red,blue,green", true) require.Len(t, data["colors"], 3) }) t.Run("splitting disabled", func(t *testing.T) { t.Parallel() var out []string data := make(map[string][]string) assignBindData(out, data, "color", "red,blue", false) require.Len(t, data["color"], 1) }) } func Test_parseToStruct_MismatchedData(t *testing.T) { t.Parallel() type User struct { Name string `query:"name"` Age int `query:"age"` } data := map[string][]string{ "name": {"John"}, "age": {"invalidAge"}, } err := parseToStruct("query", &User{}, data) require.Error(t, err) require.EqualError(t, err, "bind: schema: error converting value for \"age\"") } func Test_formatBindData_ErrorCases(t *testing.T) { t.Parallel() t.Run("unsupported value type int", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "age", 30, false, false) // int is unsupported require.Error(t, err) require.EqualError(t, err, "unsupported value type: int") }) t.Run("unsupported value type map", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "map", map[string]string{"key": "value"}, false, false) // map is unsupported require.Error(t, err) require.EqualError(t, err, "unsupported value type: map[string]string") }) t.Run("bracket notation parsing error", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "invalid[", "value", false, true) // malformed bracket notation require.Error(t, err) require.EqualError(t, err, "unmatched brackets") }) t.Run("type casting error for []string", func(t *testing.T) { t.Parallel() out := struct{}{} data := make(map[string][]string) err := formatBindData(out, data, "names", 123, false, false) // invalid type for []string require.Error(t, err) require.EqualError(t, err, "unsupported value type: int") }) }