...

Source file src/gopkg.in/ini.v1/key_test.go

Documentation: gopkg.in/ini.v1

     1  // Copyright 2014 Unknwon
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    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  // Helpers for slice tests.
    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