1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cobra
16
17 import (
18 "strings"
19 "testing"
20 )
21
22 func TestValidateFlagGroups(t *testing.T) {
23 getCmd := func() *Command {
24 c := &Command{
25 Use: "testcmd",
26 Run: func(cmd *Command, args []string) {
27 }}
28
29 for _, v := range []string{"a", "b", "c", "d"} {
30 c.Flags().String(v, "", "")
31 }
32 for _, v := range []string{"e", "f", "g"} {
33 c.PersistentFlags().String(v, "", "")
34 }
35 subC := &Command{
36 Use: "subcmd",
37 Run: func(cmd *Command, args []string) {
38 }}
39 subC.Flags().String("subonly", "", "")
40 c.AddCommand(subC)
41 return c
42 }
43
44
45 testcases := []struct {
46 desc string
47 flagGroupsRequired []string
48 flagGroupsOneRequired []string
49 flagGroupsExclusive []string
50 subCmdFlagGroupsRequired []string
51 subCmdFlagGroupsOneRequired []string
52 subCmdFlagGroupsExclusive []string
53 args []string
54 expectErr string
55 }{
56 {
57 desc: "No flags no problem",
58 }, {
59 desc: "No flags no problem even with conflicting groups",
60 flagGroupsRequired: []string{"a b"},
61 flagGroupsExclusive: []string{"a b"},
62 }, {
63 desc: "Required flag group not satisfied",
64 flagGroupsRequired: []string{"a b c"},
65 args: []string{"--a=foo"},
66 expectErr: "if any flags in the group [a b c] are set they must all be set; missing [b c]",
67 }, {
68 desc: "One-required flag group not satisfied",
69 flagGroupsOneRequired: []string{"a b"},
70 args: []string{"--c=foo"},
71 expectErr: "at least one of the flags in the group [a b] is required",
72 }, {
73 desc: "Exclusive flag group not satisfied",
74 flagGroupsExclusive: []string{"a b c"},
75 args: []string{"--a=foo", "--b=foo"},
76 expectErr: "if any flags in the group [a b c] are set none of the others can be; [a b] were all set",
77 }, {
78 desc: "Multiple required flag group not satisfied returns first error",
79 flagGroupsRequired: []string{"a b c", "a d"},
80 args: []string{"--c=foo", "--d=foo"},
81 expectErr: `if any flags in the group [a b c] are set they must all be set; missing [a b]`,
82 }, {
83 desc: "Multiple one-required flag group not satisfied returns first error",
84 flagGroupsOneRequired: []string{"a b", "d e"},
85 args: []string{"--c=foo", "--f=foo"},
86 expectErr: `at least one of the flags in the group [a b] is required`,
87 }, {
88 desc: "Multiple exclusive flag group not satisfied returns first error",
89 flagGroupsExclusive: []string{"a b c", "a d"},
90 args: []string{"--a=foo", "--c=foo", "--d=foo"},
91 expectErr: `if any flags in the group [a b c] are set none of the others can be; [a c] were all set`,
92 }, {
93 desc: "Validation of required groups occurs on groups in sorted order",
94 flagGroupsRequired: []string{"a d", "a b", "a c"},
95 args: []string{"--a=foo"},
96 expectErr: `if any flags in the group [a b] are set they must all be set; missing [b]`,
97 }, {
98 desc: "Validation of one-required groups occurs on groups in sorted order",
99 flagGroupsOneRequired: []string{"d e", "a b", "f g"},
100 args: []string{"--c=foo"},
101 expectErr: `at least one of the flags in the group [a b] is required`,
102 }, {
103 desc: "Validation of exclusive groups occurs on groups in sorted order",
104 flagGroupsExclusive: []string{"a d", "a b", "a c"},
105 args: []string{"--a=foo", "--b=foo", "--c=foo"},
106 expectErr: `if any flags in the group [a b] are set none of the others can be; [a b] were all set`,
107 }, {
108 desc: "Persistent flags utilize required and exclusive groups and can fail required groups",
109 flagGroupsRequired: []string{"a e", "e f"},
110 flagGroupsExclusive: []string{"f g"},
111 args: []string{"--a=foo", "--f=foo", "--g=foo"},
112 expectErr: `if any flags in the group [a e] are set they must all be set; missing [e]`,
113 }, {
114 desc: "Persistent flags utilize one-required and exclusive groups and can fail one-required groups",
115 flagGroupsOneRequired: []string{"a b", "e f"},
116 flagGroupsExclusive: []string{"e f"},
117 args: []string{"--e=foo"},
118 expectErr: `at least one of the flags in the group [a b] is required`,
119 }, {
120 desc: "Persistent flags utilize required and exclusive groups and can fail mutually exclusive groups",
121 flagGroupsRequired: []string{"a e", "e f"},
122 flagGroupsExclusive: []string{"f g"},
123 args: []string{"--a=foo", "--e=foo", "--f=foo", "--g=foo"},
124 expectErr: `if any flags in the group [f g] are set none of the others can be; [f g] were all set`,
125 }, {
126 desc: "Persistent flags utilize required and exclusive groups and can pass",
127 flagGroupsRequired: []string{"a e", "e f"},
128 flagGroupsExclusive: []string{"f g"},
129 args: []string{"--a=foo", "--e=foo", "--f=foo"},
130 }, {
131 desc: "Persistent flags utilize one-required and exclusive groups and can pass",
132 flagGroupsOneRequired: []string{"a e", "e f"},
133 flagGroupsExclusive: []string{"f g"},
134 args: []string{"--a=foo", "--e=foo", "--f=foo"},
135 }, {
136 desc: "Subcmds can use required groups using inherited flags",
137 subCmdFlagGroupsRequired: []string{"e subonly"},
138 args: []string{"subcmd", "--e=foo", "--subonly=foo"},
139 }, {
140 desc: "Subcmds can use one-required groups using inherited flags",
141 subCmdFlagGroupsOneRequired: []string{"e subonly"},
142 args: []string{"subcmd", "--e=foo", "--subonly=foo"},
143 }, {
144 desc: "Subcmds can use one-required groups using inherited flags and fail one-required groups",
145 subCmdFlagGroupsOneRequired: []string{"e subonly"},
146 args: []string{"subcmd"},
147 expectErr: "at least one of the flags in the group [e subonly] is required",
148 }, {
149 desc: "Subcmds can use exclusive groups using inherited flags",
150 subCmdFlagGroupsExclusive: []string{"e subonly"},
151 args: []string{"subcmd", "--e=foo", "--subonly=foo"},
152 expectErr: "if any flags in the group [e subonly] are set none of the others can be; [e subonly] were all set",
153 }, {
154 desc: "Subcmds can use exclusive groups using inherited flags and pass",
155 subCmdFlagGroupsExclusive: []string{"e subonly"},
156 args: []string{"subcmd", "--e=foo"},
157 }, {
158 desc: "Flag groups not applied if not found on invoked command",
159 subCmdFlagGroupsRequired: []string{"e subonly"},
160 args: []string{"--e=foo"},
161 },
162 }
163 for _, tc := range testcases {
164 t.Run(tc.desc, func(t *testing.T) {
165 c := getCmd()
166 sub := c.Commands()[0]
167 for _, flagGroup := range tc.flagGroupsRequired {
168 c.MarkFlagsRequiredTogether(strings.Split(flagGroup, " ")...)
169 }
170 for _, flagGroup := range tc.flagGroupsOneRequired {
171 c.MarkFlagsOneRequired(strings.Split(flagGroup, " ")...)
172 }
173 for _, flagGroup := range tc.flagGroupsExclusive {
174 c.MarkFlagsMutuallyExclusive(strings.Split(flagGroup, " ")...)
175 }
176 for _, flagGroup := range tc.subCmdFlagGroupsRequired {
177 sub.MarkFlagsRequiredTogether(strings.Split(flagGroup, " ")...)
178 }
179 for _, flagGroup := range tc.subCmdFlagGroupsOneRequired {
180 sub.MarkFlagsOneRequired(strings.Split(flagGroup, " ")...)
181 }
182 for _, flagGroup := range tc.subCmdFlagGroupsExclusive {
183 sub.MarkFlagsMutuallyExclusive(strings.Split(flagGroup, " ")...)
184 }
185 c.SetArgs(tc.args)
186 err := c.Execute()
187 switch {
188 case err == nil && len(tc.expectErr) > 0:
189 t.Errorf("Expected error %q but got nil", tc.expectErr)
190 case err != nil && err.Error() != tc.expectErr:
191 t.Errorf("Expected error %q but got %q", tc.expectErr, err)
192 }
193 })
194 }
195 }
196
View as plain text