From fc480020fd65dbbe34e58aed937cbfc5964b6fe4 Mon Sep 17 00:00:00 2001 From: jremy Date: Tue, 9 Apr 2024 15:17:00 +0200 Subject: [PATCH 1/5] test(core):add test for reflect t# On branch test/add-test-for-reflect --- internal/core/arg_file_content.go | 2 +- internal/core/reflect.go | 14 +- internal/core/reflect_test.go | 694 ++++++++++++++++++++++++++++++ internal/core/validate.go | 6 +- 4 files changed, 705 insertions(+), 11 deletions(-) create mode 100644 internal/core/reflect_test.go diff --git a/internal/core/arg_file_content.go b/internal/core/arg_file_content.go index 21a2a248b8..76385001de 100644 --- a/internal/core/arg_file_content.go +++ b/internal/core/arg_file_content.go @@ -19,7 +19,7 @@ func loadArgsFileContent(cmd *Command, cmdArgs interface{}) error { } fieldName := strcase.ToPublicGoName(argSpec.Name) - fieldValues, err := getValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) + fieldValues, err := GetValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) if err != nil { continue } diff --git a/internal/core/reflect.go b/internal/core/reflect.go index 2180476fbc..f9302c44f6 100644 --- a/internal/core/reflect.go +++ b/internal/core/reflect.go @@ -34,21 +34,21 @@ func newObjectWithForcedJSONTags(t reflect.Type) interface{} { return reflect.New(reflect.StructOf(structFieldsCopy)).Interface() } -// getValuesForFieldByName recursively search for fields in a cmdArgs' value and returns its values if they exist. +// GetValuesForFieldByName recursively search for fields in a cmdArgs' value and returns its values if they exist. // The search is based on the name of the field. -func getValuesForFieldByName(value reflect.Value, parts []string) (values []reflect.Value, err error) { +func GetValuesForFieldByName(value reflect.Value, parts []string) (values []reflect.Value, err error) { if len(parts) == 0 { return []reflect.Value{value}, nil } switch value.Kind() { case reflect.Ptr: - return getValuesForFieldByName(value.Elem(), parts) + return GetValuesForFieldByName(value.Elem(), parts) case reflect.Slice: values := []reflect.Value(nil) for i := 0; i < value.Len(); i++ { - newValues, err := getValuesForFieldByName(value.Index(i), parts[1:]) + newValues, err := GetValuesForFieldByName(value.Index(i), parts[1:]) if err != nil { return nil, err } @@ -70,7 +70,7 @@ func getValuesForFieldByName(value reflect.Value, parts []string) (values []refl for _, mapKey := range mapKeys { mapValue := value.MapIndex(mapKey) - newValues, err := getValuesForFieldByName(mapValue, parts[1:]) + newValues, err := GetValuesForFieldByName(mapValue, parts[1:]) if err != nil { return nil, err } @@ -93,12 +93,12 @@ func getValuesForFieldByName(value reflect.Value, parts []string) (values []refl fieldName := strcase.ToPublicGoName(parts[0]) if fieldIndex, exist := fieldIndexByName[fieldName]; exist { - return getValuesForFieldByName(value.Field(fieldIndex), parts[1:]) + return GetValuesForFieldByName(value.Field(fieldIndex), parts[1:]) } // If it does not exist we try to find it in nested anonymous field for _, fieldIndex := range anonymousFieldIndexes { - newValues, err := getValuesForFieldByName(value.Field(fieldIndex), parts) + newValues, err := GetValuesForFieldByName(value.Field(fieldIndex), parts) if err == nil { return newValues, nil } diff --git a/internal/core/reflect_test.go b/internal/core/reflect_test.go new file mode 100644 index 0000000000..de9aa66b63 --- /dev/null +++ b/internal/core/reflect_test.go @@ -0,0 +1,694 @@ +package core_test + +import ( + "net" + "reflect" + "strings" + "testing" + + "github.com/alecthomas/assert" + "github.com/scaleway/scaleway-cli/v2/internal/core" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +type RequestEmbedding struct { + EmbeddingField1 string + EmbeddingField2 int +} + +type CreateRequest struct { + *RequestEmbedding + CreateField1 string + CreateField2 int +} + +type ExtendedRequest struct { + *CreateRequest + ExtendedField1 string + ExtendedField2 int +} + +type ArrowRequest struct { + ServiceIP *scw.IPNet +} + +type SpecialRequest struct { + *RequestEmbedding + TabRequest []*ArrowRequest +} + +func Test_getValuesForFieldByName(t *testing.T) { + type TestCase struct { + cmdArgs interface{} + fieldName string + expectedError string + expectedValues []reflect.Value + } + + tests := []struct { + name string + testCase TestCase + testFunc func(*testing.T, TestCase) + }{ + { + name: "Simple test", + testCase: TestCase{ + cmdArgs: &ExtendedRequest{ + CreateRequest: &CreateRequest{ + RequestEmbedding: &RequestEmbedding{ + EmbeddingField1: "value1", + EmbeddingField2: 2, + }, + CreateField1: "value3", + CreateField2: 4, + }, + ExtendedField1: "value5", + ExtendedField2: 6, + }, + fieldName: "EmbeddingField1", + expectedError: "", + expectedValues: []reflect.Value{reflect.ValueOf("value1")}, + }, + testFunc: func(t *testing.T, tc TestCase) { + values, err := core.GetValuesForFieldByName(reflect.ValueOf(tc.cmdArgs), strings.Split(tc.fieldName, ".")) + if err != nil { + assert.Equal(t, tc.expectedError, err.Error()) + } else { + if tc.expectedValues != nil && !reflect.DeepEqual(tc.expectedValues[0].Interface(), values[0].Interface()) { + t.Errorf("Expected %v, got %v", tc.expectedValues[0].Interface(), values[0].Interface()) + } + } + }, + }, + { + name: "Error test", + testCase: TestCase{ + cmdArgs: &ExtendedRequest{ + CreateRequest: &CreateRequest{ + RequestEmbedding: &RequestEmbedding{ + EmbeddingField1: "value1", + EmbeddingField2: 2, + }, + CreateField1: "value3", + CreateField2: 4, + }, + ExtendedField1: "value5", + ExtendedField2: 6, + }, + fieldName: "NotExist", + expectedError: "field NotExist does not exist for ExtendedRequest", + expectedValues: []reflect.Value{reflect.ValueOf("value1")}, + }, + testFunc: func(t *testing.T, tc TestCase) { + values, err := core.GetValuesForFieldByName(reflect.ValueOf(tc.cmdArgs), strings.Split(tc.fieldName, ".")) + if err != nil { + assert.Equal(t, tc.expectedError, err.Error()) + } else { + if tc.expectedValues != nil && !reflect.DeepEqual(tc.expectedValues[0].Interface(), values[0].Interface()) { + t.Errorf("Expected %v, got %v", tc.expectedValues[0].Interface(), values[0].Interface()) + } + } + + }, + }, + { + name: "Special test", + testCase: TestCase{ + cmdArgs: &SpecialRequest{ + RequestEmbedding: &RequestEmbedding{ + EmbeddingField1: "value1", + EmbeddingField2: 2, + }, + TabRequest: []*ArrowRequest{ + { + ServiceIP: &scw.IPNet{ + IPNet: net.IPNet{ + IP: net.ParseIP("192.0.2.1"), + Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + }, + }, + }, + { + ServiceIP: &scw.IPNet{ + IPNet: net.IPNet{ + IP: net.ParseIP("198.51.100.1"), + Mask: net.CIDRMask(24, 32), // Un autre exemple avec un masque de sous-réseau /24 + }, + }, + }, + }, + }, + fieldName: "tabRequest.{index}.serviceIP", + expectedError: "", + expectedValues: []reflect.Value{reflect.ValueOf(nil)}, + }, + testFunc: func(t *testing.T, tc TestCase) { + values, err := core.GetValuesForFieldByName(reflect.ValueOf(tc.cmdArgs), strings.Split(tc.fieldName, ".")) + if err != nil { + assert.Equal(t, nil, err.Error()) + } else { + if tc.expectedValues != nil && !reflect.DeepEqual(tc.expectedValues[0].Interface(), values[0].Interface()) { + t.Errorf("Expected %v, got %v", tc.expectedValues[0].Interface(), values[0].Interface()) + } + } + + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.testFunc(t, tt.testCase) + }) + } +} + +// +//func TestValidateRequiredOneOfGroups(t *testing.T) { +// tests := []struct { +// name string +// setupManager func() *core.OneOfGroupManager +// rawArgs args.RawArgs +// expectedError string +// ArgsType interface{} +// }{ +// { +// name: "Required group satisfied with first argument", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{"group1": {"a", "b"}}, +// RequiredGroups: map[string]bool{"group1": true}, +// } +// }, +// rawArgs: []string{"a=true"}, +// ArgsType: struct { +// A bool +// B bool +// }{}, +// expectedError: "", +// }, +// { +// name: "Required group satisfied with second argument", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{"group1": {"a", "b"}}, +// RequiredGroups: map[string]bool{"group1": true}, +// } +// }, +// rawArgs: []string{"b=true"}, +// ArgsType: struct { +// A bool +// B bool +// }{}, +// expectedError: "", +// }, +// { +// name: "Required group not satisfied", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{"group1": {"a", "b"}}, +// RequiredGroups: map[string]bool{"group1": true}, +// } +// }, +// rawArgs: []string{"c=true"}, +// ArgsType: struct { +// A bool +// B bool +// C bool +// }{}, +// expectedError: "at least one argument from the 'group1' group is required", +// }, +// } +// +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// manager := tt.setupManager() +// err := manager.ValidateRequiredOneOfGroups(tt.rawArgs, tt.ArgsType) +// +// if tt.expectedError == "" { +// assert.NoError(t, err, "Expected no error, got %v", err) +// } else { +// assert.EqualError(t, err, tt.expectedError, fmt.Sprintf("Expected error message '%s', got '%v'", tt.expectedError, err)) +// } +// }) +// } +//} +// +//func TestValidateUniqueOneOfGroups(t *testing.T) { +// tests := []struct { +// name string +// setupManager func() *core.OneOfGroupManager +// rawArgs args.RawArgs +// expectedError string +// ArgsType interface{} +// }{ +// { +// name: "Required group satisfied with first argument", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{"group1": {"a", "b"}}, +// } +// }, +// rawArgs: []string{"A=true"}, +// ArgsType: struct { +// A bool +// B bool +// }{}, +// expectedError: "", +// }, +// { +// name: "No arguments passed", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{"group1": {"a", "b"}}, +// } +// }, +// rawArgs: []string{}, +// ArgsType: struct { +// A bool +// B bool +// }{}, +// expectedError: "", +// }, +// { +// name: "Multiple groups, all satisfied", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{ +// "group1": {"a", "b"}, +// "group2": {"c", "d"}, +// }, +// } +// }, +// rawArgs: []string{"a=true", "c=true"}, +// ArgsType: struct { +// A string +// B string +// C string +// D string +// }{}, +// expectedError: "", +// }, +// { +// name: "Multiple groups, one satisfied", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{ +// "group1": {"a", "b"}, +// "group2": {"c", "d"}, +// }, +// } +// }, +// rawArgs: []string{"a=true"}, +// ArgsType: struct { +// A string +// B string +// C string +// D string +// }{}, +// expectedError: "", +// }, +// { +// name: "Multiple groups, not exclusive argument for groups 2", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{ +// "group1": {"a", "b"}, +// "group2": {"c", "d"}, +// }, +// } +// }, +// rawArgs: []string{"a=true", "c=true", "d=true"}, +// ArgsType: struct { +// A string +// B string +// C string +// D string +// }{}, +// expectedError: "arguments 'c' and 'd' are mutually exclusive", +// }, +// { +// name: "Multiple groups, not exclusive argument for groups 1", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{ +// "group1": {"a", "b"}, +// "group2": {"c", "d"}, +// }, +// } +// }, +// rawArgs: []string{"a=true", "b=true", "c=true"}, +// ArgsType: struct { +// A string +// B string +// C string +// D string +// }{}, +// expectedError: "arguments 'a' and 'b' are mutually exclusive", +// }, +// { +// name: "One group, not exclusive argument for groups 1", +// setupManager: func() *core.OneOfGroupManager { +// return &core.OneOfGroupManager{ +// Groups: map[string][]string{ +// "group1": {"a", "b", "c", "d"}, +// }, +// } +// }, +// rawArgs: []string{"a=true", "d=true"}, +// ArgsType: struct { +// A string +// B string +// C string +// D string +// }{}, +// expectedError: "arguments 'a' and 'd' are mutually exclusive", +// }, +// } +// +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// manager := tt.setupManager() +// err := manager.ValidateUniqueOneOfGroups(tt.rawArgs, tt.ArgsType) +// if tt.expectedError == "" { +// assert.NoError(t, err, "Expected no error, got %v", err) +// } else { +// assert.EqualError(t, err, tt.expectedError, fmt.Sprintf("Expected error message '%s', got '%v'", tt.expectedError, err)) +// } +// }) +// } +//} +// +//func Test_ValidateOneOf(t *testing.T) { +// t.Run("Simple one-of validation check", core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(args.RawArgs{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "a", +// OneOfGroup: "groups1", +// }, +// { +// Name: "b", +// OneOfGroup: "groups1", +// }, +// }, +// }), +// Cmd: "scw oneof a=yo", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(0), +// ), +// })) +// t.Run("Required argument group check passes", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(args.RawArgs{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "a", +// OneOfGroup: "group1", +// Required: true, +// }, +// { +// Name: "b", +// OneOfGroup: "group1", +// Required: true, +// }, +// }, +// }), +// Cmd: "scw oneof b=yo", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(0), +// ), +// })(t) +// }) +// +// t.Run("Fail when required group is missing", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(args.RawArgs{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "a", +// OneOfGroup: "group1", +// Required: true, +// }, +// { +// Name: "b", +// OneOfGroup: "group1", +// Required: true, +// }, +// }, +// }), +// Cmd: "scw oneof c=yo", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(1), +// core.TestCheckError(fmt.Errorf("at least one argument from the 'group1' group is required")), +// ), +// })(t) +// }) +// +// t.Run("Check for mutual exclusivity in arguments", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// A string +// B string +// }{}), AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "a", +// OneOfGroup: "group1", +// }, +// { +// Name: "b", +// OneOfGroup: "group1", +// }, +// }, +// }), +// Cmd: "scw oneof a=yo b=no", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(1), +// core.TestCheckError(fmt.Errorf("arguments 'a' and 'b' are mutually exclusive")), +// ), +// })(t) +// }) +// +// t.Run("Three arguments' mutual exclusivity test", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// A string +// B string +// C string +// }{}), AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "a", +// OneOfGroup: "group1", +// }, +// { +// Name: "b", +// OneOfGroup: "group1", +// }, +// { +// Name: "c", +// OneOfGroup: "group1", +// }, +// }, +// }), +// Cmd: "scw oneof a=yo c=no", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(1), +// core.TestCheckError(fmt.Errorf("arguments 'a' and 'c' are mutually exclusive")), +// ), +// })(t) +// }) +// +// t.Run("Indexed arguments' exclusivity check", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// SSHKey []string +// AllSSHKeys bool +// }{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "ssh-key.{index}", +// OneOfGroup: "ssh", +// Required: true, +// }, +// { +// Name: "all-ssh-keys", +// OneOfGroup: "ssh", +// Required: true, +// }, +// }, +// }), +// Cmd: "scw oneof all-ssh-keys=true ssh-key.0=11111111-1111-1111-1111-111111111111", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(1), +// core.TestCheckError(fmt.Errorf("arguments 'ssh-key.{index}' and 'all-ssh-keys' are mutually exclusive")), +// ), +// })(t) +// }) +// +// t.Run("Passing an indexed argument test", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// SSHKey []string +// AllSSHKeys bool +// }{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "ssh-key.{index}", +// OneOfGroup: "ssh", +// }, +// { +// Name: "all-ssh-keys", +// OneOfGroup: "ssh", +// }, +// }, +// }), +// Cmd: "scw oneof ssh-key.0=11111111-1111-1111-1111-111111111111", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(0), +// ), +// })(t) +// }) +// +// t.Run("Required indexed argument satisfies condition", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// SSHKey []string +// AllSSHKeys bool +// }{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "ssh-key.{index}", +// OneOfGroup: "ssh", +// Required: true, +// }, +// { +// Name: "all-ssh-keys", +// OneOfGroup: "ssh", +// Required: true, +// }, +// }, +// }), +// Cmd: "scw oneof ssh-key.0=11111111-1111-1111-1111-111111111111", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(0), +// ), +// })(t) +// }) +// +// t.Run("Exclusive all SSH keys and indexed key test", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// SSHKey []string +// AllSSHKeys bool +// }{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "ssh-key.{index}", +// OneOfGroup: "ssh", +// Required: true, +// }, +// { +// Name: "all-ssh-keys", +// OneOfGroup: "ssh", +// Required: true, +// }, +// }, +// }), +// Cmd: "scw oneof all-ssh-keys=true", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(0), +// ), +// })(t) +// }) +// +// t.Run("Ungrouped argument with unsatisfied group fails", func(t *testing.T) { +// core.Test(&core.TestConfig{ +// Commands: core.NewCommands(&core.Command{ +// Namespace: "oneof", +// ArgsType: reflect.TypeOf(struct { +// SSHKey []string +// AllSSHKeys bool +// Arg bool +// }{}), +// AllowAnonymousClient: true, +// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { +// return &core.SuccessResult{}, nil +// }, +// ArgSpecs: core.ArgSpecs{ +// { +// Name: "ssh-key.{index}", +// OneOfGroup: "ssh", +// Required: true, +// }, +// { +// Name: "all-ssh-keys", +// OneOfGroup: "ssh", +// Required: true, +// }, +// { +// Name: "arg", +// }, +// }, +// }), +// Cmd: "scw oneof arg=true", +// Check: core.TestCheckCombine( +// core.TestCheckExitCode(1), +// core.TestCheckError(fmt.Errorf("at least one argument from the 'ssh' group is required")), +// ), +// })(t) +// }) +//} diff --git a/internal/core/validate.go b/internal/core/validate.go index b6c56a78ca..5b98a95284 100644 --- a/internal/core/validate.go +++ b/internal/core/validate.go @@ -45,7 +45,7 @@ func DefaultCommandValidateFunc() CommandValidateFunc { func validateArgValues(cmd *Command, cmdArgs interface{}) error { for _, argSpec := range cmd.ArgSpecs { fieldName := strcase.ToPublicGoName(argSpec.Name) - fieldValues, err := getValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) + fieldValues, err := GetValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) if err != nil { logger.Infof("could not validate arg value for '%v': invalid fieldName: %v: %v", argSpec.Name, fieldName, err.Error()) continue @@ -75,7 +75,7 @@ func validateRequiredArgs(cmd *Command, cmdArgs interface{}, rawArgs args.RawArg } fieldName := strcase.ToPublicGoName(arg.Name) - fieldValues, err := getValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) + fieldValues, err := GetValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) if err != nil { validationErr := fmt.Errorf("could not validate arg value for '%v': invalid field name '%v': %v", arg.Name, fieldName, err.Error()) if !arg.Required { @@ -117,7 +117,7 @@ func validateDeprecated(ctx context.Context, cmd *Command, cmdArgs interface{}, deprecatedArgs := cmd.ArgSpecs.GetDeprecated(true) for _, arg := range deprecatedArgs { fieldName := strcase.ToPublicGoName(arg.Name) - fieldValues, err := getValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) + fieldValues, err := GetValuesForFieldByName(reflect.ValueOf(cmdArgs), strings.Split(fieldName, ".")) if err != nil { validationErr := fmt.Errorf("could not validate arg value for '%v': invalid field name '%v': %v", arg.Name, fieldName, err.Error()) if !arg.Required { From d7d117da144e87846caba68204b9acba19059971 Mon Sep 17 00:00:00 2001 From: jremy Date: Wed, 10 Apr 2024 17:04:59 +0200 Subject: [PATCH 2/5] test(core):add test new struct for special reflect --- internal/core/reflect_test.go | 47 +++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/internal/core/reflect_test.go b/internal/core/reflect_test.go index de9aa66b63..3b96e913ee 100644 --- a/internal/core/reflect_test.go +++ b/internal/core/reflect_test.go @@ -29,7 +29,7 @@ type ExtendedRequest struct { } type ArrowRequest struct { - ServiceIP *scw.IPNet + *PrivateNetwork } type SpecialRequest struct { @@ -37,6 +37,15 @@ type SpecialRequest struct { TabRequest []*ArrowRequest } +type EndpointSpecPrivateNetwork struct { + PrivateNetworkId string + ServiceIP *scw.IPNet +} + +type PrivateNetwork struct { + *EndpointSpecPrivateNetwork +} + func Test_getValuesForFieldByName(t *testing.T) { type TestCase struct { cmdArgs interface{} @@ -45,6 +54,13 @@ func Test_getValuesForFieldByName(t *testing.T) { expectedValues []reflect.Value } + expectedServiceIP := &scw.IPNet{ + IPNet: net.IPNet{ + IP: net.ParseIP("192.0.2.1"), + Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + }, + } + tests := []struct { name string testCase TestCase @@ -112,6 +128,7 @@ func Test_getValuesForFieldByName(t *testing.T) { }, }, { + name: "Special test", testCase: TestCase{ cmdArgs: &SpecialRequest{ @@ -121,26 +138,34 @@ func Test_getValuesForFieldByName(t *testing.T) { }, TabRequest: []*ArrowRequest{ { - ServiceIP: &scw.IPNet{ - IPNet: net.IPNet{ - IP: net.ParseIP("192.0.2.1"), - Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + PrivateNetwork: &PrivateNetwork{ + EndpointSpecPrivateNetwork: &EndpointSpecPrivateNetwork{ + ServiceIP: &scw.IPNet{ + IPNet: net.IPNet{ + IP: net.ParseIP("192.0.2.1"), + Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + }, + }, }, }, }, { - ServiceIP: &scw.IPNet{ - IPNet: net.IPNet{ - IP: net.ParseIP("198.51.100.1"), - Mask: net.CIDRMask(24, 32), // Un autre exemple avec un masque de sous-réseau /24 + PrivateNetwork: &PrivateNetwork{ + EndpointSpecPrivateNetwork: &EndpointSpecPrivateNetwork{ + ServiceIP: &scw.IPNet{ + IPNet: net.IPNet{ + IP: net.ParseIP("198.51.100.1"), + Mask: net.CIDRMask(24, 32), // Un autre exemple avec un masque de sous-réseau /24 + }, + }, }, }, }, }, }, - fieldName: "tabRequest.{index}.serviceIP", + fieldName: "tabRequest.{index}.PrivateNetwork.EndpointSpecPrivateNetwork.ServiceIP", expectedError: "", - expectedValues: []reflect.Value{reflect.ValueOf(nil)}, + expectedValues: []reflect.Value{reflect.ValueOf(expectedServiceIP)}, }, testFunc: func(t *testing.T, tc TestCase) { values, err := core.GetValuesForFieldByName(reflect.ValueOf(tc.cmdArgs), strings.Split(tc.fieldName, ".")) From 365784978a51a00b9e49c4d58c6087e45ddf0124 Mon Sep 17 00:00:00 2001 From: jremy Date: Thu, 11 Apr 2024 14:25:45 +0200 Subject: [PATCH 3/5] test(core):add test new struct for special reflect --- internal/core/reflect.go | 2 - internal/core/reflect_test.go | 532 +--------------------------------- 2 files changed, 1 insertion(+), 533 deletions(-) diff --git a/internal/core/reflect.go b/internal/core/reflect.go index f9302c44f6..2a39b4bd33 100644 --- a/internal/core/reflect.go +++ b/internal/core/reflect.go @@ -40,7 +40,6 @@ func GetValuesForFieldByName(value reflect.Value, parts []string) (values []refl if len(parts) == 0 { return []reflect.Value{value}, nil } - switch value.Kind() { case reflect.Ptr: return GetValuesForFieldByName(value.Elem(), parts) @@ -106,6 +105,5 @@ func GetValuesForFieldByName(value reflect.Value, parts []string) (values []refl return nil, fmt.Errorf("field %v does not exist for %v", fieldName, value.Type().Name()) } - return nil, fmt.Errorf("case is not handled") } diff --git a/internal/core/reflect_test.go b/internal/core/reflect_test.go index 3b96e913ee..30af4dec78 100644 --- a/internal/core/reflect_test.go +++ b/internal/core/reflect_test.go @@ -143,7 +143,7 @@ func Test_getValuesForFieldByName(t *testing.T) { ServiceIP: &scw.IPNet{ IPNet: net.IPNet{ IP: net.ParseIP("192.0.2.1"), - Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + Mask: net.CIDRMask(24, 32), }, }, }, @@ -187,533 +187,3 @@ func Test_getValuesForFieldByName(t *testing.T) { }) } } - -// -//func TestValidateRequiredOneOfGroups(t *testing.T) { -// tests := []struct { -// name string -// setupManager func() *core.OneOfGroupManager -// rawArgs args.RawArgs -// expectedError string -// ArgsType interface{} -// }{ -// { -// name: "Required group satisfied with first argument", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{"group1": {"a", "b"}}, -// RequiredGroups: map[string]bool{"group1": true}, -// } -// }, -// rawArgs: []string{"a=true"}, -// ArgsType: struct { -// A bool -// B bool -// }{}, -// expectedError: "", -// }, -// { -// name: "Required group satisfied with second argument", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{"group1": {"a", "b"}}, -// RequiredGroups: map[string]bool{"group1": true}, -// } -// }, -// rawArgs: []string{"b=true"}, -// ArgsType: struct { -// A bool -// B bool -// }{}, -// expectedError: "", -// }, -// { -// name: "Required group not satisfied", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{"group1": {"a", "b"}}, -// RequiredGroups: map[string]bool{"group1": true}, -// } -// }, -// rawArgs: []string{"c=true"}, -// ArgsType: struct { -// A bool -// B bool -// C bool -// }{}, -// expectedError: "at least one argument from the 'group1' group is required", -// }, -// } -// -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// manager := tt.setupManager() -// err := manager.ValidateRequiredOneOfGroups(tt.rawArgs, tt.ArgsType) -// -// if tt.expectedError == "" { -// assert.NoError(t, err, "Expected no error, got %v", err) -// } else { -// assert.EqualError(t, err, tt.expectedError, fmt.Sprintf("Expected error message '%s', got '%v'", tt.expectedError, err)) -// } -// }) -// } -//} -// -//func TestValidateUniqueOneOfGroups(t *testing.T) { -// tests := []struct { -// name string -// setupManager func() *core.OneOfGroupManager -// rawArgs args.RawArgs -// expectedError string -// ArgsType interface{} -// }{ -// { -// name: "Required group satisfied with first argument", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{"group1": {"a", "b"}}, -// } -// }, -// rawArgs: []string{"A=true"}, -// ArgsType: struct { -// A bool -// B bool -// }{}, -// expectedError: "", -// }, -// { -// name: "No arguments passed", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{"group1": {"a", "b"}}, -// } -// }, -// rawArgs: []string{}, -// ArgsType: struct { -// A bool -// B bool -// }{}, -// expectedError: "", -// }, -// { -// name: "Multiple groups, all satisfied", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{ -// "group1": {"a", "b"}, -// "group2": {"c", "d"}, -// }, -// } -// }, -// rawArgs: []string{"a=true", "c=true"}, -// ArgsType: struct { -// A string -// B string -// C string -// D string -// }{}, -// expectedError: "", -// }, -// { -// name: "Multiple groups, one satisfied", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{ -// "group1": {"a", "b"}, -// "group2": {"c", "d"}, -// }, -// } -// }, -// rawArgs: []string{"a=true"}, -// ArgsType: struct { -// A string -// B string -// C string -// D string -// }{}, -// expectedError: "", -// }, -// { -// name: "Multiple groups, not exclusive argument for groups 2", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{ -// "group1": {"a", "b"}, -// "group2": {"c", "d"}, -// }, -// } -// }, -// rawArgs: []string{"a=true", "c=true", "d=true"}, -// ArgsType: struct { -// A string -// B string -// C string -// D string -// }{}, -// expectedError: "arguments 'c' and 'd' are mutually exclusive", -// }, -// { -// name: "Multiple groups, not exclusive argument for groups 1", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{ -// "group1": {"a", "b"}, -// "group2": {"c", "d"}, -// }, -// } -// }, -// rawArgs: []string{"a=true", "b=true", "c=true"}, -// ArgsType: struct { -// A string -// B string -// C string -// D string -// }{}, -// expectedError: "arguments 'a' and 'b' are mutually exclusive", -// }, -// { -// name: "One group, not exclusive argument for groups 1", -// setupManager: func() *core.OneOfGroupManager { -// return &core.OneOfGroupManager{ -// Groups: map[string][]string{ -// "group1": {"a", "b", "c", "d"}, -// }, -// } -// }, -// rawArgs: []string{"a=true", "d=true"}, -// ArgsType: struct { -// A string -// B string -// C string -// D string -// }{}, -// expectedError: "arguments 'a' and 'd' are mutually exclusive", -// }, -// } -// -// for _, tt := range tests { -// t.Run(tt.name, func(t *testing.T) { -// manager := tt.setupManager() -// err := manager.ValidateUniqueOneOfGroups(tt.rawArgs, tt.ArgsType) -// if tt.expectedError == "" { -// assert.NoError(t, err, "Expected no error, got %v", err) -// } else { -// assert.EqualError(t, err, tt.expectedError, fmt.Sprintf("Expected error message '%s', got '%v'", tt.expectedError, err)) -// } -// }) -// } -//} -// -//func Test_ValidateOneOf(t *testing.T) { -// t.Run("Simple one-of validation check", core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(args.RawArgs{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "a", -// OneOfGroup: "groups1", -// }, -// { -// Name: "b", -// OneOfGroup: "groups1", -// }, -// }, -// }), -// Cmd: "scw oneof a=yo", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(0), -// ), -// })) -// t.Run("Required argument group check passes", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(args.RawArgs{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "a", -// OneOfGroup: "group1", -// Required: true, -// }, -// { -// Name: "b", -// OneOfGroup: "group1", -// Required: true, -// }, -// }, -// }), -// Cmd: "scw oneof b=yo", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(0), -// ), -// })(t) -// }) -// -// t.Run("Fail when required group is missing", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(args.RawArgs{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "a", -// OneOfGroup: "group1", -// Required: true, -// }, -// { -// Name: "b", -// OneOfGroup: "group1", -// Required: true, -// }, -// }, -// }), -// Cmd: "scw oneof c=yo", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(1), -// core.TestCheckError(fmt.Errorf("at least one argument from the 'group1' group is required")), -// ), -// })(t) -// }) -// -// t.Run("Check for mutual exclusivity in arguments", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// A string -// B string -// }{}), AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "a", -// OneOfGroup: "group1", -// }, -// { -// Name: "b", -// OneOfGroup: "group1", -// }, -// }, -// }), -// Cmd: "scw oneof a=yo b=no", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(1), -// core.TestCheckError(fmt.Errorf("arguments 'a' and 'b' are mutually exclusive")), -// ), -// })(t) -// }) -// -// t.Run("Three arguments' mutual exclusivity test", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// A string -// B string -// C string -// }{}), AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "a", -// OneOfGroup: "group1", -// }, -// { -// Name: "b", -// OneOfGroup: "group1", -// }, -// { -// Name: "c", -// OneOfGroup: "group1", -// }, -// }, -// }), -// Cmd: "scw oneof a=yo c=no", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(1), -// core.TestCheckError(fmt.Errorf("arguments 'a' and 'c' are mutually exclusive")), -// ), -// })(t) -// }) -// -// t.Run("Indexed arguments' exclusivity check", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// SSHKey []string -// AllSSHKeys bool -// }{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "ssh-key.{index}", -// OneOfGroup: "ssh", -// Required: true, -// }, -// { -// Name: "all-ssh-keys", -// OneOfGroup: "ssh", -// Required: true, -// }, -// }, -// }), -// Cmd: "scw oneof all-ssh-keys=true ssh-key.0=11111111-1111-1111-1111-111111111111", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(1), -// core.TestCheckError(fmt.Errorf("arguments 'ssh-key.{index}' and 'all-ssh-keys' are mutually exclusive")), -// ), -// })(t) -// }) -// -// t.Run("Passing an indexed argument test", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// SSHKey []string -// AllSSHKeys bool -// }{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "ssh-key.{index}", -// OneOfGroup: "ssh", -// }, -// { -// Name: "all-ssh-keys", -// OneOfGroup: "ssh", -// }, -// }, -// }), -// Cmd: "scw oneof ssh-key.0=11111111-1111-1111-1111-111111111111", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(0), -// ), -// })(t) -// }) -// -// t.Run("Required indexed argument satisfies condition", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// SSHKey []string -// AllSSHKeys bool -// }{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "ssh-key.{index}", -// OneOfGroup: "ssh", -// Required: true, -// }, -// { -// Name: "all-ssh-keys", -// OneOfGroup: "ssh", -// Required: true, -// }, -// }, -// }), -// Cmd: "scw oneof ssh-key.0=11111111-1111-1111-1111-111111111111", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(0), -// ), -// })(t) -// }) -// -// t.Run("Exclusive all SSH keys and indexed key test", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// SSHKey []string -// AllSSHKeys bool -// }{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "ssh-key.{index}", -// OneOfGroup: "ssh", -// Required: true, -// }, -// { -// Name: "all-ssh-keys", -// OneOfGroup: "ssh", -// Required: true, -// }, -// }, -// }), -// Cmd: "scw oneof all-ssh-keys=true", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(0), -// ), -// })(t) -// }) -// -// t.Run("Ungrouped argument with unsatisfied group fails", func(t *testing.T) { -// core.Test(&core.TestConfig{ -// Commands: core.NewCommands(&core.Command{ -// Namespace: "oneof", -// ArgsType: reflect.TypeOf(struct { -// SSHKey []string -// AllSSHKeys bool -// Arg bool -// }{}), -// AllowAnonymousClient: true, -// Run: func(_ context.Context, _ interface{}) (i interface{}, e error) { -// return &core.SuccessResult{}, nil -// }, -// ArgSpecs: core.ArgSpecs{ -// { -// Name: "ssh-key.{index}", -// OneOfGroup: "ssh", -// Required: true, -// }, -// { -// Name: "all-ssh-keys", -// OneOfGroup: "ssh", -// Required: true, -// }, -// { -// Name: "arg", -// }, -// }, -// }), -// Cmd: "scw oneof arg=true", -// Check: core.TestCheckCombine( -// core.TestCheckExitCode(1), -// core.TestCheckError(fmt.Errorf("at least one argument from the 'ssh' group is required")), -// ), -// })(t) -// }) -//} From da6f72e891d1f7386688da9c3c37744d7e9958ea Mon Sep 17 00:00:00 2001 From: Jules Casteran Date: Thu, 11 Apr 2024 15:39:16 +0200 Subject: [PATCH 4/5] fix test and fix GetValuesForFieldByName --- internal/core/reflect.go | 13 +++++++++++-- internal/core/reflect_test.go | 14 ++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/internal/core/reflect.go b/internal/core/reflect.go index 2a39b4bd33..0f5646b4b3 100644 --- a/internal/core/reflect.go +++ b/internal/core/reflect.go @@ -1,6 +1,7 @@ package core import ( + "errors" "fmt" "reflect" "sort" @@ -46,13 +47,21 @@ func GetValuesForFieldByName(value reflect.Value, parts []string) (values []refl case reflect.Slice: values := []reflect.Value(nil) + errs := []error(nil) + for i := 0; i < value.Len(); i++ { newValues, err := GetValuesForFieldByName(value.Index(i), parts[1:]) if err != nil { - return nil, err + errs = append(errs, err) + } else { + values = append(values, newValues...) } - values = append(values, newValues...) } + + if len(values) == 0 && len(errs) != 0 { + return nil, errors.Join(errs...) + } + return values, nil case reflect.Map: diff --git a/internal/core/reflect_test.go b/internal/core/reflect_test.go index 30af4dec78..ca24e9a98f 100644 --- a/internal/core/reflect_test.go +++ b/internal/core/reflect_test.go @@ -29,7 +29,7 @@ type ExtendedRequest struct { } type ArrowRequest struct { - *PrivateNetwork + PrivateNetwork *PrivateNetwork } type SpecialRequest struct { @@ -44,6 +44,7 @@ type EndpointSpecPrivateNetwork struct { type PrivateNetwork struct { *EndpointSpecPrivateNetwork + OtherValue string } func Test_getValuesForFieldByName(t *testing.T) { @@ -151,19 +152,12 @@ func Test_getValuesForFieldByName(t *testing.T) { }, { PrivateNetwork: &PrivateNetwork{ - EndpointSpecPrivateNetwork: &EndpointSpecPrivateNetwork{ - ServiceIP: &scw.IPNet{ - IPNet: net.IPNet{ - IP: net.ParseIP("198.51.100.1"), - Mask: net.CIDRMask(24, 32), // Un autre exemple avec un masque de sous-réseau /24 - }, - }, - }, + OtherValue: "hello", }, }, }, }, - fieldName: "tabRequest.{index}.PrivateNetwork.EndpointSpecPrivateNetwork.ServiceIP", + fieldName: "tabRequest.{index}.privateNetwork.serviceIP", expectedError: "", expectedValues: []reflect.Value{reflect.ValueOf(expectedServiceIP)}, }, From ae3e6b71778c6bf2a42c17fa316588ebac540713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jules=20Cast=C3=A9ran?= Date: Thu, 11 Apr 2024 15:45:14 +0200 Subject: [PATCH 5/5] fix linter --- internal/core/reflect_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/core/reflect_test.go b/internal/core/reflect_test.go index ca24e9a98f..288d622f12 100644 --- a/internal/core/reflect_test.go +++ b/internal/core/reflect_test.go @@ -38,7 +38,7 @@ type SpecialRequest struct { } type EndpointSpecPrivateNetwork struct { - PrivateNetworkId string + PrivateNetworkID string ServiceIP *scw.IPNet } @@ -58,7 +58,7 @@ func Test_getValuesForFieldByName(t *testing.T) { expectedServiceIP := &scw.IPNet{ IPNet: net.IPNet{ IP: net.ParseIP("192.0.2.1"), - Mask: net.CIDRMask(24, 32), // Exemple pour un masque de sous-réseau /24 + Mask: net.CIDRMask(24, 32), }, } @@ -125,7 +125,6 @@ func Test_getValuesForFieldByName(t *testing.T) { t.Errorf("Expected %v, got %v", tc.expectedValues[0].Interface(), values[0].Interface()) } } - }, }, { @@ -170,7 +169,6 @@ func Test_getValuesForFieldByName(t *testing.T) { t.Errorf("Expected %v, got %v", tc.expectedValues[0].Interface(), values[0].Interface()) } } - }, }, }