mirror of
https://github.com/spf13/viper
synced 2025-05-11 22:57:21 +00:00
Set keys case sensitive
This commit is contained in:
commit
21f7008c6a
5 changed files with 144 additions and 32 deletions
|
@ -73,6 +73,8 @@ Viper uses the following precedence order. Each item takes precedence over the i
|
||||||
**Important:** Viper configuration keys are case insensitive.
|
**Important:** Viper configuration keys are case insensitive.
|
||||||
There are ongoing discussions about making that optional.
|
There are ongoing discussions about making that optional.
|
||||||
|
|
||||||
|
Viper configuration keys are case insensitive by default. They can be made case
|
||||||
|
sensitive with `viper.SetKeysCaseSensitive(true)`.
|
||||||
|
|
||||||
## Putting Values into Viper
|
## Putting Values into Viper
|
||||||
|
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/spf13/viper
|
module github.com/gbunt/viper
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ require (
|
||||||
github.com/spf13/cast v1.3.0
|
github.com/spf13/cast v1.3.0
|
||||||
github.com/spf13/jwalterweatherman v1.0.0
|
github.com/spf13/jwalterweatherman v1.0.0
|
||||||
github.com/spf13/pflag v1.0.3
|
github.com/spf13/pflag v1.0.3
|
||||||
|
github.com/spf13/viper v1.7.1
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
github.com/subosito/gotenv v1.2.0
|
github.com/subosito/gotenv v1.2.0
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -223,6 +223,8 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||||
|
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
|
|
97
viper.go
97
viper.go
|
@ -199,6 +199,7 @@ type Viper struct {
|
||||||
automaticEnvApplied bool
|
automaticEnvApplied bool
|
||||||
envKeyReplacer StringReplacer
|
envKeyReplacer StringReplacer
|
||||||
allowEmptyEnv bool
|
allowEmptyEnv bool
|
||||||
|
caseSensitiveKeys bool
|
||||||
|
|
||||||
config map[string]interface{}
|
config map[string]interface{}
|
||||||
override map[string]interface{}
|
override map[string]interface{}
|
||||||
|
@ -553,7 +554,6 @@ func (v *Viper) providerPathExists(p *defaultRemoteProvider) bool {
|
||||||
|
|
||||||
// searchMap recursively searches for a value for path in source map.
|
// searchMap recursively searches for a value for path in source map.
|
||||||
// Returns nil if not found.
|
// Returns nil if not found.
|
||||||
// Note: This assumes that the path entries and map keys are lower cased.
|
|
||||||
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
|
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return source
|
return source
|
||||||
|
@ -600,7 +600,7 @@ func (v *Viper) searchMapWithPathPrefixes(source map[string]interface{}, path []
|
||||||
|
|
||||||
// search for path prefixes, starting from the longest one
|
// search for path prefixes, starting from the longest one
|
||||||
for i := len(path); i > 0; i-- {
|
for i := len(path); i > 0; i-- {
|
||||||
prefixKey := strings.ToLower(strings.Join(path[0:i], v.keyDelim))
|
prefixKey := v.caseKey(strings.Join(path[0:i], v.keyDelim))
|
||||||
|
|
||||||
next, ok := source[prefixKey]
|
next, ok := source[prefixKey]
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -722,7 +722,7 @@ func GetViper() *Viper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get can retrieve any value given the key to use.
|
// Get can retrieve any value given the key to use.
|
||||||
// Get is case-insensitive for a key.
|
// Get's case-sensitivity for key is determined by viper.keyCaseSensitivity.
|
||||||
// Get has the behavior of returning the value associated with the first
|
// Get has the behavior of returning the value associated with the first
|
||||||
// place from where it is set. Viper will check in the following order:
|
// place from where it is set. Viper will check in the following order:
|
||||||
// override, flag, env, config file, key/value store, default
|
// override, flag, env, config file, key/value store, default
|
||||||
|
@ -731,8 +731,8 @@ func GetViper() *Viper {
|
||||||
func Get(key string) interface{} { return v.Get(key) }
|
func Get(key string) interface{} { return v.Get(key) }
|
||||||
|
|
||||||
func (v *Viper) Get(key string) interface{} {
|
func (v *Viper) Get(key string) interface{} {
|
||||||
lcaseKey := strings.ToLower(key)
|
casedKey := v.caseKey(key)
|
||||||
val := v.find(lcaseKey, true)
|
val := v.find(casedKey, true)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -740,7 +740,7 @@ func (v *Viper) Get(key string) interface{} {
|
||||||
if v.typeByDefValue {
|
if v.typeByDefValue {
|
||||||
// TODO(bep) this branch isn't covered by a single test.
|
// TODO(bep) this branch isn't covered by a single test.
|
||||||
valType := val
|
valType := val
|
||||||
path := strings.Split(lcaseKey, v.keyDelim)
|
path := strings.Split(casedKey, v.keyDelim)
|
||||||
defVal := v.searchMap(v.defaults, path)
|
defVal := v.searchMap(v.defaults, path)
|
||||||
if defVal != nil {
|
if defVal != nil {
|
||||||
valType = defVal
|
valType = defVal
|
||||||
|
@ -778,7 +778,7 @@ func (v *Viper) Get(key string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub returns new Viper instance representing a sub tree of this instance.
|
// Sub returns new Viper instance representing a sub tree of this instance.
|
||||||
// Sub is case-insensitive for a key.
|
// Sub's case-sensitivity for key is determined by viper.keyCaseSensitivity.
|
||||||
func Sub(key string) *Viper { return v.Sub(key) }
|
func Sub(key string) *Viper { return v.Sub(key) }
|
||||||
|
|
||||||
func (v *Viper) Sub(key string) *Viper {
|
func (v *Viper) Sub(key string) *Viper {
|
||||||
|
@ -1015,7 +1015,7 @@ func (v *Viper) BindFlagValue(key string, flag FlagValue) error {
|
||||||
if flag == nil {
|
if flag == nil {
|
||||||
return fmt.Errorf("flag for %q is nil", key)
|
return fmt.Errorf("flag for %q is nil", key)
|
||||||
}
|
}
|
||||||
v.pflags[strings.ToLower(key)] = flag
|
v.pflags[v.caseKey(key)] = flag
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,7 +1031,7 @@ func (v *Viper) BindEnv(input ...string) error {
|
||||||
return fmt.Errorf("missing key to bind to")
|
return fmt.Errorf("missing key to bind to")
|
||||||
}
|
}
|
||||||
|
|
||||||
key = strings.ToLower(input[0])
|
key = v.caseKey(input[0])
|
||||||
|
|
||||||
if len(input) == 1 {
|
if len(input) == 1 {
|
||||||
envkey = v.mergeWithEnvPrefix(key)
|
envkey = v.mergeWithEnvPrefix(key)
|
||||||
|
@ -1221,12 +1221,13 @@ func stringToStringConv(val string) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSet checks to see if the key has been set in any of the data locations.
|
// IsSet checks to see if the key has been set in any of the data locations.
|
||||||
// IsSet is case-insensitive for a key.
|
// IsSet is case-insensitive for a key. This behavior can be modified
|
||||||
|
// with viper.SetKeysCaseSensitive.
|
||||||
func IsSet(key string) bool { return v.IsSet(key) }
|
func IsSet(key string) bool { return v.IsSet(key) }
|
||||||
|
|
||||||
func (v *Viper) IsSet(key string) bool {
|
func (v *Viper) IsSet(key string) bool {
|
||||||
lcaseKey := strings.ToLower(key)
|
casedKey := v.caseKey(key)
|
||||||
val := v.find(lcaseKey, false)
|
val := v.find(casedKey, false)
|
||||||
return val != nil
|
return val != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,11 +1253,11 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
|
||||||
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
|
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
|
||||||
|
|
||||||
func (v *Viper) RegisterAlias(alias string, key string) {
|
func (v *Viper) RegisterAlias(alias string, key string) {
|
||||||
v.registerAlias(alias, strings.ToLower(key))
|
v.registerAlias(alias, v.caseKey(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Viper) registerAlias(alias string, key string) {
|
func (v *Viper) registerAlias(alias string, key string) {
|
||||||
alias = strings.ToLower(alias)
|
alias = v.caseKey(alias)
|
||||||
if alias != key && alias != v.realKey(key) {
|
if alias != key && alias != v.realKey(key) {
|
||||||
_, exists := v.aliases[alias]
|
_, exists := v.aliases[alias]
|
||||||
|
|
||||||
|
@ -1308,17 +1309,20 @@ func (v *Viper) InConfig(key string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefault sets the default value for this key.
|
// SetDefault sets the default value for this key.
|
||||||
// SetDefault is case-insensitive for a key.
|
// SetDefault is case-insensitive for a key. This behavior can be modified
|
||||||
|
// with viper.SetKeysCaseSensitive.
|
||||||
// Default only used when no value is provided by the user via flag, config or ENV.
|
// Default only used when no value is provided by the user via flag, config or ENV.
|
||||||
func SetDefault(key string, value interface{}) { v.SetDefault(key, value) }
|
func SetDefault(key string, value interface{}) { v.SetDefault(key, value) }
|
||||||
|
|
||||||
func (v *Viper) SetDefault(key string, value interface{}) {
|
func (v *Viper) SetDefault(key string, value interface{}) {
|
||||||
// If alias passed in, then set the proper default
|
// If alias passed in, then set the proper default
|
||||||
key = v.realKey(strings.ToLower(key))
|
key = v.realKey(v.caseKey(key))
|
||||||
value = toCaseInsensitiveValue(value)
|
if !v.caseSensitiveKeys {
|
||||||
|
value = toCaseInsensitiveValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
path := strings.Split(key, v.keyDelim)
|
path := strings.Split(key, v.keyDelim)
|
||||||
lastKey := strings.ToLower(path[len(path)-1])
|
lastKey := v.caseKey(path[len(path)-1])
|
||||||
deepestMap := deepSearch(v.defaults, path[0:len(path)-1])
|
deepestMap := deepSearch(v.defaults, path[0:len(path)-1])
|
||||||
|
|
||||||
// set innermost value
|
// set innermost value
|
||||||
|
@ -1326,18 +1330,21 @@ func (v *Viper) SetDefault(key string, value interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the value for the key in the override register.
|
// Set sets the value for the key in the override register.
|
||||||
// Set is case-insensitive for a key.
|
// Set is case-insensitive for a key. This behavior can be modified
|
||||||
|
// with viper.SetKeysCaseSensitive.
|
||||||
// Will be used instead of values obtained via
|
// Will be used instead of values obtained via
|
||||||
// flags, config file, ENV, default, or key/value store.
|
// flags, config file, ENV, default, or key/value store.
|
||||||
func Set(key string, value interface{}) { v.Set(key, value) }
|
func Set(key string, value interface{}) { v.Set(key, value) }
|
||||||
|
|
||||||
func (v *Viper) Set(key string, value interface{}) {
|
func (v *Viper) Set(key string, value interface{}) {
|
||||||
// If alias passed in, then set the proper override
|
// If alias passed in, then set the proper override
|
||||||
key = v.realKey(strings.ToLower(key))
|
key = v.realKey(v.caseKey(key))
|
||||||
value = toCaseInsensitiveValue(value)
|
if !v.caseSensitiveKeys {
|
||||||
|
value = toCaseInsensitiveValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
path := strings.Split(key, v.keyDelim)
|
path := strings.Split(key, v.keyDelim)
|
||||||
lastKey := strings.ToLower(path[len(path)-1])
|
lastKey := v.caseKey(path[len(path)-1])
|
||||||
deepestMap := deepSearch(v.override, path[0:len(path)-1])
|
deepestMap := deepSearch(v.override, path[0:len(path)-1])
|
||||||
|
|
||||||
// set innermost value
|
// set innermost value
|
||||||
|
@ -1426,7 +1433,9 @@ func (v *Viper) MergeConfigMap(cfg map[string]interface{}) error {
|
||||||
if v.config == nil {
|
if v.config == nil {
|
||||||
v.config = make(map[string]interface{})
|
v.config = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
insensitiviseMap(cfg)
|
if !v.caseSensitiveKeys {
|
||||||
|
insensitiviseMap(cfg)
|
||||||
|
}
|
||||||
mergeMaps(cfg, v.config, nil)
|
mergeMaps(cfg, v.config, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1566,7 +1575,7 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||||
value, _ := v.properties.Get(key)
|
value, _ := v.properties.Get(key)
|
||||||
// recursively build nested maps
|
// recursively build nested maps
|
||||||
path := strings.Split(key, ".")
|
path := strings.Split(key, ".")
|
||||||
lastKey := strings.ToLower(path[len(path)-1])
|
lastKey := v.caseKey(path[len(path)-1])
|
||||||
deepestMap := deepSearch(c, path[0:len(path)-1])
|
deepestMap := deepSearch(c, path[0:len(path)-1])
|
||||||
// set innermost value
|
// set innermost value
|
||||||
deepestMap[lastKey] = value
|
deepestMap[lastKey] = value
|
||||||
|
@ -1590,7 +1599,9 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insensitiviseMap(c)
|
if !v.caseSensitiveKeys {
|
||||||
|
insensitiviseMap(c)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1689,10 +1700,9 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func keyExists(k string, m map[string]interface{}) string {
|
func keyExists(k string, m map[string]interface{}) string {
|
||||||
lk := strings.ToLower(k)
|
ck := v.caseKey(k)
|
||||||
for mk := range m {
|
for mk := range m {
|
||||||
lmk := strings.ToLower(mk)
|
if mk == ck {
|
||||||
if lmk == lk {
|
|
||||||
return mk
|
return mk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1921,7 +1931,7 @@ func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interfac
|
||||||
m2 = cast.ToStringMap(val)
|
m2 = cast.ToStringMap(val)
|
||||||
default:
|
default:
|
||||||
// immediate value
|
// immediate value
|
||||||
shadow[strings.ToLower(fullKey)] = true
|
shadow[v.caseKey(fullKey)] = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// recursively merge to shadow map
|
// recursively merge to shadow map
|
||||||
|
@ -1947,7 +1957,7 @@ outer:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add key
|
// add key
|
||||||
shadow[strings.ToLower(k)] = true
|
shadow[v.caseKey(k)] = true
|
||||||
}
|
}
|
||||||
return shadow
|
return shadow
|
||||||
}
|
}
|
||||||
|
@ -1966,7 +1976,7 @@ func (v *Viper) AllSettings() map[string]interface{} {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
path := strings.Split(k, v.keyDelim)
|
path := strings.Split(k, v.keyDelim)
|
||||||
lastKey := strings.ToLower(path[len(path)-1])
|
lastKey := v.caseKey(path[len(path)-1])
|
||||||
deepestMap := deepSearch(m, path[0:len(path)-1])
|
deepestMap := deepSearch(m, path[0:len(path)-1])
|
||||||
// set innermost value
|
// set innermost value
|
||||||
deepestMap[lastKey] = value
|
deepestMap[lastKey] = value
|
||||||
|
@ -2009,6 +2019,22 @@ func (v *Viper) SetConfigPermissions(perm os.FileMode) {
|
||||||
v.configPermissions = perm.Perm()
|
v.configPermissions = perm.Perm()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetKeysCaseSensitive disables the default behaviour of
|
||||||
|
// case-insensitivising (lowercasing) keys and preserves the key casing
|
||||||
|
// as they are found in the config files. It is important
|
||||||
|
// to note that operations such as set and merge when
|
||||||
|
// case sensitivity is 'on', and whtn it is turneed 'off',
|
||||||
|
// are incompatible. A key that is set when case sentivity
|
||||||
|
// is 'on' may not be retrievable when case sensitivity is turned 'off',
|
||||||
|
// as the original casing is permanently lost in the former mode.
|
||||||
|
// That is ideally, this should only be invoked only once,
|
||||||
|
// during initialisation, and the subsequent usage must adhere
|
||||||
|
// to the same case sentivity.
|
||||||
|
func SetKeysCaseSensitive(on bool) { v.SetKeysCaseSensitive(on) }
|
||||||
|
func (v *Viper) SetKeysCaseSensitive(on bool) {
|
||||||
|
v.caseSensitiveKeys = on
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Viper) getConfigType() string {
|
func (v *Viper) getConfigType() string {
|
||||||
if v.configType != "" {
|
if v.configType != "" {
|
||||||
return v.configType
|
return v.configType
|
||||||
|
@ -2058,6 +2084,15 @@ func (v *Viper) searchInPath(in string) (filename string) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// caseKey cases (preserves sensitivity or lowercases) a
|
||||||
|
// given key based on the keyCaseSensitivity config.
|
||||||
|
func (v *Viper) caseKey(in string) (filename string) {
|
||||||
|
if v.caseSensitiveKeys {
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
return strings.ToLower(in)
|
||||||
|
}
|
||||||
|
|
||||||
// Search all configPaths for any config file.
|
// Search all configPaths for any config file.
|
||||||
// Returns the first path that exists (and is a config file).
|
// Returns the first path that exists (and is a config file).
|
||||||
func (v *Viper) findConfigFile() (string, error) {
|
func (v *Viper) findConfigFile() (string, error) {
|
||||||
|
|
|
@ -1967,6 +1967,51 @@ R = 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCaseSensitive(t *testing.T) {
|
||||||
|
for _, config := range []struct {
|
||||||
|
typ string
|
||||||
|
content string
|
||||||
|
}{
|
||||||
|
{"yaml", `
|
||||||
|
aBcD: 1
|
||||||
|
eF:
|
||||||
|
gH: 2
|
||||||
|
iJk: 3
|
||||||
|
Lm:
|
||||||
|
nO: 4
|
||||||
|
P:
|
||||||
|
Q: 5
|
||||||
|
R: 6
|
||||||
|
`},
|
||||||
|
{"json", `{
|
||||||
|
"aBcD": 1,
|
||||||
|
"eF": {
|
||||||
|
"iJk": 3,
|
||||||
|
"Lm": {
|
||||||
|
"P": {
|
||||||
|
"Q": 5,
|
||||||
|
"R": 6
|
||||||
|
},
|
||||||
|
"nO": 4
|
||||||
|
},
|
||||||
|
"gH": 2
|
||||||
|
}
|
||||||
|
}`},
|
||||||
|
{"toml", `aBcD = 1
|
||||||
|
[eF]
|
||||||
|
gH = 2
|
||||||
|
iJk = 3
|
||||||
|
[eF.Lm]
|
||||||
|
nO = 4
|
||||||
|
[eF.Lm.P]
|
||||||
|
Q = 5
|
||||||
|
R = 6
|
||||||
|
`},
|
||||||
|
} {
|
||||||
|
doTestCaseSensitive(t, config.typ, config.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCaseInsensitiveSet(t *testing.T) {
|
func TestCaseInsensitiveSet(t *testing.T) {
|
||||||
Reset()
|
Reset()
|
||||||
m1 := map[string]interface{}{
|
m1 := map[string]interface{}{
|
||||||
|
@ -2070,6 +2115,33 @@ func doTestCaseInsensitive(t *testing.T, typ, config string) {
|
||||||
assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q")))
|
assert.Equal(t, 5, cast.ToInt(Get("ef.lm.p.q")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doTestCaseSensitive(t *testing.T, typ, config string) {
|
||||||
|
Reset()
|
||||||
|
SetConfigType(typ)
|
||||||
|
|
||||||
|
// Turn on case sensitivy.
|
||||||
|
SetKeysCaseSensitive(true)
|
||||||
|
r := strings.NewReader(config)
|
||||||
|
if err := unmarshalReader(r, v.config); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Set("RfD", true)
|
||||||
|
assert.Equal(t, nil, Get("rfd"))
|
||||||
|
assert.Equal(t, true, Get("RfD"))
|
||||||
|
assert.Equal(t, 0, cast.ToInt(Get("abcd")))
|
||||||
|
assert.Equal(t, 1, cast.ToInt(Get("aBcD")))
|
||||||
|
assert.Equal(t, 0, cast.ToInt(Get("ef.gh")))
|
||||||
|
assert.Equal(t, 2, cast.ToInt(Get("eF.gH")))
|
||||||
|
assert.Equal(t, 0, cast.ToInt(Get("ef.ijk")))
|
||||||
|
assert.Equal(t, 3, cast.ToInt(Get("eF.iJk")))
|
||||||
|
assert.Equal(t, 0, cast.ToInt(Get("ef.lm.no")))
|
||||||
|
assert.Equal(t, 4, cast.ToInt(Get("eF.Lm.nO")))
|
||||||
|
assert.Equal(t, 0, cast.ToInt(Get("ef.lm.p.q")))
|
||||||
|
assert.Equal(t, 5, cast.ToInt(Get("eF.Lm.P.Q")))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func newViperWithConfigFile(t *testing.T) (*Viper, string, func()) {
|
func newViperWithConfigFile(t *testing.T) (*Viper, string, func()) {
|
||||||
watchDir, err := ioutil.TempDir("", "")
|
watchDir, err := ioutil.TempDir("", "")
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
Loading…
Add table
Reference in a new issue