OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / magiconair / properties / properties_test.go
1 // Copyright 2017 Frank Schroeder. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package properties
6
7 import (
8         "bytes"
9         "flag"
10         "fmt"
11         "math"
12         "os"
13         "reflect"
14         "strings"
15         "testing"
16         "time"
17
18         "github.com/magiconair/properties/assert"
19 )
20
21 var verbose = flag.Bool("verbose", false, "Verbose output")
22
23 func init() {
24         ErrorHandler = PanicHandler
25 }
26
27 // ----------------------------------------------------------------------------
28
29 // define test cases in the form of
30 // {"input", "key1", "value1", "key2", "value2", ...}
31 var complexTests = [][]string{
32         // whitespace prefix
33         {" key=value", "key", "value"},     // SPACE prefix
34         {"\fkey=value", "key", "value"},    // FF prefix
35         {"\tkey=value", "key", "value"},    // TAB prefix
36         {" \f\tkey=value", "key", "value"}, // mix prefix
37
38         // multiple keys
39         {"key1=value1\nkey2=value2\n", "key1", "value1", "key2", "value2"},
40         {"key1=value1\rkey2=value2\r", "key1", "value1", "key2", "value2"},
41         {"key1=value1\r\nkey2=value2\r\n", "key1", "value1", "key2", "value2"},
42
43         // blank lines
44         {"\nkey=value\n", "key", "value"},
45         {"\rkey=value\r", "key", "value"},
46         {"\r\nkey=value\r\n", "key", "value"},
47
48         // escaped chars in key
49         {"k\\ ey = value", "k ey", "value"},
50         {"k\\:ey = value", "k:ey", "value"},
51         {"k\\=ey = value", "k=ey", "value"},
52         {"k\\fey = value", "k\fey", "value"},
53         {"k\\ney = value", "k\ney", "value"},
54         {"k\\rey = value", "k\rey", "value"},
55         {"k\\tey = value", "k\tey", "value"},
56
57         // escaped chars in value
58         {"key = v\\ alue", "key", "v alue"},
59         {"key = v\\:alue", "key", "v:alue"},
60         {"key = v\\=alue", "key", "v=alue"},
61         {"key = v\\falue", "key", "v\falue"},
62         {"key = v\\nalue", "key", "v\nalue"},
63         {"key = v\\ralue", "key", "v\ralue"},
64         {"key = v\\talue", "key", "v\talue"},
65
66         // silently dropped escape character
67         {"k\\zey = value", "kzey", "value"},
68         {"key = v\\zalue", "key", "vzalue"},
69
70         // unicode literals
71         {"key\\u2318 = value", "key⌘", "value"},
72         {"k\\u2318ey = value", "k⌘ey", "value"},
73         {"key = value\\u2318", "key", "value⌘"},
74         {"key = valu\\u2318e", "key", "valu⌘e"},
75
76         // multiline values
77         {"key = valueA,\\\n    valueB", "key", "valueA,valueB"},   // SPACE indent
78         {"key = valueA,\\\n\f\f\fvalueB", "key", "valueA,valueB"}, // FF indent
79         {"key = valueA,\\\n\t\t\tvalueB", "key", "valueA,valueB"}, // TAB indent
80         {"key = valueA,\\\n \f\tvalueB", "key", "valueA,valueB"},  // mix indent
81
82         // comments
83         {"# this is a comment\n! and so is this\nkey1=value1\nkey#2=value#2\n\nkey!3=value!3\n# and another one\n! and the final one", "key1", "value1", "key#2", "value#2", "key!3", "value!3"},
84
85         // expansion tests
86         {"key=value\nkey2=${key}", "key", "value", "key2", "value"},
87         {"key=value\nkey2=aa${key}", "key", "value", "key2", "aavalue"},
88         {"key=value\nkey2=${key}bb", "key", "value", "key2", "valuebb"},
89         {"key=value\nkey2=aa${key}bb", "key", "value", "key2", "aavaluebb"},
90         {"key=value\nkey2=${key}\nkey3=${key2}", "key", "value", "key2", "value", "key3", "value"},
91         {"key=${USER}", "key", os.Getenv("USER")},
92         {"key=${USER}\nUSER=value", "key", "value", "USER", "value"},
93 }
94
95 // ----------------------------------------------------------------------------
96
97 var commentTests = []struct {
98         input, key, value string
99         comments          []string
100 }{
101         {"key=value", "key", "value", nil},
102         {"#\nkey=value", "key", "value", []string{""}},
103         {"#comment\nkey=value", "key", "value", []string{"comment"}},
104         {"# comment\nkey=value", "key", "value", []string{"comment"}},
105         {"#  comment\nkey=value", "key", "value", []string{"comment"}},
106         {"# comment\n\nkey=value", "key", "value", []string{"comment"}},
107         {"# comment1\n# comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}},
108         {"# comment1\n\n# comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}},
109         {"!comment\nkey=value", "key", "value", []string{"comment"}},
110         {"! comment\nkey=value", "key", "value", []string{"comment"}},
111         {"!  comment\nkey=value", "key", "value", []string{"comment"}},
112         {"! comment\n\nkey=value", "key", "value", []string{"comment"}},
113         {"! comment1\n! comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}},
114         {"! comment1\n\n! comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}},
115 }
116
117 // ----------------------------------------------------------------------------
118
119 var errorTests = []struct {
120         input, msg string
121 }{
122         // unicode literals
123         {"key\\u1 = value", "invalid unicode literal"},
124         {"key\\u12 = value", "invalid unicode literal"},
125         {"key\\u123 = value", "invalid unicode literal"},
126         {"key\\u123g = value", "invalid unicode literal"},
127         {"key\\u123", "invalid unicode literal"},
128
129         // circular references
130         {"key=${key}", "circular reference"},
131         {"key1=${key2}\nkey2=${key1}", "circular reference"},
132
133         // malformed expressions
134         {"key=${ke", "malformed expression"},
135         {"key=valu${ke", "malformed expression"},
136 }
137
138 // ----------------------------------------------------------------------------
139
140 var writeTests = []struct {
141         input, output, encoding string
142 }{
143         // ISO-8859-1 tests
144         {"key = value", "key = value\n", "ISO-8859-1"},
145         {"key = value \\\n   continued", "key = value continued\n", "ISO-8859-1"},
146         {"key⌘ = value", "key\\u2318 = value\n", "ISO-8859-1"},
147         {"ke\\ \\:y = value", "ke\\ \\:y = value\n", "ISO-8859-1"},
148
149         // UTF-8 tests
150         {"key = value", "key = value\n", "UTF-8"},
151         {"key = value \\\n   continued", "key = value continued\n", "UTF-8"},
152         {"key⌘ = value⌘", "key⌘ = value⌘\n", "UTF-8"},
153         {"ke\\ \\:y = value", "ke\\ \\:y = value\n", "UTF-8"},
154 }
155
156 // ----------------------------------------------------------------------------
157
158 var writeCommentTests = []struct {
159         input, output, encoding string
160 }{
161         // ISO-8859-1 tests
162         {"key = value", "key = value\n", "ISO-8859-1"},
163         {"#\nkey = value", "key = value\n", "ISO-8859-1"},
164         {"#\n#\n#\nkey = value", "key = value\n", "ISO-8859-1"},
165         {"# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
166         {"\n# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
167         {"# comment\n\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
168         {"# comment1\n# comment2\nkey = value", "# comment1\n# comment2\nkey = value\n", "ISO-8859-1"},
169         {"#comment1\nkey1 = value1\n#comment2\nkey2 = value2", "# comment1\nkey1 = value1\n\n# comment2\nkey2 = value2\n", "ISO-8859-1"},
170
171         // UTF-8 tests
172         {"key = value", "key = value\n", "UTF-8"},
173         {"# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
174         {"\n# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
175         {"# comment⌘\n\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
176         {"# comment1⌘\n# comment2⌘\nkey = value⌘", "# comment1⌘\n# comment2⌘\nkey = value⌘\n", "UTF-8"},
177         {"#comment1⌘\nkey1 = value1⌘\n#comment2⌘\nkey2 = value2⌘", "# comment1⌘\nkey1 = value1⌘\n\n# comment2⌘\nkey2 = value2⌘\n", "UTF-8"},
178 }
179
180 // ----------------------------------------------------------------------------
181
182 var boolTests = []struct {
183         input, key string
184         def, value bool
185 }{
186         // valid values for TRUE
187         {"key = 1", "key", false, true},
188         {"key = on", "key", false, true},
189         {"key = On", "key", false, true},
190         {"key = ON", "key", false, true},
191         {"key = true", "key", false, true},
192         {"key = True", "key", false, true},
193         {"key = TRUE", "key", false, true},
194         {"key = yes", "key", false, true},
195         {"key = Yes", "key", false, true},
196         {"key = YES", "key", false, true},
197
198         // valid values for FALSE (all other)
199         {"key = 0", "key", true, false},
200         {"key = off", "key", true, false},
201         {"key = false", "key", true, false},
202         {"key = no", "key", true, false},
203
204         // non existent key
205         {"key = true", "key2", false, false},
206 }
207
208 // ----------------------------------------------------------------------------
209
210 var durationTests = []struct {
211         input, key string
212         def, value time.Duration
213 }{
214         // valid values
215         {"key = 1", "key", 999, 1},
216         {"key = 0", "key", 999, 0},
217         {"key = -1", "key", 999, -1},
218         {"key = 0123", "key", 999, 123},
219
220         // invalid values
221         {"key = 0xff", "key", 999, 999},
222         {"key = 1.0", "key", 999, 999},
223         {"key = a", "key", 999, 999},
224
225         // non existent key
226         {"key = 1", "key2", 999, 999},
227 }
228
229 // ----------------------------------------------------------------------------
230
231 var parsedDurationTests = []struct {
232         input, key string
233         def, value time.Duration
234 }{
235         // valid values
236         {"key = -1ns", "key", 999, -1 * time.Nanosecond},
237         {"key = 300ms", "key", 999, 300 * time.Millisecond},
238         {"key = 5s", "key", 999, 5 * time.Second},
239         {"key = 3h", "key", 999, 3 * time.Hour},
240         {"key = 2h45m", "key", 999, 2*time.Hour + 45*time.Minute},
241
242         // invalid values
243         {"key = 0xff", "key", 999, 999},
244         {"key = 1.0", "key", 999, 999},
245         {"key = a", "key", 999, 999},
246         {"key = 1", "key", 999, 999},
247         {"key = 0", "key", 999, 0},
248
249         // non existent key
250         {"key = 1", "key2", 999, 999},
251 }
252
253 // ----------------------------------------------------------------------------
254
255 var floatTests = []struct {
256         input, key string
257         def, value float64
258 }{
259         // valid values
260         {"key = 1.0", "key", 999, 1.0},
261         {"key = 0.0", "key", 999, 0.0},
262         {"key = -1.0", "key", 999, -1.0},
263         {"key = 1", "key", 999, 1},
264         {"key = 0", "key", 999, 0},
265         {"key = -1", "key", 999, -1},
266         {"key = 0123", "key", 999, 123},
267
268         // invalid values
269         {"key = 0xff", "key", 999, 999},
270         {"key = a", "key", 999, 999},
271
272         // non existent key
273         {"key = 1", "key2", 999, 999},
274 }
275
276 // ----------------------------------------------------------------------------
277
278 var int64Tests = []struct {
279         input, key string
280         def, value int64
281 }{
282         // valid values
283         {"key = 1", "key", 999, 1},
284         {"key = 0", "key", 999, 0},
285         {"key = -1", "key", 999, -1},
286         {"key = 0123", "key", 999, 123},
287
288         // invalid values
289         {"key = 0xff", "key", 999, 999},
290         {"key = 1.0", "key", 999, 999},
291         {"key = a", "key", 999, 999},
292
293         // non existent key
294         {"key = 1", "key2", 999, 999},
295 }
296
297 // ----------------------------------------------------------------------------
298
299 var uint64Tests = []struct {
300         input, key string
301         def, value uint64
302 }{
303         // valid values
304         {"key = 1", "key", 999, 1},
305         {"key = 0", "key", 999, 0},
306         {"key = 0123", "key", 999, 123},
307
308         // invalid values
309         {"key = -1", "key", 999, 999},
310         {"key = 0xff", "key", 999, 999},
311         {"key = 1.0", "key", 999, 999},
312         {"key = a", "key", 999, 999},
313
314         // non existent key
315         {"key = 1", "key2", 999, 999},
316 }
317
318 // ----------------------------------------------------------------------------
319
320 var stringTests = []struct {
321         input, key string
322         def, value string
323 }{
324         // valid values
325         {"key = abc", "key", "def", "abc"},
326
327         // non existent key
328         {"key = abc", "key2", "def", "def"},
329 }
330
331 // ----------------------------------------------------------------------------
332
333 var keysTests = []struct {
334         input string
335         keys  []string
336 }{
337         {"", []string{}},
338         {"key = abc", []string{"key"}},
339         {"key = abc\nkey2=def", []string{"key", "key2"}},
340         {"key2 = abc\nkey=def", []string{"key2", "key"}},
341         {"key = abc\nkey=def", []string{"key"}},
342 }
343
344 // ----------------------------------------------------------------------------
345
346 var filterTests = []struct {
347         input   string
348         pattern string
349         keys    []string
350         err     string
351 }{
352         {"", "", []string{}, ""},
353         {"", "abc", []string{}, ""},
354         {"key=value", "", []string{"key"}, ""},
355         {"key=value", "key=", []string{}, ""},
356         {"key=value\nfoo=bar", "", []string{"foo", "key"}, ""},
357         {"key=value\nfoo=bar", "f", []string{"foo"}, ""},
358         {"key=value\nfoo=bar", "fo", []string{"foo"}, ""},
359         {"key=value\nfoo=bar", "foo", []string{"foo"}, ""},
360         {"key=value\nfoo=bar", "fooo", []string{}, ""},
361         {"key=value\nkey2=value2\nfoo=bar", "ey", []string{"key", "key2"}, ""},
362         {"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}, ""},
363         {"key=value\nkey2=value2\nfoo=bar", "^key", []string{"key", "key2"}, ""},
364         {"key=value\nkey2=value2\nfoo=bar", "^(key|foo)", []string{"foo", "key", "key2"}, ""},
365         {"key=value\nkey2=value2\nfoo=bar", "[ abc", nil, "error parsing regexp.*"},
366 }
367
368 // ----------------------------------------------------------------------------
369
370 var filterPrefixTests = []struct {
371         input  string
372         prefix string
373         keys   []string
374 }{
375         {"", "", []string{}},
376         {"", "abc", []string{}},
377         {"key=value", "", []string{"key"}},
378         {"key=value", "key=", []string{}},
379         {"key=value\nfoo=bar", "", []string{"foo", "key"}},
380         {"key=value\nfoo=bar", "f", []string{"foo"}},
381         {"key=value\nfoo=bar", "fo", []string{"foo"}},
382         {"key=value\nfoo=bar", "foo", []string{"foo"}},
383         {"key=value\nfoo=bar", "fooo", []string{}},
384         {"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}},
385 }
386
387 // ----------------------------------------------------------------------------
388
389 var filterStripPrefixTests = []struct {
390         input  string
391         prefix string
392         keys   []string
393 }{
394         {"", "", []string{}},
395         {"", "abc", []string{}},
396         {"key=value", "", []string{"key"}},
397         {"key=value", "key=", []string{}},
398         {"key=value\nfoo=bar", "", []string{"foo", "key"}},
399         {"key=value\nfoo=bar", "f", []string{"foo"}},
400         {"key=value\nfoo=bar", "fo", []string{"foo"}},
401         {"key=value\nfoo=bar", "foo", []string{"foo"}},
402         {"key=value\nfoo=bar", "fooo", []string{}},
403         {"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}},
404 }
405
406 // ----------------------------------------------------------------------------
407
408 var setTests = []struct {
409         input      string
410         key, value string
411         prev       string
412         ok         bool
413         err        string
414         keys       []string
415 }{
416         {"", "", "", "", false, "", []string{}},
417         {"", "key", "value", "", false, "", []string{"key"}},
418         {"key=value", "key2", "value2", "", false, "", []string{"key", "key2"}},
419         {"key=value", "abc", "value3", "", false, "", []string{"key", "abc"}},
420         {"key=value", "key", "value3", "value", true, "", []string{"key"}},
421 }
422
423 // ----------------------------------------------------------------------------
424
425 // TestBasic tests basic single key/value combinations with all possible
426 // whitespace, delimiter and newline permutations.
427 func TestBasic(t *testing.T) {
428         testWhitespaceAndDelimiterCombinations(t, "key", "")
429         testWhitespaceAndDelimiterCombinations(t, "key", "value")
430         testWhitespaceAndDelimiterCombinations(t, "key", "value   ")
431 }
432
433 func TestComplex(t *testing.T) {
434         for _, test := range complexTests {
435                 testKeyValue(t, test[0], test[1:]...)
436         }
437 }
438
439 func TestErrors(t *testing.T) {
440         for _, test := range errorTests {
441                 _, err := Load([]byte(test.input), ISO_8859_1)
442                 assert.Equal(t, err != nil, true, "want error")
443                 assert.Equal(t, strings.Contains(err.Error(), test.msg), true)
444         }
445 }
446
447 func TestDisableExpansion(t *testing.T) {
448         input := "key=value\nkey2=${key}"
449         p := mustParse(t, input)
450         p.DisableExpansion = true
451         assert.Equal(t, p.MustGet("key"), "value")
452         assert.Equal(t, p.MustGet("key2"), "${key}")
453
454         // with expansion disabled we can introduce circular references
455         p.MustSet("keyA", "${keyB}")
456         p.MustSet("keyB", "${keyA}")
457         assert.Equal(t, p.MustGet("keyA"), "${keyB}")
458         assert.Equal(t, p.MustGet("keyB"), "${keyA}")
459 }
460
461 func TestDisableExpansionStillUpdatesKeys(t *testing.T) {
462         p := NewProperties()
463         p.MustSet("p1", "a")
464         assert.Equal(t, p.Keys(), []string{"p1"})
465         assert.Equal(t, p.String(), "p1 = a\n")
466
467         p.DisableExpansion = true
468         p.MustSet("p2", "b")
469
470         assert.Equal(t, p.Keys(), []string{"p1", "p2"})
471         assert.Equal(t, p.String(), "p1 = a\np2 = b\n")
472 }
473
474 func TestMustGet(t *testing.T) {
475         input := "key = value\nkey2 = ghi"
476         p := mustParse(t, input)
477         assert.Equal(t, p.MustGet("key"), "value")
478         assert.Panic(t, func() { p.MustGet("invalid") }, "unknown property: invalid")
479 }
480
481 func TestGetBool(t *testing.T) {
482         for _, test := range boolTests {
483                 p := mustParse(t, test.input)
484                 assert.Equal(t, p.Len(), 1)
485                 assert.Equal(t, p.GetBool(test.key, test.def), test.value)
486         }
487 }
488
489 func TestMustGetBool(t *testing.T) {
490         input := "key = true\nkey2 = ghi"
491         p := mustParse(t, input)
492         assert.Equal(t, p.MustGetBool("key"), true)
493         assert.Panic(t, func() { p.MustGetBool("invalid") }, "unknown property: invalid")
494 }
495
496 func TestGetDuration(t *testing.T) {
497         for _, test := range durationTests {
498                 p := mustParse(t, test.input)
499                 assert.Equal(t, p.Len(), 1)
500                 assert.Equal(t, p.GetDuration(test.key, test.def), test.value)
501         }
502 }
503
504 func TestMustGetDuration(t *testing.T) {
505         input := "key = 123\nkey2 = ghi"
506         p := mustParse(t, input)
507         assert.Equal(t, p.MustGetDuration("key"), time.Duration(123))
508         assert.Panic(t, func() { p.MustGetDuration("key2") }, "strconv.ParseInt: parsing.*")
509         assert.Panic(t, func() { p.MustGetDuration("invalid") }, "unknown property: invalid")
510 }
511
512 func TestGetParsedDuration(t *testing.T) {
513         for _, test := range parsedDurationTests {
514                 p := mustParse(t, test.input)
515                 assert.Equal(t, p.Len(), 1)
516                 assert.Equal(t, p.GetParsedDuration(test.key, test.def), test.value)
517         }
518 }
519
520 func TestMustGetParsedDuration(t *testing.T) {
521         input := "key = 123ms\nkey2 = ghi"
522         p := mustParse(t, input)
523         assert.Equal(t, p.MustGetParsedDuration("key"), 123*time.Millisecond)
524         assert.Panic(t, func() { p.MustGetParsedDuration("key2") }, "time: invalid duration ghi")
525         assert.Panic(t, func() { p.MustGetParsedDuration("invalid") }, "unknown property: invalid")
526 }
527
528 func TestGetFloat64(t *testing.T) {
529         for _, test := range floatTests {
530                 p := mustParse(t, test.input)
531                 assert.Equal(t, p.Len(), 1)
532                 assert.Equal(t, p.GetFloat64(test.key, test.def), test.value)
533         }
534 }
535
536 func TestMustGetFloat64(t *testing.T) {
537         input := "key = 123\nkey2 = ghi"
538         p := mustParse(t, input)
539         assert.Equal(t, p.MustGetFloat64("key"), float64(123))
540         assert.Panic(t, func() { p.MustGetFloat64("key2") }, "strconv.ParseFloat: parsing.*")
541         assert.Panic(t, func() { p.MustGetFloat64("invalid") }, "unknown property: invalid")
542 }
543
544 func TestGetInt(t *testing.T) {
545         for _, test := range int64Tests {
546                 p := mustParse(t, test.input)
547                 assert.Equal(t, p.Len(), 1)
548                 assert.Equal(t, p.GetInt(test.key, int(test.def)), int(test.value))
549         }
550 }
551
552 func TestMustGetInt(t *testing.T) {
553         input := "key = 123\nkey2 = ghi"
554         p := mustParse(t, input)
555         assert.Equal(t, p.MustGetInt("key"), int(123))
556         assert.Panic(t, func() { p.MustGetInt("key2") }, "strconv.ParseInt: parsing.*")
557         assert.Panic(t, func() { p.MustGetInt("invalid") }, "unknown property: invalid")
558 }
559
560 func TestGetInt64(t *testing.T) {
561         for _, test := range int64Tests {
562                 p := mustParse(t, test.input)
563                 assert.Equal(t, p.Len(), 1)
564                 assert.Equal(t, p.GetInt64(test.key, test.def), test.value)
565         }
566 }
567
568 func TestMustGetInt64(t *testing.T) {
569         input := "key = 123\nkey2 = ghi"
570         p := mustParse(t, input)
571         assert.Equal(t, p.MustGetInt64("key"), int64(123))
572         assert.Panic(t, func() { p.MustGetInt64("key2") }, "strconv.ParseInt: parsing.*")
573         assert.Panic(t, func() { p.MustGetInt64("invalid") }, "unknown property: invalid")
574 }
575
576 func TestGetUint(t *testing.T) {
577         for _, test := range uint64Tests {
578                 p := mustParse(t, test.input)
579                 assert.Equal(t, p.Len(), 1)
580                 assert.Equal(t, p.GetUint(test.key, uint(test.def)), uint(test.value))
581         }
582 }
583
584 func TestMustGetUint(t *testing.T) {
585         input := "key = 123\nkey2 = ghi"
586         p := mustParse(t, input)
587         assert.Equal(t, p.MustGetUint("key"), uint(123))
588         assert.Panic(t, func() { p.MustGetUint64("key2") }, "strconv.ParseUint: parsing.*")
589         assert.Panic(t, func() { p.MustGetUint64("invalid") }, "unknown property: invalid")
590 }
591
592 func TestGetUint64(t *testing.T) {
593         for _, test := range uint64Tests {
594                 p := mustParse(t, test.input)
595                 assert.Equal(t, p.Len(), 1)
596                 assert.Equal(t, p.GetUint64(test.key, test.def), test.value)
597         }
598 }
599
600 func TestMustGetUint64(t *testing.T) {
601         input := "key = 123\nkey2 = ghi"
602         p := mustParse(t, input)
603         assert.Equal(t, p.MustGetUint64("key"), uint64(123))
604         assert.Panic(t, func() { p.MustGetUint64("key2") }, "strconv.ParseUint: parsing.*")
605         assert.Panic(t, func() { p.MustGetUint64("invalid") }, "unknown property: invalid")
606 }
607
608 func TestGetString(t *testing.T) {
609         for _, test := range stringTests {
610                 p := mustParse(t, test.input)
611                 assert.Equal(t, p.Len(), 1)
612                 assert.Equal(t, p.GetString(test.key, test.def), test.value)
613         }
614 }
615
616 func TestMustGetString(t *testing.T) {
617         input := `key = value`
618         p := mustParse(t, input)
619         assert.Equal(t, p.MustGetString("key"), "value")
620         assert.Panic(t, func() { p.MustGetString("invalid") }, "unknown property: invalid")
621 }
622
623 func TestComment(t *testing.T) {
624         for _, test := range commentTests {
625                 p := mustParse(t, test.input)
626                 assert.Equal(t, p.MustGetString(test.key), test.value)
627                 assert.Equal(t, p.GetComments(test.key), test.comments)
628                 if test.comments != nil {
629                         assert.Equal(t, p.GetComment(test.key), test.comments[len(test.comments)-1])
630                 } else {
631                         assert.Equal(t, p.GetComment(test.key), "")
632                 }
633
634                 // test setting comments
635                 if len(test.comments) > 0 {
636                         // set single comment
637                         p.ClearComments()
638                         assert.Equal(t, len(p.c), 0)
639                         p.SetComment(test.key, test.comments[0])
640                         assert.Equal(t, p.GetComment(test.key), test.comments[0])
641
642                         // set multiple comments
643                         p.ClearComments()
644                         assert.Equal(t, len(p.c), 0)
645                         p.SetComments(test.key, test.comments)
646                         assert.Equal(t, p.GetComments(test.key), test.comments)
647
648                         // clear comments for a key
649                         p.SetComments(test.key, nil)
650                         assert.Equal(t, p.GetComment(test.key), "")
651                         assert.Equal(t, p.GetComments(test.key), ([]string)(nil))
652                 }
653         }
654 }
655
656 func TestFilter(t *testing.T) {
657         for _, test := range filterTests {
658                 p := mustParse(t, test.input)
659                 pp, err := p.Filter(test.pattern)
660                 if err != nil {
661                         assert.Matches(t, err.Error(), test.err)
662                         continue
663                 }
664                 assert.Equal(t, pp != nil, true, "want properties")
665                 assert.Equal(t, pp.Len(), len(test.keys))
666                 for _, key := range test.keys {
667                         v1, ok1 := p.Get(key)
668                         v2, ok2 := pp.Get(key)
669                         assert.Equal(t, ok1, true)
670                         assert.Equal(t, ok2, true)
671                         assert.Equal(t, v1, v2)
672                 }
673         }
674 }
675
676 func TestFilterPrefix(t *testing.T) {
677         for _, test := range filterPrefixTests {
678                 p := mustParse(t, test.input)
679                 pp := p.FilterPrefix(test.prefix)
680                 assert.Equal(t, pp != nil, true, "want properties")
681                 assert.Equal(t, pp.Len(), len(test.keys))
682                 for _, key := range test.keys {
683                         v1, ok1 := p.Get(key)
684                         v2, ok2 := pp.Get(key)
685                         assert.Equal(t, ok1, true)
686                         assert.Equal(t, ok2, true)
687                         assert.Equal(t, v1, v2)
688                 }
689         }
690 }
691
692 func TestFilterStripPrefix(t *testing.T) {
693         for _, test := range filterStripPrefixTests {
694                 p := mustParse(t, test.input)
695                 pp := p.FilterPrefix(test.prefix)
696                 assert.Equal(t, pp != nil, true, "want properties")
697                 assert.Equal(t, pp.Len(), len(test.keys))
698                 for _, key := range test.keys {
699                         v1, ok1 := p.Get(key)
700                         v2, ok2 := pp.Get(key)
701                         assert.Equal(t, ok1, true)
702                         assert.Equal(t, ok2, true)
703                         assert.Equal(t, v1, v2)
704                 }
705         }
706 }
707
708 func TestKeys(t *testing.T) {
709         for _, test := range keysTests {
710                 p := mustParse(t, test.input)
711                 assert.Equal(t, p.Len(), len(test.keys))
712                 assert.Equal(t, len(p.Keys()), len(test.keys))
713                 assert.Equal(t, p.Keys(), test.keys)
714         }
715 }
716
717 func TestSet(t *testing.T) {
718         for _, test := range setTests {
719                 p := mustParse(t, test.input)
720                 prev, ok, err := p.Set(test.key, test.value)
721                 if test.err != "" {
722                         assert.Matches(t, err.Error(), test.err)
723                         continue
724                 }
725
726                 assert.Equal(t, err, nil)
727                 assert.Equal(t, ok, test.ok)
728                 if ok {
729                         assert.Equal(t, prev, test.prev)
730                 }
731                 assert.Equal(t, p.Keys(), test.keys)
732         }
733 }
734
735 func TestSetValue(t *testing.T) {
736         tests := []interface{}{
737                 true, false,
738                 int8(123), int16(123), int32(123), int64(123), int(123),
739                 uint8(123), uint16(123), uint32(123), uint64(123), uint(123),
740                 float32(1.23), float64(1.23),
741                 "abc",
742         }
743
744         for _, v := range tests {
745                 p := NewProperties()
746                 err := p.SetValue("x", v)
747                 assert.Equal(t, err, nil)
748                 assert.Equal(t, p.GetString("x", ""), fmt.Sprintf("%v", v))
749         }
750 }
751
752 func TestMustSet(t *testing.T) {
753         input := "key=${key}"
754         p := mustParse(t, input)
755         assert.Panic(t, func() { p.MustSet("key", "${key}") }, "circular reference .*")
756 }
757
758 func TestWrite(t *testing.T) {
759         for _, test := range writeTests {
760                 p, err := parse(test.input)
761
762                 buf := new(bytes.Buffer)
763                 var n int
764                 switch test.encoding {
765                 case "UTF-8":
766                         n, err = p.Write(buf, UTF8)
767                 case "ISO-8859-1":
768                         n, err = p.Write(buf, ISO_8859_1)
769                 }
770                 assert.Equal(t, err, nil)
771                 s := string(buf.Bytes())
772                 assert.Equal(t, n, len(test.output), fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
773                 assert.Equal(t, s, test.output, fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
774         }
775 }
776
777 func TestWriteComment(t *testing.T) {
778         for _, test := range writeCommentTests {
779                 p, err := parse(test.input)
780
781                 buf := new(bytes.Buffer)
782                 var n int
783                 switch test.encoding {
784                 case "UTF-8":
785                         n, err = p.WriteComment(buf, "# ", UTF8)
786                 case "ISO-8859-1":
787                         n, err = p.WriteComment(buf, "# ", ISO_8859_1)
788                 }
789                 assert.Equal(t, err, nil)
790                 s := string(buf.Bytes())
791                 assert.Equal(t, n, len(test.output), fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
792                 assert.Equal(t, s, test.output, fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
793         }
794 }
795
796 func TestCustomExpansionExpression(t *testing.T) {
797         testKeyValuePrePostfix(t, "*[", "]*", "key=value\nkey2=*[key]*", "key", "value", "key2", "value")
798 }
799
800 func TestPanicOn32BitIntOverflow(t *testing.T) {
801         is32Bit = true
802         var min, max int64 = math.MinInt32 - 1, math.MaxInt32 + 1
803         input := fmt.Sprintf("min=%d\nmax=%d", min, max)
804         p := mustParse(t, input)
805         assert.Equal(t, p.MustGetInt64("min"), min)
806         assert.Equal(t, p.MustGetInt64("max"), max)
807         assert.Panic(t, func() { p.MustGetInt("min") }, ".* out of range")
808         assert.Panic(t, func() { p.MustGetInt("max") }, ".* out of range")
809 }
810
811 func TestPanicOn32BitUintOverflow(t *testing.T) {
812         is32Bit = true
813         var max uint64 = math.MaxUint32 + 1
814         input := fmt.Sprintf("max=%d", max)
815         p := mustParse(t, input)
816         assert.Equal(t, p.MustGetUint64("max"), max)
817         assert.Panic(t, func() { p.MustGetUint("max") }, ".* out of range")
818 }
819
820 func TestDeleteKey(t *testing.T) {
821         input := "#comments should also be gone\nkey=to-be-deleted\nsecond=key"
822         p := mustParse(t, input)
823         assert.Equal(t, len(p.m), 2)
824         assert.Equal(t, len(p.c), 1)
825         assert.Equal(t, len(p.k), 2)
826         p.Delete("key")
827         assert.Equal(t, len(p.m), 1)
828         assert.Equal(t, len(p.c), 0)
829         assert.Equal(t, len(p.k), 1)
830         assert.Equal(t, p.k[0], "second")
831         assert.Equal(t, p.m["second"], "key")
832 }
833
834 func TestDeleteUnknownKey(t *testing.T) {
835         input := "#comments should also be gone\nkey=to-be-deleted"
836         p := mustParse(t, input)
837         assert.Equal(t, len(p.m), 1)
838         assert.Equal(t, len(p.c), 1)
839         assert.Equal(t, len(p.k), 1)
840         p.Delete("wrong-key")
841         assert.Equal(t, len(p.m), 1)
842         assert.Equal(t, len(p.c), 1)
843         assert.Equal(t, len(p.k), 1)
844 }
845
846 func TestMerge(t *testing.T) {
847         input1 := "#comment\nkey=value\nkey2=value2"
848         input2 := "#another comment\nkey=another value\nkey3=value3"
849         p1 := mustParse(t, input1)
850         p2 := mustParse(t, input2)
851         p1.Merge(p2)
852         assert.Equal(t, len(p1.m), 3)
853         assert.Equal(t, len(p1.c), 1)
854         assert.Equal(t, len(p1.k), 3)
855         assert.Equal(t, p1.MustGet("key"), "another value")
856         assert.Equal(t, p1.GetComment("key"), "another comment")
857 }
858
859 func TestMap(t *testing.T) {
860         input := "key=value\nabc=def"
861         p := mustParse(t, input)
862         m := map[string]string{"key": "value", "abc": "def"}
863         assert.Equal(t, p.Map(), m)
864 }
865
866 func TestFilterFunc(t *testing.T) {
867         input := "key=value\nabc=def"
868         p := mustParse(t, input)
869         pp := p.FilterFunc(func(k, v string) bool {
870                 return k != "abc"
871         })
872         m := map[string]string{"key": "value"}
873         assert.Equal(t, pp.Map(), m)
874 }
875
876 // ----------------------------------------------------------------------------
877
878 // tests all combinations of delimiters, leading and/or trailing whitespace and newlines.
879 func testWhitespaceAndDelimiterCombinations(t *testing.T, key, value string) {
880         whitespace := []string{"", " ", "\f", "\t"}
881         delimiters := []string{"", " ", "=", ":"}
882         newlines := []string{"", "\r", "\n", "\r\n"}
883         for _, dl := range delimiters {
884                 for _, ws1 := range whitespace {
885                         for _, ws2 := range whitespace {
886                                 for _, nl := range newlines {
887                                         // skip the one case where there is nothing between a key and a value
888                                         if ws1 == "" && dl == "" && ws2 == "" && value != "" {
889                                                 continue
890                                         }
891
892                                         input := fmt.Sprintf("%s%s%s%s%s%s", key, ws1, dl, ws2, value, nl)
893                                         testKeyValue(t, input, key, value)
894                                 }
895                         }
896                 }
897         }
898 }
899
900 // tests whether key/value pairs exist for a given input.
901 // keyvalues is expected to be an even number of strings of "key", "value", ...
902 func testKeyValue(t *testing.T, input string, keyvalues ...string) {
903         testKeyValuePrePostfix(t, "${", "}", input, keyvalues...)
904 }
905
906 // tests whether key/value pairs exist for a given input.
907 // keyvalues is expected to be an even number of strings of "key", "value", ...
908 func testKeyValuePrePostfix(t *testing.T, prefix, postfix, input string, keyvalues ...string) {
909         p, err := Load([]byte(input), ISO_8859_1)
910         assert.Equal(t, err, nil)
911         p.Prefix = prefix
912         p.Postfix = postfix
913         assertKeyValues(t, input, p, keyvalues...)
914 }
915
916 // tests whether key/value pairs exist for a given input.
917 // keyvalues is expected to be an even number of strings of "key", "value", ...
918 func assertKeyValues(t *testing.T, input string, p *Properties, keyvalues ...string) {
919         assert.Equal(t, p != nil, true, "want properties")
920         assert.Equal(t, 2*p.Len(), len(keyvalues), "Odd number of key/value pairs.")
921
922         for i := 0; i < len(keyvalues); i += 2 {
923                 key, value := keyvalues[i], keyvalues[i+1]
924                 v, ok := p.Get(key)
925                 if !ok {
926                         t.Errorf("No key %q found (input=%q)", key, input)
927                 }
928                 if got, want := v, value; !reflect.DeepEqual(got, want) {
929                         t.Errorf("Value %q does not match %q (input=%q)", v, value, input)
930                 }
931         }
932 }
933
934 func mustParse(t *testing.T, s string) *Properties {
935         p, err := parse(s)
936         if err != nil {
937                 t.Fatalf("parse failed with %s", err)
938         }
939         return p
940 }
941
942 // prints to stderr if the -verbose flag was given.
943 func printf(format string, args ...interface{}) {
944         if *verbose {
945                 fmt.Fprintf(os.Stderr, format, args...)
946         }
947 }