1 package altsrc_test
2
3 import (
4 "errors"
5 "fmt"
6 "io/ioutil"
7 "log"
8 "os"
9 "testing"
10 "time"
11
12 "github.com/urfave/cli/v2"
13 "github.com/urfave/cli/v2/altsrc"
14 )
15
16 func ExampleApp_Run_yamlFileLoaderDuration() {
17 execServe := func(c *cli.Context) error {
18 keepaliveInterval := c.Duration("keepalive-interval")
19 fmt.Printf("keepalive %s\n", keepaliveInterval)
20 return nil
21 }
22
23 fileExists := func(filename string) bool {
24 stat, _ := os.Stat(filename)
25 return stat != nil
26 }
27
28
29
30 initConfigFileInputSource := func(configFlag string, flags []cli.Flag) cli.BeforeFunc {
31 return func(context *cli.Context) error {
32 configFile := context.String(configFlag)
33 if context.IsSet(configFlag) && !fileExists(configFile) {
34 return fmt.Errorf("config file %s does not exist", configFile)
35 } else if !context.IsSet(configFlag) && !fileExists(configFile) {
36 return nil
37 }
38 inputSource, err := altsrc.NewYamlSourceFromFile(configFile)
39 if err != nil {
40 return err
41 }
42 return altsrc.ApplyInputSourceValues(context, inputSource, flags)
43 }
44 }
45
46 flagsServe := []cli.Flag{
47 &cli.StringFlag{
48 Name: "config",
49 Aliases: []string{"c"},
50 EnvVars: []string{"CONFIG_FILE"},
51 Value: "../testdata/empty.yml",
52 DefaultText: "../testdata/empty.yml",
53 Usage: "config file",
54 },
55 altsrc.NewDurationFlag(
56 &cli.DurationFlag{
57 Name: "keepalive-interval",
58 Aliases: []string{"k"},
59 EnvVars: []string{"KEEPALIVE_INTERVAL"},
60 Value: 45 * time.Second,
61 Usage: "interval of keepalive messages",
62 },
63 ),
64 }
65
66 cmdServe := &cli.Command{
67 Name: "serve",
68 Usage: "Run the server",
69 UsageText: "serve [OPTIONS..]",
70 Action: execServe,
71 Flags: flagsServe,
72 Before: initConfigFileInputSource("config", flagsServe),
73 }
74
75 c := &cli.App{
76 Name: "cmd",
77 HideVersion: true,
78 UseShortOptionHandling: true,
79 Commands: []*cli.Command{
80 cmdServe,
81 },
82 }
83
84 if err := c.Run([]string{"cmd", "serve", "--config", "../testdata/empty.yml"}); err != nil {
85 log.Fatal(err)
86 }
87
88
89
90 }
91
92 func TestYamlFileInt64Slice(t *testing.T) {
93 _ = ioutil.WriteFile("current.yaml", []byte(`top:
94 test: [100, 9223372036854775808]`), 0666)
95 defer os.Remove("current.yaml")
96
97 testFlag := []cli.Flag{
98 &altsrc.StringFlag{StringFlag: &cli.StringFlag{Name: "conf"}},
99 &altsrc.Int64SliceFlag{Int64SliceFlag: &cli.Int64SliceFlag{Name: "top.test"}},
100 }
101 app := &cli.App{}
102 app.Before = altsrc.InitInputSourceWithContext(testFlag, altsrc.NewYamlSourceFromFlagFunc("conf"))
103 app.Action = func(c *cli.Context) error { return nil }
104 app.Flags = append(app.Flags, testFlag...)
105
106 test := []string{"testApp", "--conf", "current.yaml"}
107 if err := app.Run(test); err == nil {
108 t.Error("should return the mismatch error")
109 }
110 }
111
112 func TestYamlFileStringSlice(t *testing.T) {
113 _ = ioutil.WriteFile("current.yaml", []byte(`top:
114 test: ["s1", "s2"]`), 0666)
115 defer os.Remove("current.yaml")
116
117 testFlag := []cli.Flag{
118 &altsrc.StringFlag{StringFlag: &cli.StringFlag{Name: "conf"}},
119 &altsrc.StringSliceFlag{StringSliceFlag: &cli.StringSliceFlag{Name: "top.test", EnvVars: []string{"THE_TEST"}}},
120 }
121 app := &cli.App{}
122 app.Before = altsrc.InitInputSourceWithContext(testFlag, altsrc.NewYamlSourceFromFlagFunc("conf"))
123 app.Action = func(c *cli.Context) error {
124 if c.IsSet("top.test") {
125 return nil
126 } else {
127 return errors.New("top.test is not set")
128 }
129 }
130 app.Flags = append(app.Flags, testFlag...)
131
132 test := []string{"testApp", "--conf", "current.yaml"}
133 if err := app.Run(test); err != nil {
134 t.Error(err)
135 }
136 }
137
138 func TestYamlFileUint64(t *testing.T) {
139 tests := []struct {
140 name string
141 entry string
142 err bool
143 }{
144 {
145 "top.test",
146 `top:
147 test: 100`,
148 false,
149 },
150 {
151 "test",
152 "test: ",
153 false,
154 },
155 {
156 "test",
157 "test: 100",
158 false,
159 },
160 {
161 "test",
162 "test: -100",
163 true,
164 },
165 {
166 "test",
167 "test: 9223372036854775807",
168 false,
169 },
170 {
171 "test",
172 "test: 9223372036854775808",
173 false,
174 },
175 {
176 "test",
177 "test: 19223372036854775808",
178 true,
179 },
180 }
181
182 for i, test := range tests {
183 _ = ioutil.WriteFile("current.yaml", []byte(test.entry), 0666)
184 defer os.Remove("current.yaml")
185
186 testFlag := []cli.Flag{
187 &altsrc.StringFlag{StringFlag: &cli.StringFlag{Name: "conf"}},
188 &altsrc.Uint64Flag{Uint64Flag: &cli.Uint64Flag{Name: test.name}},
189 }
190 app := &cli.App{}
191 app.Flags = append(app.Flags, testFlag...)
192 app.Before = altsrc.InitInputSourceWithContext(testFlag, altsrc.NewYamlSourceFromFlagFunc("conf"))
193
194 appCmd := []string{"testApp", "--conf", "current.yaml"}
195 err := app.Run(appCmd)
196 if result := err != nil; result != test.err {
197 t.Error(i, "testcast: expect error but", err)
198 }
199 }
200 }
201
202 func TestYamlFileUint(t *testing.T) {
203 tests := []struct {
204 name string
205 entry string
206 err bool
207 }{
208 {
209 "top.test",
210 `top:
211 test: 100`,
212 false,
213 },
214 {
215 "test",
216 "test: ",
217 false,
218 },
219 {
220 "test",
221 "test: 100",
222 false,
223 },
224 {
225 "test",
226 "test: -100",
227 true,
228 },
229 {
230 "test",
231 "test: 9223372036854775807",
232 false,
233 },
234 {
235 "test",
236 "test: 9223372036854775808",
237 false,
238 },
239 {
240 "test",
241 "test: 19223372036854775808",
242 true,
243 },
244 }
245
246 for i, test := range tests {
247 _ = ioutil.WriteFile("current.yaml", []byte(test.entry), 0666)
248 defer os.Remove("current.yaml")
249
250 testFlag := []cli.Flag{
251 &altsrc.StringFlag{StringFlag: &cli.StringFlag{Name: "conf"}},
252 &altsrc.UintFlag{UintFlag: &cli.UintFlag{Name: test.name}},
253 }
254 app := &cli.App{}
255 app.Flags = append(app.Flags, testFlag...)
256 app.Before = altsrc.InitInputSourceWithContext(testFlag, altsrc.NewYamlSourceFromFlagFunc("conf"))
257
258 appCmd := []string{"testApp", "--conf", "current.yaml"}
259 err := app.Run(appCmd)
260 if result := err != nil; result != test.err {
261 t.Error(i, "testcast: expect error but", err)
262 }
263 }
264 }
265
266 func TestYamlFileInt64(t *testing.T) {
267 tests := []struct {
268 name string
269 entry string
270 err bool
271 }{
272 {
273 "top.test",
274 `top:
275 test: 100`,
276 false,
277 },
278 {
279 "test",
280 "test: ",
281 false,
282 },
283 {
284 "test",
285 "test: 100",
286 false,
287 },
288 {
289 "test",
290 "test: -100",
291 false,
292 },
293 {
294 "test",
295 "test: 9223372036854775807",
296 false,
297 },
298 {
299 "test",
300 "test: 9223372036854775808",
301 true,
302 },
303 {
304 "test",
305 "test: 19223372036854775808",
306 true,
307 },
308 }
309
310 for i, test := range tests {
311 _ = ioutil.WriteFile("current.yaml", []byte(test.entry), 0666)
312 defer os.Remove("current.yaml")
313
314 testFlag := []cli.Flag{
315 &altsrc.StringFlag{StringFlag: &cli.StringFlag{Name: "conf"}},
316 &altsrc.Int64Flag{Int64Flag: &cli.Int64Flag{Name: test.name}},
317 }
318 app := &cli.App{}
319 app.Flags = append(app.Flags, testFlag...)
320 app.Before = altsrc.InitInputSourceWithContext(testFlag, altsrc.NewYamlSourceFromFlagFunc("conf"))
321
322 appCmd := []string{"testApp", "--conf", "current.yaml"}
323 err := app.Run(appCmd)
324 if result := err != nil; result != test.err {
325 t.Error(i, "testcast: expect error but", err)
326 }
327 }
328 }
329
View as plain text