Skip to content

Commit b6575b0

Browse files
scaleway-botjremy42
authored andcommitted
feat(core): fix lint (scaleway#3730)
feat(llm_inference): activate cli (scaleway#3729) docs: update developers website url (scaleway#3733) feat(llm-inference): add support llm-inference cli (scaleway#3731) chore: enable update for github actions in dependabot (scaleway#3734) Co-authored-by: Mia-Cross <[email protected]> feat(llm_inference): change more cli fields to positional (scaleway#3732) Co-authored-by: Jules Casteran <[email protected]> chore(deps): bump goreleaser/goreleaser-action from 4 to 5 (scaleway#3735) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore(deps): bump gaurav-nelson/github-action-markdown-link-check from 1.0.13 to 1.0.15 (scaleway#3736) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> chore(deps): bump github/codeql-action from 2 to 3 (scaleway#3737) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore(deps): bump actions/setup-go from 3 to 5 (scaleway#3738) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore(deps): bump golangci/golangci-lint-action from 3 to 4 (scaleway#3739) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore: add support for docker in dependabot (scaleway#3741) chore(deps): bump alpine from 3.16 to 3.19 (scaleway#3742) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> chore(deps): bump pnpm/action-setup from 2 to 3 (scaleway#3743) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore(deps): bump actions/checkout from 3 to 4 (scaleway#3744) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> chore(deps): bump codecov/codecov-action from 2 to 4 (scaleway#3745) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mia-Cross <[email protected]> feat(core):add test end to end feat(core):fix lint
1 parent aaa595c commit b6575b0

File tree

2 files changed

+283
-10
lines changed

2 files changed

+283
-10
lines changed

internal/core/validate.go

+30-8
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ type CommandValidateFunc func(ctx context.Context, cmd *Command, cmdArgs interfa
2121
type ArgSpecValidateFunc func(argSpec *ArgSpec, value interface{}) error
2222

2323
type OneOfGroupManager struct {
24-
Groups map[string][]string // Contient les noms des arguments pour chaque groupe
25-
RequiredGroups map[string]bool // Indique si un groupe est requis
24+
Groups map[string][]string
25+
RequiredGroups map[string]bool
2626
}
2727

2828
// DefaultCommandValidateFunc is the default validation function for commands.
@@ -74,9 +74,6 @@ func validateArgValues(cmd *Command, cmdArgs interface{}) error {
7474
// Returns nil otherwise.
7575
// TODO refactor this method which uses a mix of reflect and string arrays
7676
func validateRequiredArgs(cmd *Command, cmdArgs interface{}, rawArgs args.RawArgs) error {
77-
78-
oneOfManager := NewOneOfGroupManager(cmd)
79-
8077
for _, arg := range cmd.ArgSpecs {
8178
if !arg.Required || arg.OneOfGroup != "" {
8279
continue
@@ -103,14 +100,24 @@ func validateRequiredArgs(cmd *Command, cmdArgs interface{}, rawArgs args.RawArg
103100
}
104101
}
105102
}
106-
107-
if err := oneOfManager.ValidateOneOfGroups(rawArgs); err != nil {
103+
if err := validateOneOfRequiredArgs(cmd, rawArgs); err != nil {
108104
return err
109105
}
110106

111107
return nil
112108
}
113109

110+
func validateOneOfRequiredArgs(cmd *Command, rawArgs args.RawArgs) error {
111+
oneOfManager := NewOneOfGroupManager(cmd)
112+
if err := oneOfManager.ValidateUniqueOneOfGroups(rawArgs); err != nil {
113+
return err
114+
}
115+
if err := oneOfManager.ValidateRequiredOneOfGroups(rawArgs); err != nil {
116+
return err
117+
}
118+
return nil
119+
}
120+
114121
func ValidateNoConflict(cmd *Command, rawArgs args.RawArgs) error {
115122
for _, arg1 := range cmd.ArgSpecs {
116123
for _, arg2 := range cmd.ArgSpecs {
@@ -281,7 +288,22 @@ func NewOneOfGroupManager(cmd *Command) *OneOfGroupManager {
281288
return manager
282289
}
283290

284-
func (m *OneOfGroupManager) ValidateOneOfGroups(rawArgs args.RawArgs) error {
291+
func (m *OneOfGroupManager) ValidateUniqueOneOfGroups(rawArgs args.RawArgs) error {
292+
for _, groupArgs := range m.Groups {
293+
existingArg := ""
294+
for _, argName := range groupArgs {
295+
if rawArgs.ExistsArgByName(argName) {
296+
if existingArg != "" {
297+
return fmt.Errorf("arguments '%s' and '%s' are mutually exclusive", existingArg, argName)
298+
}
299+
existingArg = argName
300+
}
301+
}
302+
}
303+
return nil
304+
}
305+
306+
func (m *OneOfGroupManager) ValidateRequiredOneOfGroups(rawArgs args.RawArgs) error {
285307
for group, required := range m.RequiredGroups {
286308
if required {
287309
found := false

internal/core/validate_test.go

+253-2
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ func TestNewOneOfGroupManager(t *testing.T) {
477477
}
478478
}
479479

480-
func TestValidateOneOfGroups(t *testing.T) {
480+
func TestValidateRequiredOneOfGroups(t *testing.T) {
481481
tests := []struct {
482482
name string
483483
setupManager func() *core.OneOfGroupManager
@@ -522,7 +522,7 @@ func TestValidateOneOfGroups(t *testing.T) {
522522
for _, tt := range tests {
523523
t.Run(tt.name, func(t *testing.T) {
524524
manager := tt.setupManager()
525-
err := manager.ValidateOneOfGroups(tt.rawArgs)
525+
err := manager.ValidateRequiredOneOfGroups(tt.rawArgs)
526526

527527
if tt.expectedError == "" {
528528
assert.NoError(t, err, "Expected no error, got %v", err)
@@ -532,3 +532,254 @@ func TestValidateOneOfGroups(t *testing.T) {
532532
})
533533
}
534534
}
535+
536+
func TestValidateUniqueOneOfGroups(t *testing.T) {
537+
tests := []struct {
538+
name string
539+
setupManager func() *core.OneOfGroupManager
540+
rawArgs args.RawArgs
541+
expectedError string
542+
}{
543+
{
544+
name: "Required group satisfied with first argument",
545+
setupManager: func() *core.OneOfGroupManager {
546+
return &core.OneOfGroupManager{
547+
Groups: map[string][]string{"group1": {"a", "b"}},
548+
}
549+
},
550+
rawArgs: []string{"a=true"},
551+
expectedError: "",
552+
},
553+
{
554+
name: "No arguments passed",
555+
setupManager: func() *core.OneOfGroupManager {
556+
return &core.OneOfGroupManager{
557+
Groups: map[string][]string{"group1": {"a", "b"}},
558+
}
559+
},
560+
rawArgs: []string{},
561+
expectedError: "",
562+
},
563+
{
564+
name: "Multiple groups, all satisfied",
565+
setupManager: func() *core.OneOfGroupManager {
566+
return &core.OneOfGroupManager{
567+
Groups: map[string][]string{
568+
"group1": {"a", "b"},
569+
"group2": {"c", "d"},
570+
},
571+
}
572+
},
573+
rawArgs: []string{"a=true", "c=true"},
574+
expectedError: "",
575+
},
576+
{
577+
name: "Multiple groups, one satisfied",
578+
setupManager: func() *core.OneOfGroupManager {
579+
return &core.OneOfGroupManager{
580+
Groups: map[string][]string{
581+
"group1": {"a", "b"},
582+
"group2": {"c", "d"},
583+
},
584+
}
585+
},
586+
rawArgs: []string{"a=true"},
587+
expectedError: "",
588+
},
589+
{
590+
name: "Multiple groups, not exclusive argument for groups 2",
591+
setupManager: func() *core.OneOfGroupManager {
592+
return &core.OneOfGroupManager{
593+
Groups: map[string][]string{
594+
"group1": {"a", "b"},
595+
"group2": {"c", "d"},
596+
},
597+
}
598+
},
599+
rawArgs: []string{"a=true", "c=true", "d=true"},
600+
expectedError: "arguments 'c' and 'd' are mutually exclusive",
601+
},
602+
{
603+
name: "Multiple groups, not exclusive argument for groups 1",
604+
setupManager: func() *core.OneOfGroupManager {
605+
return &core.OneOfGroupManager{
606+
Groups: map[string][]string{
607+
"group1": {"a", "b"},
608+
"group2": {"c", "d"},
609+
},
610+
}
611+
},
612+
rawArgs: []string{"a=true", "b=true", "c=true"},
613+
expectedError: "arguments 'a' and 'b' are mutually exclusive",
614+
},
615+
{
616+
name: "One group, not exclusive argument for groups 1",
617+
setupManager: func() *core.OneOfGroupManager {
618+
return &core.OneOfGroupManager{
619+
Groups: map[string][]string{
620+
"group1": {"a", "b", "c", "d"},
621+
},
622+
}
623+
},
624+
rawArgs: []string{"a=true", "d=true"},
625+
expectedError: "arguments 'a' and 'd' are mutually exclusive",
626+
},
627+
}
628+
629+
for _, tt := range tests {
630+
t.Run(tt.name, func(t *testing.T) {
631+
manager := tt.setupManager()
632+
err := manager.ValidateUniqueOneOfGroups(tt.rawArgs)
633+
if tt.expectedError == "" {
634+
assert.NoError(t, err, "Expected no error, got %v", err)
635+
} else {
636+
assert.EqualError(t, err, tt.expectedError, fmt.Sprintf("Expected error message '%s', got '%v'", tt.expectedError, err))
637+
}
638+
})
639+
}
640+
}
641+
642+
func Test_ValidateOneOf(t *testing.T) {
643+
t.Run("Validate OneOf", core.Test(&core.TestConfig{
644+
Commands: core.NewCommands(&core.Command{
645+
Namespace: "oneof",
646+
ArgsType: reflect.TypeOf(args.RawArgs{}),
647+
AllowAnonymousClient: true,
648+
Run: func(_ context.Context, _ interface{}) (i interface{}, e error) {
649+
return &core.SuccessResult{}, nil
650+
},
651+
ArgSpecs: core.ArgSpecs{
652+
{
653+
Name: "a",
654+
OneOfGroup: "groups1",
655+
},
656+
{
657+
Name: "b",
658+
OneOfGroup: "groups1",
659+
},
660+
},
661+
}),
662+
Cmd: "scw oneof a=yo",
663+
Check: core.TestCheckCombine(
664+
core.TestCheckExitCode(0),
665+
),
666+
}))
667+
t.Run("Required group satisfied", func(t *testing.T) {
668+
core.Test(&core.TestConfig{
669+
Commands: core.NewCommands(&core.Command{
670+
Namespace: "oneof",
671+
ArgsType: reflect.TypeOf(args.RawArgs{}),
672+
AllowAnonymousClient: true,
673+
Run: func(_ context.Context, _ interface{}) (i interface{}, e error) {
674+
return &core.SuccessResult{}, nil
675+
},
676+
ArgSpecs: core.ArgSpecs{
677+
{
678+
Name: "a",
679+
OneOfGroup: "group1",
680+
Required: true,
681+
},
682+
{
683+
Name: "b",
684+
OneOfGroup: "group1",
685+
Required: true,
686+
},
687+
},
688+
}),
689+
Cmd: "scw oneof b=yo",
690+
Check: core.TestCheckCombine(
691+
core.TestCheckExitCode(0),
692+
),
693+
})(t)
694+
})
695+
696+
t.Run("Required group not satisfied", func(t *testing.T) {
697+
core.Test(&core.TestConfig{
698+
Commands: core.NewCommands(&core.Command{
699+
Namespace: "oneof",
700+
ArgsType: reflect.TypeOf(args.RawArgs{}),
701+
AllowAnonymousClient: true,
702+
Run: func(_ context.Context, _ interface{}) (i interface{}, e error) {
703+
return &core.SuccessResult{}, nil
704+
},
705+
ArgSpecs: core.ArgSpecs{
706+
{
707+
Name: "a",
708+
OneOfGroup: "group1",
709+
Required: true,
710+
},
711+
{
712+
Name: "b",
713+
OneOfGroup: "group1",
714+
Required: true,
715+
},
716+
},
717+
}),
718+
Cmd: "scw oneof c=yo",
719+
Check: core.TestCheckCombine(
720+
core.TestCheckExitCode(1),
721+
core.TestCheckError(fmt.Errorf("at least one argument from the 'group1' group is required")),
722+
),
723+
})(t)
724+
})
725+
726+
t.Run("Arguments are mutually exclusive", func(t *testing.T) {
727+
core.Test(&core.TestConfig{
728+
Commands: core.NewCommands(&core.Command{
729+
Namespace: "oneof",
730+
ArgsType: reflect.TypeOf(args.RawArgs{}),
731+
AllowAnonymousClient: true,
732+
Run: func(_ context.Context, _ interface{}) (i interface{}, e error) {
733+
return &core.SuccessResult{}, nil
734+
},
735+
ArgSpecs: core.ArgSpecs{
736+
{
737+
Name: "a",
738+
OneOfGroup: "group1",
739+
},
740+
{
741+
Name: "b",
742+
OneOfGroup: "group1",
743+
},
744+
},
745+
}),
746+
Cmd: "scw oneof a=yo b=no",
747+
Check: core.TestCheckCombine(
748+
core.TestCheckExitCode(1),
749+
core.TestCheckError(fmt.Errorf("arguments 'a' and 'b' are mutually exclusive")),
750+
),
751+
})(t)
752+
})
753+
754+
t.Run("Arguments are mutually exclusive with 3 arguments", func(t *testing.T) {
755+
core.Test(&core.TestConfig{
756+
Commands: core.NewCommands(&core.Command{
757+
Namespace: "oneof",
758+
ArgsType: reflect.TypeOf(args.RawArgs{}),
759+
AllowAnonymousClient: true,
760+
Run: func(_ context.Context, _ interface{}) (i interface{}, e error) {
761+
return &core.SuccessResult{}, nil
762+
},
763+
ArgSpecs: core.ArgSpecs{
764+
{
765+
Name: "a",
766+
OneOfGroup: "group1",
767+
},
768+
{
769+
Name: "b",
770+
OneOfGroup: "group1",
771+
},
772+
{
773+
Name: "c",
774+
OneOfGroup: "group1",
775+
},
776+
},
777+
}),
778+
Cmd: "scw oneof a=yo c=no",
779+
Check: core.TestCheckCombine(
780+
core.TestCheckExitCode(1),
781+
core.TestCheckError(fmt.Errorf("arguments 'a' and 'c' are mutually exclusive")),
782+
),
783+
})(t)
784+
})
785+
}

0 commit comments

Comments
 (0)