From 57491284b458619efd2f9e0cea96dbaa54e2b99a Mon Sep 17 00:00:00 2001 From: Sidi Chang Date: Mon, 4 Aug 2025 13:09:59 +0900 Subject: [PATCH] test(binding): add comprehensive slice/array BindUnmarshaler tests - Add TestMappingSliceOfCustomBindUnmarshalerElementsUri with validation for multiple elements, single element, and error cases - Add TestMappingSliceOfCustomBindUnmarshalerElementsForm with comprehensive test coverage including large slices - Add TestMappingArrayOfCustomBindUnmarshalerElementsUri with exact array size validation and error handling - Add TestMappingArrayOfCustomBindUnmarshalerElementsForm with proper error case coverage - Enhance test coverage for custom BindUnmarshaler slice and array functionality --- binding/form_mapping_test.go | 245 +++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 55b967a3..a681f568 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -635,3 +635,248 @@ func TestMappingCustomArrayForm(t *testing.T) { expected, _ := convertTo(val) assert.Equal(t, expected, s.FileData) } + +func TestMappingSliceOfCustomBindUnmarshalerElementsUri(t *testing.T) { + tests := []struct { + name string + input []string + expectError bool + expectLen int + validate func(t *testing.T, items []customUnmarshalParamType) + }{ + { + name: "multiple valid elements", + input: []string{"http:path1:name1", "https:path2:name2"}, + expectLen: 2, + validate: func(t *testing.T, items []customUnmarshalParamType) { + assert.Equal(t, "http", items[0].Protocol) + assert.Equal(t, "path1", items[0].Path) + assert.Equal(t, "name1", items[0].Name) + assert.Equal(t, "https", items[1].Protocol) + assert.Equal(t, "path2", items[1].Path) + assert.Equal(t, "name2", items[1].Name) + }, + }, + { + name: "single element", + input: []string{"tcp:socket:server"}, + expectLen: 1, + validate: func(t *testing.T, items []customUnmarshalParamType) { + assert.Equal(t, "tcp", items[0].Protocol) + assert.Equal(t, "socket", items[0].Path) + assert.Equal(t, "server", items[0].Name) + }, + }, + { + name: "invalid format - too few parts", + input: []string{"http:path"}, + expectError: true, + }, + { + name: "invalid format - too many parts", + input: []string{"http:path:name:extra"}, + expectError: true, + }, + { + name: "mixed valid and invalid", + input: []string{"tcp:valid:data", "invalid"}, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var s struct { + Items []customUnmarshalParamType `uri:"items"` + } + err := mappingByPtr(&s, formSource{"items": tt.input}, "uri") + + if tt.expectError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Len(t, s.Items, tt.expectLen) + if tt.validate != nil { + tt.validate(t, s.Items) + } + } + }) + } +} + +func TestMappingSliceOfCustomBindUnmarshalerElementsForm(t *testing.T) { + tests := []struct { + name string + input []string + expectError bool + expectLen int + validate func(t *testing.T, items []customUnmarshalParamType) + }{ + { + name: "multiple valid elements", + input: []string{"tcp:socket1:server", "udp:socket2:client"}, + expectLen: 2, + validate: func(t *testing.T, items []customUnmarshalParamType) { + assert.Equal(t, "tcp", items[0].Protocol) + assert.Equal(t, "socket1", items[0].Path) + assert.Equal(t, "server", items[0].Name) + assert.Equal(t, "udp", items[1].Protocol) + assert.Equal(t, "socket2", items[1].Path) + assert.Equal(t, "client", items[1].Name) + }, + }, + { + name: "single element", + input: []string{"grpc:api:service"}, + expectLen: 1, + validate: func(t *testing.T, items []customUnmarshalParamType) { + assert.Equal(t, "grpc", items[0].Protocol) + assert.Equal(t, "api", items[0].Path) + assert.Equal(t, "service", items[0].Name) + }, + }, + { + name: "invalid format - empty string", + input: []string{""}, + expectError: true, + }, + { + name: "invalid format - insufficient parts", + input: []string{"tcp:socket"}, + expectError: true, + }, + { + name: "large slice", + input: []string{"tcp:s1:n1", "udp:s2:n2", "http:s3:n3", "grpc:s4:n4", "ws:s5:n5"}, + expectLen: 5, + validate: func(t *testing.T, items []customUnmarshalParamType) { + assert.Equal(t, "tcp", items[0].Protocol) + assert.Equal(t, "ws", items[4].Protocol) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var s struct { + Items []customUnmarshalParamType `form:"items"` + } + err := mappingByPtr(&s, formSource{"items": tt.input}, "form") + + if tt.expectError { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Len(t, s.Items, tt.expectLen) + if tt.validate != nil { + tt.validate(t, s.Items) + } + } + }) + } +} + +func TestMappingArrayOfCustomBindUnmarshalerElementsUri(t *testing.T) { + tests := []struct { + name string + input []string + expectError bool + validate func(t *testing.T, items [2]customUnmarshalParamType) + }{ + { + name: "exact array size", + input: []string{"grpc:service1:auth", "rest:service2:data"}, + validate: func(t *testing.T, items [2]customUnmarshalParamType) { + assert.Equal(t, "grpc", items[0].Protocol) + assert.Equal(t, "service1", items[0].Path) + assert.Equal(t, "auth", items[0].Name) + assert.Equal(t, "rest", items[1].Protocol) + assert.Equal(t, "service2", items[1].Path) + assert.Equal(t, "data", items[1].Name) + }, + }, + { + name: "insufficient elements for array", + input: []string{"tcp:socket:server"}, + expectError: true, + }, + { + name: "invalid format in first element", + input: []string{"invalid", "tcp:valid:data"}, + expectError: true, + }, + { + name: "invalid format in second element", + input: []string{"tcp:valid:data", "invalid"}, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var s struct { + Items [2]customUnmarshalParamType `uri:"items"` + } + err := mappingByPtr(&s, formSource{"items": tt.input}, "uri") + + if tt.expectError { + assert.Error(t, err) + } else { + require.NoError(t, err) + if tt.validate != nil { + tt.validate(t, s.Items) + } + } + }) + } +} + +func TestMappingArrayOfCustomBindUnmarshalerElementsForm(t *testing.T) { + tests := []struct { + name string + input []string + expectError bool + validate func(t *testing.T, items [2]customUnmarshalParamType) + }{ + { + name: "exact array size", + input: []string{"ws:chat:room1", "wss:chat:room2"}, + validate: func(t *testing.T, items [2]customUnmarshalParamType) { + assert.Equal(t, "ws", items[0].Protocol) + assert.Equal(t, "chat", items[0].Path) + assert.Equal(t, "room1", items[0].Name) + assert.Equal(t, "wss", items[1].Protocol) + assert.Equal(t, "chat", items[1].Path) + assert.Equal(t, "room2", items[1].Name) + }, + }, + { + name: "insufficient elements for array", + input: []string{"http:api:v1"}, + expectError: true, + }, + { + name: "invalid format stops processing", + input: []string{"tcp:valid:data", "invalid:format"}, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var s struct { + Items [2]customUnmarshalParamType `form:"items"` + } + err := mappingByPtr(&s, formSource{"items": tt.input}, "form") + + if tt.expectError { + assert.Error(t, err) + } else { + require.NoError(t, err) + if tt.validate != nil { + tt.validate(t, s.Items) + } + } + }) + } +}