...

Source file src/edge-infra.dev/pkg/lib/ini/key_test.go

Documentation: edge-infra.dev/pkg/lib/ini

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

View as plain text