fix #1700: update tests to use local viper instance (#1791)

* fix:test to use local viper instance

* fix linting

* fix typo

* remove unsed function
This commit is contained in:
sandeep 2024-04-07 04:09:02 -07:00 committed by GitHub
parent 947eb59667
commit 2e9148610a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 295 additions and 283 deletions

View File

@ -1791,12 +1791,6 @@ func (v *Viper) writeConfig(filename string, force bool) error {
return f.Sync()
}
// Unmarshal a Reader into a map.
// Should probably be an unexported function.
func unmarshalReader(in io.Reader, c map[string]any) error {
return v.unmarshalReader(in, c)
}
func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
buf := new(bytes.Buffer)
buf.ReadFrom(in)

View File

@ -136,104 +136,50 @@ Coding addict.
Good man.
""" # Succeeding comment`)
func initConfigs() {
Reset()
func initConfigs(v *Viper) {
var r io.Reader
SetConfigType("yaml")
v.SetConfigType("yaml")
r = bytes.NewReader(yamlExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("json")
v.SetConfigType("json")
r = bytes.NewReader(jsonExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("hcl")
v.SetConfigType("hcl")
r = bytes.NewReader(hclExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("properties")
v.SetConfigType("properties")
r = bytes.NewReader(propertiesExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("toml")
v.SetConfigType("toml")
r = bytes.NewReader(tomlExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("env")
v.SetConfigType("env")
r = bytes.NewReader(dotenvExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
SetConfigType("json")
v.SetConfigType("json")
remote := bytes.NewReader(remoteExample)
unmarshalReader(remote, v.kvstore)
v.unmarshalReader(remote, v.kvstore)
SetConfigType("ini")
v.SetConfigType("ini")
r = bytes.NewReader(iniExample)
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
}
func initConfig(typ, config string) {
Reset()
SetConfigType(typ)
func initConfig(typ, config string, v *Viper) {
v.SetConfigType(typ)
r := strings.NewReader(config)
if err := unmarshalReader(r, v.config); err != nil {
if err := v.unmarshalReader(r, v.config); err != nil {
panic(err)
}
}
func initYAML() {
initConfig("yaml", string(yamlExample))
}
func initJSON() {
Reset()
SetConfigType("json")
r := bytes.NewReader(jsonExample)
unmarshalReader(r, v.config)
}
func initProperties() {
Reset()
SetConfigType("properties")
r := bytes.NewReader(propertiesExample)
unmarshalReader(r, v.config)
}
func initTOML() {
Reset()
SetConfigType("toml")
r := bytes.NewReader(tomlExample)
unmarshalReader(r, v.config)
}
func initDotEnv() {
Reset()
SetConfigType("env")
r := bytes.NewReader(dotenvExample)
unmarshalReader(r, v.config)
}
func initHcl() {
Reset()
SetConfigType("hcl")
r := bytes.NewReader(hclExample)
unmarshalReader(r, v.config)
}
func initIni() {
Reset()
SetConfigType("ini")
r := bytes.NewReader(iniExample)
unmarshalReader(r, v.config)
}
// initDirs makes directories for testing.
func initDirs(t *testing.T) (string, string) {
var (
@ -472,257 +418,313 @@ func TestReadInConfig(t *testing.T) {
}
func TestDefault(t *testing.T) {
Reset()
SetDefault("age", 45)
assert.Equal(t, 45, Get("age"))
v := New()
v.SetDefault("age", 45)
assert.Equal(t, 45, v.Get("age"))
SetDefault("clothing.jacket", "slacks")
assert.Equal(t, "slacks", Get("clothing.jacket"))
v.SetDefault("clothing.jacket", "slacks")
assert.Equal(t, "slacks", v.Get("clothing.jacket"))
SetConfigType("yaml")
err := ReadConfig(bytes.NewBuffer(yamlExample))
v.SetConfigType("yaml")
err := v.ReadConfig(bytes.NewBuffer(yamlExample))
assert.NoError(t, err)
assert.Equal(t, "leather", Get("clothing.jacket"))
assert.Equal(t, "leather", v.Get("clothing.jacket"))
}
func TestUnmarshaling(t *testing.T) {
Reset()
SetConfigType("yaml")
v := New()
v.SetConfigType("yaml")
r := bytes.NewReader(yamlExample)
unmarshalReader(r, v.config)
assert.True(t, InConfig("name"))
assert.True(t, InConfig("clothing.jacket"))
assert.False(t, InConfig("state"))
assert.False(t, InConfig("clothing.hat"))
assert.Equal(t, "steve", Get("name"))
assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, Get("clothing"))
assert.Equal(t, 35, Get("age"))
v.unmarshalReader(r, v.config)
assert.True(t, v.InConfig("name"))
assert.True(t, v.InConfig("clothing.jacket"))
assert.False(t, v.InConfig("state"))
assert.False(t, v.InConfig("clothing.hat"))
assert.Equal(t, "steve", v.Get("name"))
assert.Equal(t, []any{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
assert.Equal(t, map[string]any{"jacket": "leather", "trousers": "denim", "pants": map[string]any{"size": "large"}}, v.Get("clothing"))
assert.Equal(t, 35, v.Get("age"))
}
func TestUnmarshalExact(t *testing.T) {
vip := New()
v := New()
target := &testUnmarshalExtra{}
vip.SetConfigType("yaml")
v.SetConfigType("yaml")
r := bytes.NewReader(yamlExampleWithExtras)
vip.ReadConfig(r)
err := vip.UnmarshalExact(target)
v.ReadConfig(r)
err := v.UnmarshalExact(target)
assert.Error(t, err, "UnmarshalExact should error when populating a struct from a conf that contains unused fields")
}
func TestOverrides(t *testing.T) {
Set("age", 40)
assert.Equal(t, 40, Get("age"))
v := New()
v.Set("age", 40)
assert.Equal(t, 40, v.Get("age"))
}
func TestDefaultPost(t *testing.T) {
assert.NotEqual(t, "NYC", Get("state"))
SetDefault("state", "NYC")
assert.Equal(t, "NYC", Get("state"))
v := New()
assert.NotEqual(t, "NYC", v.Get("state"))
v.SetDefault("state", "NYC")
assert.Equal(t, "NYC", v.Get("state"))
}
func TestAliases(t *testing.T) {
initConfigs()
Set("age", 40)
RegisterAlias("years", "age")
assert.Equal(t, 40, Get("years"))
Set("years", 45)
assert.Equal(t, 45, Get("age"))
v := New()
v.Set("age", 40)
v.RegisterAlias("years", "age")
assert.Equal(t, 40, v.Get("years"))
v.Set("years", 45)
assert.Equal(t, 45, v.Get("age"))
}
func TestAliasInConfigFile(t *testing.T) {
initConfigs()
// the config file specifies "beard". If we make this an alias for
// "hasbeard", we still want the old config file to work with beard.
RegisterAlias("beard", "hasbeard")
assert.Equal(t, true, Get("hasbeard"))
Set("hasbeard", false)
assert.Equal(t, false, Get("beard"))
v := New()
v.SetConfigType("yaml")
// Read the YAML data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(yamlExample)), "Error reading YAML data")
v.RegisterAlias("beard", "hasbeard")
assert.Equal(t, true, v.Get("hasbeard"))
v.Set("hasbeard", false)
assert.Equal(t, false, v.Get("beard"))
}
func TestYML(t *testing.T) {
initYAML()
assert.Equal(t, "steve", Get("name"))
v := New()
v.SetConfigType("yaml")
// Read the YAML data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(yamlExample)), "Error reading YAML data")
assert.Equal(t, "steve", v.Get("name"))
}
func TestJSON(t *testing.T) {
initJSON()
assert.Equal(t, "0001", Get("id"))
v := New()
v.SetConfigType("json")
// Read the JSON data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading JSON data")
assert.Equal(t, "0001", v.Get("id"))
}
func TestProperties(t *testing.T) {
initProperties()
assert.Equal(t, "0001", Get("p_id"))
v := New()
v.SetConfigType("properties")
// Read the properties data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(propertiesExample)), "Error reading properties data")
assert.Equal(t, "0001", v.Get("p_id"))
}
func TestTOML(t *testing.T) {
initTOML()
assert.Equal(t, "TOML Example", Get("title"))
v := New()
v.SetConfigType("toml")
// Read the properties data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(tomlExample)), "Error reading toml data")
assert.Equal(t, "TOML Example", v.Get("title"))
}
func TestDotEnv(t *testing.T) {
initDotEnv()
assert.Equal(t, "DotEnv Example", Get("title_dotenv"))
v := New()
v.SetConfigType("env")
// Read the properties data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(dotenvExample)), "Error reading env data")
assert.Equal(t, "DotEnv Example", v.Get("title_dotenv"))
}
func TestHCL(t *testing.T) {
initHcl()
assert.Equal(t, "0001", Get("id"))
assert.Equal(t, 0.55, Get("ppu"))
assert.Equal(t, "donut", Get("type"))
assert.Equal(t, "Cake", Get("name"))
Set("id", "0002")
assert.Equal(t, "0002", Get("id"))
assert.NotEqual(t, "cronut", Get("type"))
v := New()
v.SetConfigType("hcl")
// Read the properties data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(hclExample)), "Error reading hcl data")
// initHcl()
assert.Equal(t, "0001", v.Get("id"))
assert.Equal(t, 0.55, v.Get("ppu"))
assert.Equal(t, "donut", v.Get("type"))
assert.Equal(t, "Cake", v.Get("name"))
v.Set("id", "0002")
assert.Equal(t, "0002", v.Get("id"))
assert.NotEqual(t, "cronut", v.Get("type"))
}
func TestIni(t *testing.T) {
initIni()
assert.Equal(t, "ini", Get("default.name"))
// initIni()
v := New()
v.SetConfigType("ini")
// Read the properties data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(iniExample)), "Error reading ini data")
assert.Equal(t, "ini", v.Get("default.name"))
}
func TestRemotePrecedence(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
assert.Equal(t, "0001", v.Get("id"))
// update the kvstore with the remoteExample which should overite the key in v.config
remote := bytes.NewReader(remoteExample)
assert.Equal(t, "0001", Get("id"))
unmarshalReader(remote, v.kvstore)
assert.Equal(t, "0001", Get("id"))
assert.NotEqual(t, "cronut", Get("type"))
assert.Equal(t, "remote", Get("newkey"))
Set("newkey", "newvalue")
assert.NotEqual(t, "remote", Get("newkey"))
assert.Equal(t, "newvalue", Get("newkey"))
Set("newkey", "remote")
require.NoError(t, v.unmarshalReader(remote, v.kvstore), "Error reading json data in to kvstore")
assert.Equal(t, "0001", v.Get("id"))
assert.NotEqual(t, "cronut", v.Get("type"))
assert.Equal(t, "remote", v.Get("newkey"))
v.Set("newkey", "newvalue")
assert.NotEqual(t, "remote", v.Get("newkey"))
assert.Equal(t, "newvalue", v.Get("newkey"))
}
func TestEnv(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
BindEnv("id")
BindEnv("f", "FOOD", "OLD_FOOD")
v.BindEnv("id")
v.BindEnv("f", "FOOD", "OLD_FOOD")
t.Setenv("ID", "13")
t.Setenv("FOOD", "apple")
t.Setenv("OLD_FOOD", "banana")
t.Setenv("NAME", "crunk")
assert.Equal(t, "13", Get("id"))
assert.Equal(t, "apple", Get("f"))
assert.Equal(t, "Cake", Get("name"))
assert.Equal(t, "13", v.Get("id"))
assert.Equal(t, "apple", v.Get("f"))
assert.Equal(t, "Cake", v.Get("name"))
AutomaticEnv()
v.AutomaticEnv()
assert.Equal(t, "crunk", Get("name"))
assert.Equal(t, "crunk", v.Get("name"))
}
func TestMultipleEnv(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
BindEnv("f", "FOOD", "OLD_FOOD")
v.BindEnv("f", "FOOD", "OLD_FOOD")
t.Setenv("OLD_FOOD", "banana")
assert.Equal(t, "banana", Get("f"))
assert.Equal(t, "banana", v.Get("f"))
}
func TestEmptyEnv(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
BindEnv("type") // Empty environment variable
BindEnv("name") // Bound, but not set environment variable
v.BindEnv("type") // Empty environment variable
v.BindEnv("name") // Bound, but not set environment variable
t.Setenv("TYPE", "")
assert.Equal(t, "donut", Get("type"))
assert.Equal(t, "Cake", Get("name"))
assert.Equal(t, "donut", v.Get("type"))
assert.Equal(t, "Cake", v.Get("name"))
}
func TestEmptyEnv_Allowed(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
AllowEmptyEnv(true)
v.AllowEmptyEnv(true)
BindEnv("type") // Empty environment variable
BindEnv("name") // Bound, but not set environment variable
v.BindEnv("type") // Empty environment variable
v.BindEnv("name") // Bound, but not set environment variable
t.Setenv("TYPE", "")
assert.Equal(t, "", Get("type"))
assert.Equal(t, "Cake", Get("name"))
assert.Equal(t, "", v.Get("type"))
assert.Equal(t, "Cake", v.Get("name"))
}
func TestEnvPrefix(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading json data")
SetEnvPrefix("foo") // will be uppercased automatically
BindEnv("id")
BindEnv("f", "FOOD") // not using prefix
v.SetEnvPrefix("foo") // will be uppercased automatically
v.BindEnv("id")
v.BindEnv("f", "FOOD") // not using prefix
t.Setenv("FOO_ID", "13")
t.Setenv("FOOD", "apple")
t.Setenv("FOO_NAME", "crunk")
assert.Equal(t, "13", Get("id"))
assert.Equal(t, "apple", Get("f"))
assert.Equal(t, "Cake", Get("name"))
assert.Equal(t, "13", v.Get("id"))
assert.Equal(t, "apple", v.Get("f"))
assert.Equal(t, "Cake", v.Get("name"))
AutomaticEnv()
v.AutomaticEnv()
assert.Equal(t, "crunk", Get("name"))
assert.Equal(t, "crunk", v.Get("name"))
}
func TestAutoEnv(t *testing.T) {
Reset()
v := New()
AutomaticEnv()
v.AutomaticEnv()
t.Setenv("FOO_BAR", "13")
assert.Equal(t, "13", Get("foo_bar"))
assert.Equal(t, "13", v.Get("foo_bar"))
}
func TestAutoEnvWithPrefix(t *testing.T) {
Reset()
AutomaticEnv()
SetEnvPrefix("Baz")
v := New()
v.AutomaticEnv()
v.SetEnvPrefix("Baz")
t.Setenv("BAZ_BAR", "13")
assert.Equal(t, "13", Get("bar"))
assert.Equal(t, "13", v.Get("bar"))
}
func TestSetEnvKeyReplacer(t *testing.T) {
Reset()
AutomaticEnv()
v := New()
v.AutomaticEnv()
t.Setenv("REFRESH_INTERVAL", "30s")
replacer := strings.NewReplacer("-", "_")
SetEnvKeyReplacer(replacer)
assert.Equal(t, "30s", Get("refresh-interval"))
}
func TestEnvKeyReplacer(t *testing.T) {
v := NewWithOptions(EnvKeyReplacer(strings.NewReplacer("-", "_")))
v.AutomaticEnv()
t.Setenv("REFRESH_INTERVAL", "30s")
v.SetEnvKeyReplacer(replacer)
assert.Equal(t, "30s", v.Get("refresh-interval"))
}
func TestEnvSubConfig(t *testing.T) {
initYAML()
func TestEnvKeyReplacer(t *testing.T) {
v := NewWithOptions(EnvKeyReplacer(strings.NewReplacer("-", "_")))
v.AutomaticEnv()
t.Setenv("REFRESH_INTERVAL", "30s")
assert.Equal(t, "30s", v.Get("refresh-interval"))
}
func TestEnvSubConfig(t *testing.T) {
v := New()
v.SetConfigType("yaml")
// Read the properties data into Viper configuration v.config
require.NoError(t, v.ReadConfig(bytes.NewBuffer(yamlExample)), "Error reading json data")
v.AutomaticEnv()
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
t.Setenv("CLOTHING_PANTS_SIZE", "small")
@ -737,7 +739,8 @@ func TestEnvSubConfig(t *testing.T) {
}
func TestAllKeys(t *testing.T) {
initConfigs()
v := New()
initConfigs(v)
ks := []string{
"title",
@ -843,8 +846,8 @@ func TestAllKeys(t *testing.T) {
"name_dotenv": "Cake",
}
assert.ElementsMatch(t, ks, AllKeys())
assert.Equal(t, all, AllSettings())
assert.ElementsMatch(t, ks, v.AllKeys())
assert.Equal(t, all, v.AllSettings())
}
func TestAllKeysWithEnv(t *testing.T) {
@ -862,25 +865,27 @@ func TestAllKeysWithEnv(t *testing.T) {
}
func TestAliasesOfAliases(t *testing.T) {
Set("Title", "Checking Case")
RegisterAlias("Foo", "Bar")
RegisterAlias("Bar", "Title")
assert.Equal(t, "Checking Case", Get("FOO"))
v := New()
v.Set("Title", "Checking Case")
v.RegisterAlias("Foo", "Bar")
v.RegisterAlias("Bar", "Title")
assert.Equal(t, "Checking Case", v.Get("FOO"))
}
func TestRecursiveAliases(t *testing.T) {
Set("baz", "bat")
RegisterAlias("Baz", "Roo")
RegisterAlias("Roo", "baz")
assert.Equal(t, "bat", Get("Baz"))
v := New()
v.Set("baz", "bat")
v.RegisterAlias("Baz", "Roo")
v.RegisterAlias("Roo", "baz")
assert.Equal(t, "bat", v.Get("Baz"))
}
func TestUnmarshal(t *testing.T) {
Reset()
SetDefault("port", 1313)
Set("name", "Steve")
Set("duration", "1s1ms")
Set("modes", []int{1, 2, 3})
v := New()
v.SetDefault("port", 1313)
v.Set("name", "Steve")
v.Set("duration", "1s1ms")
v.Set("modes", []int{1, 2, 3})
type config struct {
Port int
@ -890,9 +895,7 @@ func TestUnmarshal(t *testing.T) {
}
var C config
err := Unmarshal(&C)
require.NoError(t, err, "unable to decode into struct")
require.NoError(t, v.Unmarshal(&C), "unable to decode into struct")
assert.Equal(
t,
@ -905,9 +908,8 @@ func TestUnmarshal(t *testing.T) {
&C,
)
Set("port", 1234)
err = Unmarshal(&C)
require.NoError(t, err, "unable to decode into struct")
v.Set("port", 1234)
require.NoError(t, v.Unmarshal(&C), "unable to decode into struct")
assert.Equal(
t,
@ -922,7 +924,8 @@ func TestUnmarshal(t *testing.T) {
}
func TestUnmarshalWithDecoderOptions(t *testing.T) {
Set("credentials", "{\"foo\":\"bar\"}")
v := New()
v.Set("credentials", "{\"foo\":\"bar\"}")
opt := DecodeHook(mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeDurationHookFunc(),
@ -948,8 +951,7 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) {
var C config
err := Unmarshal(&C, opt)
require.NoError(t, err, "unable to decode into struct")
require.NoError(t, v.Unmarshal(&C, opt), "unable to decode into struct")
assert.Equal(t, &config{
Credentials: map[string]string{"foo": "bar"},
@ -1266,6 +1268,7 @@ func TestBindPFlagsIntSlice(t *testing.T) {
}
func TestBindPFlag(t *testing.T) {
v := New()
testString := "testing"
testValue := newStringValue(testString, &testString)
@ -1275,18 +1278,19 @@ func TestBindPFlag(t *testing.T) {
Changed: false,
}
BindPFlag("testvalue", flag)
v.BindPFlag("testvalue", flag)
assert.Equal(t, testString, Get("testvalue"))
assert.Equal(t, testString, v.Get("testvalue"))
flag.Value.Set("testing_mutate")
flag.Changed = true // hack for pflag usage
assert.Equal(t, "testing_mutate", Get("testvalue"))
assert.Equal(t, "testing_mutate", v.Get("testvalue"))
}
func TestBindPFlagDetectNilFlag(t *testing.T) {
result := BindPFlag("testvalue", nil)
v := New()
result := v.BindPFlag("testvalue", nil)
assert.Error(t, result)
}
@ -1379,14 +1383,15 @@ func TestBindPFlagStringToInt(t *testing.T) {
}
func TestBoundCaseSensitivity(t *testing.T) {
initConfigs()
assert.Equal(t, "brown", Get("eyes"))
v := New()
initConfigs(v)
assert.Equal(t, "brown", v.Get("eyes"))
BindEnv("eYEs", "TURTLE_EYES")
v.BindEnv("eYEs", "TURTLE_EYES")
t.Setenv("TURTLE_EYES", "blue")
assert.Equal(t, "blue", Get("eyes"))
assert.Equal(t, "blue", v.Get("eyes"))
testString := "green"
testValue := newStringValue(testString, &testString)
@ -1397,8 +1402,8 @@ func TestBoundCaseSensitivity(t *testing.T) {
Changed: true,
}
BindPFlag("eYEs", flag)
assert.Equal(t, "green", Get("eyes"))
v.BindPFlag("eYEs", flag)
assert.Equal(t, "green", v.Get("eyes"))
}
func TestSizeInBytes(t *testing.T) {
@ -1419,10 +1424,11 @@ func TestSizeInBytes(t *testing.T) {
}
func TestFindsNestedKeys(t *testing.T) {
initConfigs()
v := New()
initConfigs(v)
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
Set("super", map[string]any{
v.Set("super", map[string]any{
"deep": map[string]any{
"nested": "value",
},
@ -1653,8 +1659,9 @@ var yamlInvalid = []byte(`hash: map
`)
func TestUnwrapParseErrors(t *testing.T) {
SetConfigType("yaml")
assert.ErrorAs(t, ReadConfig(bytes.NewBuffer(yamlInvalid)), &ConfigParseError{})
v := New()
v.SetConfigType("yaml")
assert.ErrorAs(t, v.ReadConfig(bytes.NewBuffer(yamlInvalid)), &ConfigParseError{})
}
func TestSub(t *testing.T) {
@ -2208,14 +2215,16 @@ func TestUnmarshalingWithAliases(t *testing.T) {
}
func TestSetConfigNameClearsFileCache(t *testing.T) {
SetConfigFile("/tmp/config.yaml")
SetConfigName("default")
v := New()
v.SetConfigFile("/tmp/config.yaml")
v.SetConfigName("default")
f, err := v.getConfigFile()
require.Error(t, err, "config file cache should have been cleared")
assert.Empty(t, f)
}
func TestShadowedNestedValue(t *testing.T) {
v := New()
config := `name: steve
clothing:
jacket: leather
@ -2223,30 +2232,36 @@ clothing:
pants:
size: large
`
initConfig("yaml", config)
initConfig("yaml", config, v)
assert.Equal(t, "steve", GetString("name"))
assert.Equal(t, "steve", v.GetString("name"))
polyester := "polyester"
SetDefault("clothing.shirt", polyester)
SetDefault("clothing.jacket.price", 100)
v.SetDefault("clothing.shirt", polyester)
v.SetDefault("clothing.jacket.price", 100)
assert.Equal(t, "leather", GetString("clothing.jacket"))
assert.Nil(t, Get("clothing.jacket.price"))
assert.Equal(t, polyester, GetString("clothing.shirt"))
assert.Equal(t, "leather", v.GetString("clothing.jacket"))
assert.Nil(t, v.Get("clothing.jacket.price"))
assert.Equal(t, polyester, v.GetString("clothing.shirt"))
clothingSettings := AllSettings()["clothing"].(map[string]any)
clothingSettings := v.AllSettings()["clothing"].(map[string]any)
assert.Equal(t, "leather", clothingSettings["jacket"])
assert.Equal(t, polyester, clothingSettings["shirt"])
}
func TestDotParameter(t *testing.T) {
initJSON()
v := New()
v.SetConfigType("json")
// Read the YAML data into Viper configuration
require.NoError(t, v.ReadConfig(bytes.NewBuffer(jsonExample)), "Error reading YAML data")
// should take precedence over batters defined in jsonExample
r := bytes.NewReader([]byte(`{ "batters.batter": [ { "type": "Small" } ] }`))
unmarshalReader(r, v.config)
v.unmarshalReader(r, v.config)
actual := Get("batters.batter")
actual := v.Get("batters.batter")
expected := []any{map[string]any{"type": "Small"}}
assert.Equal(t, expected, actual)
}
@ -2297,7 +2312,7 @@ R = 6
}
func TestCaseInsensitiveSet(t *testing.T) {
Reset()
v := New()
m1 := map[string]any{
"Foo": 32,
"Bar": map[any]any{
@ -2314,28 +2329,29 @@ func TestCaseInsensitiveSet(t *testing.T) {
},
}
Set("Given1", m1)
Set("Number1", 42)
v.Set("Given1", m1)
v.Set("Number1", 42)
SetDefault("Given2", m2)
SetDefault("Number2", 52)
v.SetDefault("Given2", m2)
v.SetDefault("Number2", 52)
// Verify SetDefault
assert.Equal(t, 52, Get("number2"))
assert.Equal(t, 52, Get("given2.foo"))
assert.Equal(t, "A", Get("given2.bar.bcd"))
assert.Equal(t, 52, v.Get("number2"))
assert.Equal(t, 52, v.Get("given2.foo"))
assert.Equal(t, "A", v.Get("given2.bar.bcd"))
_, ok := m2["Foo"]
assert.True(t, ok)
// Verify Set
assert.Equal(t, 42, Get("number1"))
assert.Equal(t, 32, Get("given1.foo"))
assert.Equal(t, "A", Get("given1.bar.abc"))
assert.Equal(t, 42, v.Get("number1"))
assert.Equal(t, 32, v.Get("given1.foo"))
assert.Equal(t, "A", v.Get("given1.bar.abc"))
_, ok = m1["Foo"]
assert.True(t, ok)
}
func TestParseNested(t *testing.T) {
v := New()
type duration struct {
Delay time.Duration
}
@ -2351,7 +2367,7 @@ func TestParseNested(t *testing.T) {
[parent.nested]
delay="200ms"
`
initConfig("toml", config)
initConfig("toml", config, v)
var items []item
err := v.UnmarshalKey("parent", &items)
@ -2363,16 +2379,17 @@ func TestParseNested(t *testing.T) {
}
func doTestCaseInsensitive(t *testing.T, typ, config string) {
initConfig(typ, config)
Set("RfD", true)
assert.Equal(t, true, Get("rfd"))
assert.Equal(t, true, Get("rFD"))
assert.Equal(t, 1, cast.ToInt(Get("abcd")))
assert.Equal(t, 1, cast.ToInt(Get("Abcd")))
assert.Equal(t, 2, cast.ToInt(Get("ef.gh")))
assert.Equal(t, 3, cast.ToInt(Get("ef.ijk")))
assert.Equal(t, 4, cast.ToInt(Get("ef.lm.no")))
assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q")))
v := New()
initConfig(typ, config, v)
v.Set("RfD", true)
assert.Equal(t, true, v.Get("rfd"))
assert.Equal(t, true, v.Get("rFD"))
assert.Equal(t, 1, cast.ToInt(v.Get("abcd")))
assert.Equal(t, 1, cast.ToInt(v.Get("Abcd")))
assert.Equal(t, 2, cast.ToInt(v.Get("ef.gh")))
assert.Equal(t, 3, cast.ToInt(v.Get("ef.ijk")))
assert.Equal(t, 4, cast.ToInt(v.Get("ef.lm.no")))
assert.Equal(t, 5, cast.ToInt(v.Get("ef.lm.p.q")))
}
func newViperWithConfigFile(t *testing.T) (*Viper, string) {
@ -2584,6 +2601,7 @@ var yamlDeepNestedSlices = []byte(`TV:
`)
func TestSliceIndexAccess(t *testing.T) {
v := New()
v.SetConfigType("yaml")
r := strings.NewReader(string(yamlDeepNestedSlices))