1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ini
16
17 import (
18 "bytes"
19 "fmt"
20 "runtime"
21 "strings"
22 "testing"
23 "time"
24
25 "github.com/stretchr/testify/assert"
26 "github.com/stretchr/testify/require"
27 )
28
29 func TestKey_AddShadow(t *testing.T) {
30 t.Run("add shadow to a key", func(t *testing.T) {
31 f, err := ShadowLoad([]byte(`
32 [notes]
33 -: note1`))
34 require.NoError(t, err)
35 require.NotNil(t, f)
36
37 k, err := f.Section("").NewKey("NAME", "ini")
38 require.NoError(t, err)
39 require.NotNil(t, k)
40
41 assert.NoError(t, k.AddShadow("ini.v1"))
42 assert.Equal(t, []string{"ini", "ini.v1"}, k.ValueWithShadows())
43
44 t.Run("add shadow to boolean key", func(t *testing.T) {
45 k, err := f.Section("").NewBooleanKey("published")
46 require.NoError(t, err)
47 require.NotNil(t, k)
48 assert.Error(t, k.AddShadow("beta"))
49 })
50
51 t.Run("add shadow to auto-increment key", func(t *testing.T) {
52 assert.Error(t, f.Section("notes").Key("#1").AddShadow("beta"))
53 })
54
55 t.Run("deduplicate an existing value", func(t *testing.T) {
56 k := f.Section("").Key("NAME")
57 assert.NoError(t, k.AddShadow("ini"))
58 assert.Equal(t, []string{"ini", "ini.v1"}, k.ValueWithShadows())
59 })
60
61 t.Run("ignore empty shadow values", func(t *testing.T) {
62 k := f.Section("").Key("empty")
63 assert.NoError(t, k.AddShadow(""))
64 assert.NoError(t, k.AddShadow("ini"))
65 assert.Equal(t, []string{"ini"}, k.ValueWithShadows())
66 })
67 })
68
69 t.Run("allow duplicate shadowed values", func(t *testing.T) {
70 f := Empty(LoadOptions{
71 AllowShadows: true,
72 AllowDuplicateShadowValues: true,
73 })
74 require.NotNil(t, f)
75
76 k, err := f.Section("").NewKey("NAME", "ini")
77 require.NoError(t, err)
78 require.NotNil(t, k)
79
80 assert.NoError(t, k.AddShadow("ini.v1"))
81 assert.NoError(t, k.AddShadow("ini"))
82 assert.NoError(t, k.AddShadow("ini"))
83 assert.Equal(t, []string{"ini", "ini.v1", "ini", "ini"}, k.ValueWithShadows())
84 })
85
86 t.Run("shadow is not allowed", func(t *testing.T) {
87 f := Empty()
88 require.NotNil(t, f)
89
90 k, err := f.Section("").NewKey("NAME", "ini")
91 require.NoError(t, err)
92 require.NotNil(t, k)
93
94 assert.Error(t, k.AddShadow("ini.v1"))
95 })
96 }
97
98
99 func float64sEqual(t *testing.T, values []float64, expected ...float64) {
100 t.Helper()
101
102 assert.Len(t, values, len(expected))
103 for i, v := range expected {
104 assert.Equal(t, v, values[i])
105 }
106 }
107
108 func intsEqual(t *testing.T, values []int, expected ...int) {
109 t.Helper()
110
111 assert.Len(t, values, len(expected))
112 for i, v := range expected {
113 assert.Equal(t, v, values[i])
114 }
115 }
116
117 func int64sEqual(t *testing.T, values []int64, expected ...int64) {
118 t.Helper()
119
120 assert.Len(t, values, len(expected))
121 for i, v := range expected {
122 assert.Equal(t, v, values[i])
123 }
124 }
125
126 func uintsEqual(t *testing.T, values []uint, expected ...uint) {
127 t.Helper()
128
129 assert.Len(t, values, len(expected))
130 for i, v := range expected {
131 assert.Equal(t, v, values[i])
132 }
133 }
134
135 func uint64sEqual(t *testing.T, values []uint64, expected ...uint64) {
136 t.Helper()
137
138 assert.Len(t, values, len(expected))
139 for i, v := range expected {
140 assert.Equal(t, v, values[i])
141 }
142 }
143
144 func boolsEqual(t *testing.T, values []bool, expected ...bool) {
145 t.Helper()
146
147 assert.Len(t, values, len(expected))
148 for i, v := range expected {
149 assert.Equal(t, v, values[i])
150 }
151 }
152
153 func timesEqual(t *testing.T, values []time.Time, expected ...time.Time) {
154 t.Helper()
155
156 assert.Len(t, values, len(expected))
157 for i, v := range expected {
158 assert.Equal(t, v.String(), values[i].String())
159 }
160 }
161
162 func TestKey_Helpers(t *testing.T) {
163 t.Run("getting and setting values", func(t *testing.T) {
164 f, err := Load(fullConf)
165 require.NoError(t, err)
166 require.NotNil(t, f)
167
168 t.Run("get string representation", func(t *testing.T) {
169 sec := f.Section("")
170 require.NotNil(t, sec)
171 assert.Equal(t, "ini", sec.Key("NAME").Value())
172 assert.Equal(t, "ini", sec.Key("NAME").String())
173 assert.Equal(t, "ini", sec.Key("NAME").Validate(func(in string) string {
174 return in
175 }))
176 assert.Equal(t, "; Package name", sec.Key("NAME").Comment)
177 assert.Equal(t, "gopkg.in/ini.v1", sec.Key("IMPORT_PATH").String())
178
179 t.Run("with ValueMapper", func(t *testing.T) {
180 f.ValueMapper = func(in string) string {
181 if in == "gopkg.in/%(NAME)s.%(VERSION)s" {
182 return "github.com/go-ini/ini"
183 }
184 return in
185 }
186 assert.Equal(t, "github.com/go-ini/ini", sec.Key("IMPORT_PATH").String())
187 })
188 })
189
190 t.Run("get values in non-default section", func(t *testing.T) {
191 sec := f.Section("author")
192 require.NotNil(t, sec)
193 assert.Equal(t, "Unknwon", sec.Key("NAME").String())
194 assert.Equal(t, "https://github.com/Unknwon", sec.Key("GITHUB").String())
195
196 sec = f.Section("package")
197 require.NotNil(t, sec)
198 assert.Equal(t, "https://gopkg.in/ini.v1", sec.Key("CLONE_URL").String())
199 })
200
201 t.Run("get auto-increment key names", func(t *testing.T) {
202 keys := f.Section("features").Keys()
203 for i, k := range keys {
204 assert.Equal(t, fmt.Sprintf("#%d", i+1), k.Name())
205 }
206 })
207
208 t.Run("get parent-keys that are available to the child section", func(t *testing.T) {
209 parentKeys := f.Section("package.sub").ParentKeys()
210 for _, k := range parentKeys {
211 assert.Equal(t, "CLONE_URL", k.Name())
212 }
213 })
214
215 t.Run("get overwrite value", func(t *testing.T) {
216 assert.Equal(t, "u@gogs.io", f.Section("author").Key("E-MAIL").String())
217 })
218
219 t.Run("get sections", func(t *testing.T) {
220 sections := f.Sections()
221 for i, name := range []string{DefaultSection, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
222 assert.Equal(t, name, sections[i].Name())
223 }
224 })
225
226 t.Run("get parent section value", func(t *testing.T) {
227 assert.Equal(t, "https://gopkg.in/ini.v1", f.Section("package.sub").Key("CLONE_URL").String())
228 assert.Equal(t, "https://gopkg.in/ini.v1", f.Section("package.fake.sub").Key("CLONE_URL").String())
229 })
230
231 t.Run("get multiple line value", func(t *testing.T) {
232 if runtime.GOOS == "windows" {
233 t.Skip("Skipping testing on Windows")
234 }
235
236 assert.Equal(t, "Gopher.\nCoding addict.\nGood man.\n", f.Section("author").Key("BIO").String())
237 })
238
239 t.Run("get values with type", func(t *testing.T) {
240 sec := f.Section("types")
241 v1, err := sec.Key("BOOL").Bool()
242 require.NoError(t, err)
243 assert.True(t, v1)
244
245 v1, err = sec.Key("BOOL_FALSE").Bool()
246 require.NoError(t, err)
247 assert.False(t, v1)
248
249 v2, err := sec.Key("FLOAT64").Float64()
250 require.NoError(t, err)
251 assert.Equal(t, 1.25, v2)
252
253 v3, err := sec.Key("INT").Int()
254 require.NoError(t, err)
255 assert.Equal(t, 10, v3)
256
257 v4, err := sec.Key("INT").Int64()
258 require.NoError(t, err)
259 assert.Equal(t, int64(10), v4)
260
261 v5, err := sec.Key("UINT").Uint()
262 require.NoError(t, err)
263 assert.Equal(t, uint(3), v5)
264
265 v6, err := sec.Key("UINT").Uint64()
266 require.NoError(t, err)
267 assert.Equal(t, uint64(3), v6)
268
269 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
270 require.NoError(t, err)
271 v7, err := sec.Key("TIME").Time()
272 require.NoError(t, err)
273 assert.Equal(t, ti.String(), v7.String())
274
275 v8, err := sec.Key("HEX_NUMBER").Int()
276 require.NoError(t, err)
277 assert.Equal(t, 0x3000, v8)
278
279 t.Run("must get values with type", func(t *testing.T) {
280 assert.Equal(t, "str", sec.Key("STRING").MustString("404"))
281 assert.True(t, sec.Key("BOOL").MustBool())
282 assert.Equal(t, float64(1.25), sec.Key("FLOAT64").MustFloat64())
283 assert.Equal(t, int(10), sec.Key("INT").MustInt())
284 assert.Equal(t, int64(10), sec.Key("INT").MustInt64())
285 assert.Equal(t, uint(3), sec.Key("UINT").MustUint())
286 assert.Equal(t, uint64(3), sec.Key("UINT").MustUint64())
287 assert.Equal(t, ti.String(), sec.Key("TIME").MustTime().String())
288 assert.Equal(t, 0x3000, sec.Key("HEX_NUMBER").MustInt())
289
290 dur, err := time.ParseDuration("2h45m")
291 require.NoError(t, err)
292 assert.Equal(t, dur.Seconds(), sec.Key("DURATION").MustDuration().Seconds())
293
294 t.Run("must get values with default value", func(t *testing.T) {
295 assert.Equal(t, "404", sec.Key("STRING_404").MustString("404"))
296 assert.True(t, sec.Key("BOOL_404").MustBool(true))
297 assert.Equal(t, float64(2.5), sec.Key("FLOAT64_404").MustFloat64(2.5))
298 assert.Equal(t, int(15), sec.Key("INT_404").MustInt(15))
299 assert.Equal(t, int64(15), sec.Key("INT64_404").MustInt64(15))
300 assert.Equal(t, uint(6), sec.Key("UINT_404").MustUint(6))
301 assert.Equal(t, uint64(6), sec.Key("UINT64_404").MustUint64(6))
302 assert.Equal(t, 0x3001, sec.Key("HEX_NUMBER_404").MustInt(0x3001))
303
304 ti, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
305 require.NoError(t, err)
306 assert.Equal(t, ti.String(), sec.Key("TIME_404").MustTime(ti).String())
307
308 assert.Equal(t, dur.Seconds(), sec.Key("DURATION_404").MustDuration(dur).Seconds())
309
310 t.Run("must should set default as key value", func(t *testing.T) {
311 assert.Equal(t, "404", sec.Key("STRING_404").String())
312 assert.Equal(t, "true", sec.Key("BOOL_404").String())
313 assert.Equal(t, "2.5", sec.Key("FLOAT64_404").String())
314 assert.Equal(t, "15", sec.Key("INT_404").String())
315 assert.Equal(t, "15", sec.Key("INT64_404").String())
316 assert.Equal(t, "6", sec.Key("UINT_404").String())
317 assert.Equal(t, "6", sec.Key("UINT64_404").String())
318 assert.Equal(t, "2014-01-01T20:17:05Z", sec.Key("TIME_404").String())
319 assert.Equal(t, "2h45m0s", sec.Key("DURATION_404").String())
320 assert.Equal(t, "12289", sec.Key("HEX_NUMBER_404").String())
321 })
322 })
323 })
324 })
325
326 t.Run("get value with candidates", func(t *testing.T) {
327 sec := f.Section("types")
328 assert.Equal(t, "str", sec.Key("STRING").In("", []string{"str", "arr", "types"}))
329 assert.Equal(t, float64(1.25), sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}))
330 assert.Equal(t, int(10), sec.Key("INT").InInt(0, []int{10, 20, 30}))
331 assert.Equal(t, int64(10), sec.Key("INT").InInt64(0, []int64{10, 20, 30}))
332 assert.Equal(t, uint(3), sec.Key("UINT").InUint(0, []uint{3, 6, 9}))
333 assert.Equal(t, uint64(3), sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}))
334
335 zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
336 require.NoError(t, err)
337 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
338 require.NoError(t, err)
339 assert.Equal(t, ti.String(), sec.Key("TIME").InTime(zt, []time.Time{ti, time.Now(), time.Now().Add(1 * time.Second)}).String())
340
341 t.Run("get value with candidates and default value", func(t *testing.T) {
342 assert.Equal(t, "str", sec.Key("STRING_404_2").In("str", []string{"str", "arr", "types"}))
343 assert.Equal(t, float64(1.25), sec.Key("FLOAT64_404_2").InFloat64(1.25, []float64{1.25, 2.5, 3.75}))
344 assert.Equal(t, int(10), sec.Key("INT_404_2").InInt(10, []int{10, 20, 30}))
345 assert.Equal(t, int64(10), sec.Key("INT64_404_2").InInt64(10, []int64{10, 20, 30}))
346 assert.Equal(t, uint(3), sec.Key("UINT_404_2").InUint(3, []uint{3, 6, 9}))
347 assert.Equal(t, uint64(3), sec.Key("UINT_404_2").InUint64(3, []uint64{3, 6, 9}))
348 assert.Equal(t, ti.String(), sec.Key("TIME_404_2").InTime(ti, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String())
349 })
350 })
351
352 t.Run("get values in range", func(t *testing.T) {
353 sec := f.Section("types")
354 assert.Equal(t, float64(1.25), sec.Key("FLOAT64").RangeFloat64(0, 1, 2))
355 assert.Equal(t, int(10), sec.Key("INT").RangeInt(0, 10, 20))
356 assert.Equal(t, int64(10), sec.Key("INT").RangeInt64(0, 10, 20))
357
358 minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
359 require.NoError(t, err)
360 midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
361 require.NoError(t, err)
362 maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
363 require.NoError(t, err)
364 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
365 require.NoError(t, err)
366 assert.Equal(t, ti.String(), sec.Key("TIME").RangeTime(ti, minT, maxT).String())
367
368 t.Run("get value in range with default value", func(t *testing.T) {
369 assert.Equal(t, float64(5), sec.Key("FLOAT64").RangeFloat64(5, 0, 1))
370 assert.Equal(t, 7, sec.Key("INT").RangeInt(7, 0, 5))
371 assert.Equal(t, int64(7), sec.Key("INT").RangeInt64(7, 0, 5))
372 assert.Equal(t, ti.String(), sec.Key("TIME").RangeTime(ti, minT, midT).String())
373 })
374 })
375
376 t.Run("get values into slice", func(t *testing.T) {
377 sec := f.Section("array")
378 assert.Equal(t, "en,zh,de", strings.Join(sec.Key("STRINGS").Strings(","), ","))
379 assert.Equal(t, 0, len(sec.Key("STRINGS_404").Strings(",")))
380
381 vals1 := sec.Key("FLOAT64S").Float64s(",")
382 float64sEqual(t, vals1, 1.1, 2.2, 3.3)
383
384 vals2 := sec.Key("INTS").Ints(",")
385 intsEqual(t, vals2, 1, 2, 3)
386
387 vals3 := sec.Key("INTS").Int64s(",")
388 int64sEqual(t, vals3, 1, 2, 3)
389
390 vals4 := sec.Key("UINTS").Uints(",")
391 uintsEqual(t, vals4, 1, 2, 3)
392
393 vals5 := sec.Key("UINTS").Uint64s(",")
394 uint64sEqual(t, vals5, 1, 2, 3)
395
396 vals6 := sec.Key("BOOLS").Bools(",")
397 boolsEqual(t, vals6, true, false, false)
398
399 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
400 require.NoError(t, err)
401 vals7 := sec.Key("TIMES").Times(",")
402 timesEqual(t, vals7, ti, ti, ti)
403 })
404
405 t.Run("test string slice escapes", func(t *testing.T) {
406 sec := f.Section("string escapes")
407 assert.Equal(t, []string{"value1", "value2", "value3"}, sec.Key("key1").Strings(","))
408 assert.Equal(t, []string{"value1, value2"}, sec.Key("key2").Strings(","))
409 assert.Equal(t, []string{`val\ue1`, "value2"}, sec.Key("key3").Strings(","))
410 assert.Equal(t, []string{`value1\`, `value\\2`}, sec.Key("key4").Strings(","))
411 assert.Equal(t, []string{"value1,, value2"}, sec.Key("key5").Strings(",,"))
412 assert.Equal(t, []string{"aaa", "bbb and space", "ccc"}, sec.Key("key6").Strings(" "))
413 })
414
415 t.Run("get valid values into slice", func(t *testing.T) {
416 sec := f.Section("array")
417 vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
418 float64sEqual(t, vals1, 1.1, 2.2, 3.3)
419
420 vals2 := sec.Key("INTS").ValidInts(",")
421 intsEqual(t, vals2, 1, 2, 3)
422
423 vals3 := sec.Key("INTS").ValidInt64s(",")
424 int64sEqual(t, vals3, 1, 2, 3)
425
426 vals4 := sec.Key("UINTS").ValidUints(",")
427 uintsEqual(t, vals4, 1, 2, 3)
428
429 vals5 := sec.Key("UINTS").ValidUint64s(",")
430 uint64sEqual(t, vals5, 1, 2, 3)
431
432 vals6 := sec.Key("BOOLS").ValidBools(",")
433 boolsEqual(t, vals6, true, false, false)
434
435 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
436 require.NoError(t, err)
437 vals7 := sec.Key("TIMES").ValidTimes(",")
438 timesEqual(t, vals7, ti, ti, ti)
439 })
440
441 t.Run("get values one type into slice of another type", func(t *testing.T) {
442 sec := f.Section("array")
443 vals1 := sec.Key("STRINGS").ValidFloat64s(",")
444 assert.Empty(t, vals1)
445
446 vals2 := sec.Key("STRINGS").ValidInts(",")
447 assert.Empty(t, vals2)
448
449 vals3 := sec.Key("STRINGS").ValidInt64s(",")
450 assert.Empty(t, vals3)
451
452 vals4 := sec.Key("STRINGS").ValidUints(",")
453 assert.Empty(t, vals4)
454
455 vals5 := sec.Key("STRINGS").ValidUint64s(",")
456 assert.Empty(t, vals5)
457
458 vals6 := sec.Key("STRINGS").ValidBools(",")
459 assert.Empty(t, vals6)
460
461 vals7 := sec.Key("STRINGS").ValidTimes(",")
462 assert.Empty(t, vals7)
463 })
464
465 t.Run("get valid values into slice without errors", func(t *testing.T) {
466 sec := f.Section("array")
467 vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
468 require.NoError(t, err)
469 float64sEqual(t, vals1, 1.1, 2.2, 3.3)
470
471 vals2, err := sec.Key("INTS").StrictInts(",")
472 require.NoError(t, err)
473 intsEqual(t, vals2, 1, 2, 3)
474
475 vals3, err := sec.Key("INTS").StrictInt64s(",")
476 require.NoError(t, err)
477 int64sEqual(t, vals3, 1, 2, 3)
478
479 vals4, err := sec.Key("UINTS").StrictUints(",")
480 require.NoError(t, err)
481 uintsEqual(t, vals4, 1, 2, 3)
482
483 vals5, err := sec.Key("UINTS").StrictUint64s(",")
484 require.NoError(t, err)
485 uint64sEqual(t, vals5, 1, 2, 3)
486
487 vals6, err := sec.Key("BOOLS").StrictBools(",")
488 require.NoError(t, err)
489 boolsEqual(t, vals6, true, false, false)
490
491 ti, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
492 require.NoError(t, err)
493 vals7, err := sec.Key("TIMES").StrictTimes(",")
494 require.NoError(t, err)
495 timesEqual(t, vals7, ti, ti, ti)
496 })
497
498 t.Run("get invalid values into slice", func(t *testing.T) {
499 sec := f.Section("array")
500 vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
501 assert.Empty(t, vals1)
502 assert.Error(t, err)
503
504 vals2, err := sec.Key("STRINGS").StrictInts(",")
505 assert.Empty(t, vals2)
506 assert.Error(t, err)
507
508 vals3, err := sec.Key("STRINGS").StrictInt64s(",")
509 assert.Empty(t, vals3)
510 assert.Error(t, err)
511
512 vals4, err := sec.Key("STRINGS").StrictUints(",")
513 assert.Empty(t, vals4)
514 assert.Error(t, err)
515
516 vals5, err := sec.Key("STRINGS").StrictUint64s(",")
517 assert.Empty(t, vals5)
518 assert.Error(t, err)
519
520 vals6, err := sec.Key("STRINGS").StrictBools(",")
521 assert.Empty(t, vals6)
522 assert.Error(t, err)
523
524 vals7, err := sec.Key("STRINGS").StrictTimes(",")
525 assert.Empty(t, vals7)
526 assert.Error(t, err)
527 })
528 })
529 }
530
531 func TestKey_ValueWithShadows(t *testing.T) {
532 t.Run("", func(t *testing.T) {
533 f, err := ShadowLoad([]byte(`
534 keyName = value1
535 keyName = value2
536 `))
537 require.NoError(t, err)
538 require.NotNil(t, f)
539
540 k := f.Section("").Key("FakeKey")
541 require.NotNil(t, k)
542 assert.Equal(t, []string{}, k.ValueWithShadows())
543
544 k = f.Section("").Key("keyName")
545 require.NotNil(t, k)
546 assert.Equal(t, []string{"value1", "value2"}, k.ValueWithShadows())
547 })
548 }
549
550 func TestKey_StringsWithShadows(t *testing.T) {
551 t.Run("get strings of shadows of a key", func(t *testing.T) {
552 f, err := ShadowLoad([]byte(""))
553 require.NoError(t, err)
554 require.NotNil(t, f)
555
556 k, err := f.Section("").NewKey("NUMS", "1,2")
557 require.NoError(t, err)
558 require.NotNil(t, k)
559 k, err = f.Section("").NewKey("NUMS", "4,5,6")
560 require.NoError(t, err)
561 require.NotNil(t, k)
562
563 assert.Equal(t, []string{"1", "2", "4", "5", "6"}, k.StringsWithShadows(","))
564 })
565 }
566
567 func TestKey_SetValue(t *testing.T) {
568 t.Run("set value of key", func(t *testing.T) {
569 f := Empty()
570 require.NotNil(t, f)
571
572 k, err := f.Section("").NewKey("NAME", "ini")
573 require.NoError(t, err)
574 require.NotNil(t, k)
575 assert.Equal(t, "ini", k.Value())
576
577 k.SetValue("ini.v1")
578 assert.Equal(t, "ini.v1", k.Value())
579 })
580 }
581
582 func TestKey_NestedValues(t *testing.T) {
583 t.Run("read and write nested values", func(t *testing.T) {
584 f, err := LoadSources(LoadOptions{
585 AllowNestedValues: true,
586 }, []byte(`
587 aws_access_key_id = foo
588 aws_secret_access_key = bar
589 region = us-west-2
590 s3 =
591 max_concurrent_requests=10
592 max_queue_size=1000`))
593 require.NoError(t, err)
594 require.NotNil(t, f)
595
596 assert.Equal(t, []string{"max_concurrent_requests=10", "max_queue_size=1000"}, f.Section("").Key("s3").NestedValues())
597
598 var buf bytes.Buffer
599 _, err = f.WriteTo(&buf)
600 require.NoError(t, err)
601 assert.Equal(t, `aws_access_key_id = foo
602 aws_secret_access_key = bar
603 region = us-west-2
604 s3 =
605 max_concurrent_requests=10
606 max_queue_size=1000
607 `,
608 buf.String(),
609 )
610 })
611 }
612
613 func TestRecursiveValues(t *testing.T) {
614 t.Run("recursive values should not reflect on same key", func(t *testing.T) {
615 f, err := Load([]byte(`
616 NAME = ini
617 expires = yes
618 [package]
619 NAME = %(NAME)s
620 expires = %(expires)s`))
621 require.NoError(t, err)
622 require.NotNil(t, f)
623
624 assert.Equal(t, "ini", f.Section("package").Key("NAME").String())
625 assert.Equal(t, "yes", f.Section("package").Key("expires").String())
626 })
627
628 t.Run("recursive value with no target found", func(t *testing.T) {
629 f, err := Load([]byte(`
630 [foo]
631 bar = %(missing)s
632 `))
633 require.NoError(t, err)
634 require.NotNil(t, f)
635
636 assert.Equal(t, "%(missing)s", f.Section("foo").Key("bar").String())
637 })
638 }
639
View as plain text