Upgrade server dependencies, manage them with govendor
This commit is contained in:
parent
ebee2746d6
commit
971278e7e5
1748 changed files with 196165 additions and 194500 deletions
35
vendor/github.com/spf13/viper/README.md
generated
vendored
35
vendor/github.com/spf13/viper/README.md
generated
vendored
|
@ -10,9 +10,9 @@ Many Go projects are built using Viper including:
|
|||
* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
|
||||
* [Docker Notary](https://github.com/docker/Notary)
|
||||
* [BloomApi](https://www.bloomapi.com/)
|
||||
* [DOIt](https://github.com/bryanl/doit)
|
||||
* [doctl](https://github.com/digitalocean/doctl)
|
||||
|
||||
[](https://travis-ci.org/spf13/viper) [](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://travis-ci.org/spf13/viper) [](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://godoc.org/github.com/spf13/viper)
|
||||
|
||||
|
||||
## What is Viper?
|
||||
|
@ -110,7 +110,7 @@ Gone are the days of needing to restart a server to have a config take effect,
|
|||
viper powered applications can read an update to a config file while running and
|
||||
not miss a beat.
|
||||
|
||||
Simply tell the viper instance to watchConfig.
|
||||
Simply tell the viper instance to watchConfig.
|
||||
Optionally you can provide a function for Viper to run each time a change occurs.
|
||||
|
||||
**Make sure you add all of the configPaths prior to calling `WatchConfig()`**
|
||||
|
@ -277,10 +277,10 @@ Viper provides two Go interfaces to bind other flag systems if you don't use `Pf
|
|||
|
||||
```go
|
||||
type myFlag struct {}
|
||||
func (f myFlag) IsChanged() { return false }
|
||||
func (f myFlag) Name() { return "my-flag-name" }
|
||||
func (f myFlag) ValueString() { return "my-flag-value" }
|
||||
func (f myFlag) ValueType() { return "string" }
|
||||
func (f myFlag) HasChanged() bool { return false }
|
||||
func (f myFlag) Name() string { return "my-flag-name" }
|
||||
func (f myFlag) ValueString() string { return "my-flag-value" }
|
||||
func (f myFlag) ValueType() string { return "string" }
|
||||
```
|
||||
|
||||
Once your flag implements this interface, you can simply tell Viper to bind it:
|
||||
|
@ -298,7 +298,7 @@ type myFlagSet struct {
|
|||
|
||||
func (f myFlagSet) VisitAll(fn func(FlagValue)) {
|
||||
for _, flag := range flags {
|
||||
fn(flag)
|
||||
fn(flag)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -458,16 +458,17 @@ Viper can access a nested field by passing a `.` delimited path of keys:
|
|||
GetString("datastore.metric.host") // (returns "127.0.0.1")
|
||||
```
|
||||
|
||||
This obeys the precedence rules established above; the search for the root key
|
||||
(in this example, `datastore`) will cascade through the remaining configuration
|
||||
registries until found. The search for the sub-keys (`metric` and `host`),
|
||||
however, will not.
|
||||
This obeys the precedence rules established above; the search for the path
|
||||
will cascade through the remaining configuration registries until found.
|
||||
|
||||
For example, if the `metric` key was not defined in the configuration loaded
|
||||
from file, but was defined in the defaults, Viper would return the zero value.
|
||||
For example, given this configuration file, both `datastore.metric.host` and
|
||||
`datastore.metric.port` are already defined (and may be overridden). If in addition
|
||||
`datastore.metric.protocol` was defined in the defaults, Viper would also find it.
|
||||
|
||||
On the other hand, if the primary key was not defined, Viper would go through
|
||||
the remaining registries looking for it.
|
||||
However, if `datastore.metric` was overridden (by a flag, an environment variable,
|
||||
the `Set()` method, …) with an immediate value, then all sub-keys of
|
||||
`datastore.metric` become undefined, they are “shadowed” by the higher-priority
|
||||
configuration level.
|
||||
|
||||
Lastly, if there exists a key that matches the delimited key path, its value
|
||||
will be returned instead. E.g.
|
||||
|
@ -491,7 +492,7 @@ will be returned instead. E.g.
|
|||
}
|
||||
}
|
||||
|
||||
GetString("datastore.metric.host") //returns "0.0.0.0"
|
||||
GetString("datastore.metric.host") // returns "0.0.0.0"
|
||||
```
|
||||
|
||||
### Extract sub-tree
|
||||
|
|
66
vendor/github.com/spf13/viper/flags_test.go
generated
vendored
66
vendor/github.com/spf13/viper/flags_test.go
generated
vendored
|
@ -1,66 +0,0 @@
|
|||
package viper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBindFlagValueSet(t *testing.T) {
|
||||
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
var testValues = map[string]*string{
|
||||
"host": nil,
|
||||
"port": nil,
|
||||
"endpoint": nil,
|
||||
}
|
||||
|
||||
var mutatedTestValues = map[string]string{
|
||||
"host": "localhost",
|
||||
"port": "6060",
|
||||
"endpoint": "/public",
|
||||
}
|
||||
|
||||
for name, _ := range testValues {
|
||||
testValues[name] = flagSet.String(name, "", "test")
|
||||
}
|
||||
|
||||
flagValueSet := pflagValueSet{flagSet}
|
||||
|
||||
err := BindFlagValues(flagValueSet)
|
||||
if err != nil {
|
||||
t.Fatalf("error binding flag set, %v", err)
|
||||
}
|
||||
|
||||
flagSet.VisitAll(func(flag *pflag.Flag) {
|
||||
flag.Value.Set(mutatedTestValues[flag.Name])
|
||||
flag.Changed = true
|
||||
})
|
||||
|
||||
for name, expected := range mutatedTestValues {
|
||||
assert.Equal(t, Get(name), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBindFlagValue(t *testing.T) {
|
||||
var testString = "testing"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "testflag",
|
||||
Value: testValue,
|
||||
Changed: false,
|
||||
}
|
||||
|
||||
flagValue := pflagValue{flag}
|
||||
BindFlagValue("testvalue", flagValue)
|
||||
|
||||
assert.Equal(t, testString, Get("testvalue"))
|
||||
|
||||
flag.Value.Set("testing_mutate")
|
||||
flag.Changed = true //hack for pflag usage
|
||||
|
||||
assert.Equal(t, "testing_mutate", Get("testvalue"))
|
||||
|
||||
}
|
1
vendor/github.com/spf13/viper/nohup.out
generated
vendored
Normal file
1
vendor/github.com/spf13/viper/nohup.out
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
QProcess::start: Process is already running
|
77
vendor/github.com/spf13/viper/remote/remote.go
generated
vendored
77
vendor/github.com/spf13/viper/remote/remote.go
generated
vendored
|
@ -1,77 +0,0 @@
|
|||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package remote integrates the remote features of Viper.
|
||||
package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/spf13/viper"
|
||||
crypt "github.com/xordataexchange/crypt/config"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type remoteConfigProvider struct{}
|
||||
|
||||
func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
|
||||
cm, err := getConfigManager(rp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := cm.Get(rp.Path())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bytes.NewReader(b), nil
|
||||
}
|
||||
|
||||
func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
|
||||
cm, err := getConfigManager(rp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := <-cm.Watch(rp.Path(), nil)
|
||||
err = resp.Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.NewReader(resp.Value), nil
|
||||
}
|
||||
|
||||
func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
|
||||
|
||||
var cm crypt.ConfigManager
|
||||
var err error
|
||||
|
||||
if rp.SecretKeyring() != "" {
|
||||
kr, err := os.Open(rp.SecretKeyring())
|
||||
defer kr.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rp.Provider() == "etcd" {
|
||||
cm, err = crypt.NewEtcdConfigManager([]string{rp.Endpoint()}, kr)
|
||||
} else {
|
||||
cm, err = crypt.NewConsulConfigManager([]string{rp.Endpoint()}, kr)
|
||||
}
|
||||
} else {
|
||||
if rp.Provider() == "etcd" {
|
||||
cm, err = crypt.NewStandardEtcdConfigManager([]string{rp.Endpoint()})
|
||||
} else {
|
||||
cm, err = crypt.NewStandardConsulConfigManager([]string{rp.Endpoint()})
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cm, nil
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
viper.RemoteConfig = &remoteConfigProvider{}
|
||||
}
|
129
vendor/github.com/spf13/viper/util.go
generated
vendored
129
vendor/github.com/spf13/viper/util.go
generated
vendored
|
@ -21,31 +21,76 @@ import (
|
|||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/hashicorp/hcl"
|
||||
"github.com/magiconair/properties"
|
||||
toml "github.com/pelletier/go-toml"
|
||||
"github.com/spf13/cast"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Denotes failing to parse configuration file.
|
||||
// ConfigParseError denotes failing to parse configuration file.
|
||||
type ConfigParseError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// Returns the formatted configuration error.
|
||||
// Error returns the formatted configuration error.
|
||||
func (pe ConfigParseError) Error() string {
|
||||
return fmt.Sprintf("While parsing config: %s", pe.err.Error())
|
||||
}
|
||||
|
||||
// toCaseInsensitiveValue checks if the value is a map;
|
||||
// if so, create a copy and lower-case the keys recursively.
|
||||
func toCaseInsensitiveValue(value interface{}) interface{} {
|
||||
switch v := value.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
value = copyAndInsensitiviseMap(cast.ToStringMap(v))
|
||||
case map[string]interface{}:
|
||||
value = copyAndInsensitiviseMap(v)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of
|
||||
// any map it makes case insensitive.
|
||||
func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
|
||||
nm := make(map[string]interface{})
|
||||
|
||||
for key, val := range m {
|
||||
lkey := strings.ToLower(key)
|
||||
switch v := val.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
|
||||
case map[string]interface{}:
|
||||
nm[lkey] = copyAndInsensitiviseMap(v)
|
||||
default:
|
||||
nm[lkey] = v
|
||||
}
|
||||
}
|
||||
|
||||
return nm
|
||||
}
|
||||
|
||||
func insensitiviseMap(m map[string]interface{}) {
|
||||
for key, val := range m {
|
||||
switch val.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
// nested map: cast and recursively insensitivise
|
||||
val = cast.ToStringMap(val)
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
case map[string]interface{}:
|
||||
// nested map: recursively insensitivise
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
}
|
||||
|
||||
lower := strings.ToLower(key)
|
||||
if key != lower {
|
||||
// remove old key (not lower-cased)
|
||||
delete(m, key)
|
||||
m[lower] = val
|
||||
}
|
||||
// update map
|
||||
m[lower] = val
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,16 +113,16 @@ func absPathify(inPath string) string {
|
|||
p, err := filepath.Abs(inPath)
|
||||
if err == nil {
|
||||
return filepath.Clean(p)
|
||||
} else {
|
||||
jww.ERROR.Println("Couldn't discover absolute path")
|
||||
jww.ERROR.Println(err)
|
||||
}
|
||||
|
||||
jww.ERROR.Println("Couldn't discover absolute path")
|
||||
jww.ERROR.Println(err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// Check if File / Directory Exists
|
||||
func exists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
_, err := v.fs.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
@ -107,29 +152,6 @@ func userHomeDir() string {
|
|||
return os.Getenv("HOME")
|
||||
}
|
||||
|
||||
func findCWD() (string, error) {
|
||||
serverFile, err := filepath.Abs(os.Args[0])
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Can't get absolute path for executable: %v", err)
|
||||
}
|
||||
|
||||
path := filepath.Dir(serverFile)
|
||||
realFile, err := filepath.EvalSymlinks(serverFile)
|
||||
|
||||
if err != nil {
|
||||
if _, err = os.Stat(serverFile + ".exe"); err == nil {
|
||||
realFile = filepath.Clean(serverFile + ".exe")
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && realFile != serverFile {
|
||||
path = filepath.Dir(realFile)
|
||||
}
|
||||
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType string) error {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(in)
|
||||
|
@ -155,9 +177,14 @@ func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType s
|
|||
}
|
||||
|
||||
case "toml":
|
||||
if _, err := toml.Decode(buf.String(), &c); err != nil {
|
||||
tree, err := toml.LoadReader(buf)
|
||||
if err != nil {
|
||||
return ConfigParseError{err}
|
||||
}
|
||||
tmap := tree.ToMap()
|
||||
for k, v := range tmap {
|
||||
c[k] = v
|
||||
}
|
||||
|
||||
case "properties", "props", "prop":
|
||||
var p *properties.Properties
|
||||
|
@ -167,7 +194,12 @@ func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType s
|
|||
}
|
||||
for _, key := range p.Keys() {
|
||||
value, _ := p.Get(key)
|
||||
c[key] = value
|
||||
// recursively build nested maps
|
||||
path := strings.Split(key, ".")
|
||||
lastKey := strings.ToLower(path[len(path)-1])
|
||||
deepestMap := deepSearch(c, path[0:len(path)-1])
|
||||
// set innermost value
|
||||
deepestMap[lastKey] = value
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,3 +249,34 @@ func parseSizeInBytes(sizeStr string) uint {
|
|||
|
||||
return safeMul(uint(size), multiplier)
|
||||
}
|
||||
|
||||
// deepSearch scans deep maps, following the key indexes listed in the
|
||||
// sequence "path".
|
||||
// The last value is expected to be another map, and is returned.
|
||||
//
|
||||
// In case intermediate keys do not exist, or map to a non-map value,
|
||||
// a new map is created and inserted, and the search continues from there:
|
||||
// the initial map "m" may be modified!
|
||||
func deepSearch(m map[string]interface{}, path []string) map[string]interface{} {
|
||||
for _, k := range path {
|
||||
m2, ok := m[k]
|
||||
if !ok {
|
||||
// intermediate key does not exist
|
||||
// => create it and continue from there
|
||||
m3 := make(map[string]interface{})
|
||||
m[k] = m3
|
||||
m = m3
|
||||
continue
|
||||
}
|
||||
m3, ok := m2.(map[string]interface{})
|
||||
if !ok {
|
||||
// intermediate key is a value
|
||||
// => replace with a new map
|
||||
m3 = make(map[string]interface{})
|
||||
m[k] = m3
|
||||
}
|
||||
// continue search from here
|
||||
m = m3
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
852
vendor/github.com/spf13/viper/viper.go
generated
vendored
852
vendor/github.com/spf13/viper/viper.go
generated
vendored
File diff suppressed because it is too large
Load diff
885
vendor/github.com/spf13/viper/viper_test.go
generated
vendored
885
vendor/github.com/spf13/viper/viper_test.go
generated
vendored
|
@ -1,885 +0,0 @@
|
|||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package viper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var yamlExample = []byte(`Hacker: true
|
||||
name: steve
|
||||
hobbies:
|
||||
- skateboarding
|
||||
- snowboarding
|
||||
- go
|
||||
clothing:
|
||||
jacket: leather
|
||||
trousers: denim
|
||||
pants:
|
||||
size: large
|
||||
age: 35
|
||||
eyes : brown
|
||||
beard: true
|
||||
`)
|
||||
|
||||
var yamlExampleWithExtras = []byte(`Existing: true
|
||||
Bogus: true
|
||||
`)
|
||||
|
||||
type testUnmarshalExtra struct {
|
||||
Existing bool
|
||||
}
|
||||
|
||||
var tomlExample = []byte(`
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
organization = "MongoDB"
|
||||
Bio = "MongoDB Chief Developer Advocate & Hacker at Large"
|
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?`)
|
||||
|
||||
var jsonExample = []byte(`{
|
||||
"id": "0001",
|
||||
"type": "donut",
|
||||
"name": "Cake",
|
||||
"ppu": 0.55,
|
||||
"batters": {
|
||||
"batter": [
|
||||
{ "type": "Regular" },
|
||||
{ "type": "Chocolate" },
|
||||
{ "type": "Blueberry" },
|
||||
{ "type": "Devil's Food" }
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
var hclExample = []byte(`
|
||||
id = "0001"
|
||||
type = "donut"
|
||||
name = "Cake"
|
||||
ppu = 0.55
|
||||
foos {
|
||||
foo {
|
||||
key = 1
|
||||
}
|
||||
foo {
|
||||
key = 2
|
||||
}
|
||||
foo {
|
||||
key = 3
|
||||
}
|
||||
foo {
|
||||
key = 4
|
||||
}
|
||||
}`)
|
||||
|
||||
var propertiesExample = []byte(`
|
||||
p_id: 0001
|
||||
p_type: donut
|
||||
p_name: Cake
|
||||
p_ppu: 0.55
|
||||
p_batters.batter.type: Regular
|
||||
`)
|
||||
|
||||
var remoteExample = []byte(`{
|
||||
"id":"0002",
|
||||
"type":"cronut",
|
||||
"newkey":"remote"
|
||||
}`)
|
||||
|
||||
func initConfigs() {
|
||||
Reset()
|
||||
SetConfigType("yaml")
|
||||
r := bytes.NewReader(yamlExample)
|
||||
unmarshalReader(r, v.config)
|
||||
|
||||
SetConfigType("json")
|
||||
r = bytes.NewReader(jsonExample)
|
||||
unmarshalReader(r, v.config)
|
||||
|
||||
SetConfigType("hcl")
|
||||
r = bytes.NewReader(hclExample)
|
||||
unmarshalReader(r, v.config)
|
||||
|
||||
SetConfigType("properties")
|
||||
r = bytes.NewReader(propertiesExample)
|
||||
unmarshalReader(r, v.config)
|
||||
|
||||
SetConfigType("toml")
|
||||
r = bytes.NewReader(tomlExample)
|
||||
unmarshalReader(r, v.config)
|
||||
|
||||
SetConfigType("json")
|
||||
remote := bytes.NewReader(remoteExample)
|
||||
unmarshalReader(remote, v.kvstore)
|
||||
}
|
||||
|
||||
func initYAML() {
|
||||
Reset()
|
||||
SetConfigType("yaml")
|
||||
r := bytes.NewReader(yamlExample)
|
||||
|
||||
unmarshalReader(r, v.config)
|
||||
}
|
||||
|
||||
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 initHcl() {
|
||||
Reset()
|
||||
SetConfigType("hcl")
|
||||
r := bytes.NewReader(hclExample)
|
||||
|
||||
unmarshalReader(r, v.config)
|
||||
}
|
||||
|
||||
// make directories for testing
|
||||
func initDirs(t *testing.T) (string, string, func()) {
|
||||
|
||||
var (
|
||||
testDirs = []string{`a a`, `b`, `c\c`, `D_`}
|
||||
config = `improbable`
|
||||
)
|
||||
|
||||
root, err := ioutil.TempDir("", "")
|
||||
|
||||
cleanup := true
|
||||
defer func() {
|
||||
if cleanup {
|
||||
os.Chdir("..")
|
||||
os.RemoveAll(root)
|
||||
}
|
||||
}()
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = os.Chdir(root)
|
||||
assert.Nil(t, err)
|
||||
|
||||
for _, dir := range testDirs {
|
||||
err = os.Mkdir(dir, 0750)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = ioutil.WriteFile(
|
||||
path.Join(dir, config+".toml"),
|
||||
[]byte("key = \"value is "+dir+"\"\n"),
|
||||
0640)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
cleanup = false
|
||||
return root, config, func() {
|
||||
os.Chdir("..")
|
||||
os.RemoveAll(root)
|
||||
}
|
||||
}
|
||||
|
||||
//stubs for PFlag Values
|
||||
type stringValue string
|
||||
|
||||
func newStringValue(val string, p *string) *stringValue {
|
||||
*p = val
|
||||
return (*stringValue)(p)
|
||||
}
|
||||
|
||||
func (s *stringValue) Set(val string) error {
|
||||
*s = stringValue(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringValue) Type() string {
|
||||
return "string"
|
||||
}
|
||||
|
||||
func (s *stringValue) String() string {
|
||||
return fmt.Sprintf("%s", *s)
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
SetConfigFile("/tmp/config.yaml")
|
||||
assert.Equal(t, "/tmp/config.yaml", v.getConfigFile())
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
SetDefault("age", 45)
|
||||
assert.Equal(t, 45, Get("age"))
|
||||
|
||||
SetDefault("clothing.jacket", "slacks")
|
||||
assert.Equal(t, "slacks", Get("clothing.jacket"))
|
||||
|
||||
SetConfigType("yaml")
|
||||
err := ReadConfig(bytes.NewBuffer(yamlExample))
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "leather", Get("clothing.jacket"))
|
||||
}
|
||||
|
||||
func TestUnmarshalling(t *testing.T) {
|
||||
SetConfigType("yaml")
|
||||
r := bytes.NewReader(yamlExample)
|
||||
|
||||
unmarshalReader(r, v.config)
|
||||
assert.True(t, InConfig("name"))
|
||||
assert.False(t, InConfig("state"))
|
||||
assert.Equal(t, "steve", Get("name"))
|
||||
assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, Get("hobbies"))
|
||||
assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[interface{}]interface{}{"size": "large"}}, Get("clothing"))
|
||||
assert.Equal(t, 35, Get("age"))
|
||||
}
|
||||
|
||||
func TestUnmarshalExact(t *testing.T) {
|
||||
vip := New()
|
||||
target := &testUnmarshalExtra{}
|
||||
vip.SetConfigType("yaml")
|
||||
r := bytes.NewReader(yamlExampleWithExtras)
|
||||
vip.ReadConfig(r)
|
||||
err := vip.UnmarshalExact(target)
|
||||
if err == nil {
|
||||
t.Fatal("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"))
|
||||
}
|
||||
|
||||
func TestDefaultPost(t *testing.T) {
|
||||
assert.NotEqual(t, "NYC", Get("state"))
|
||||
SetDefault("state", "NYC")
|
||||
assert.Equal(t, "NYC", Get("state"))
|
||||
}
|
||||
|
||||
func TestAliases(t *testing.T) {
|
||||
RegisterAlias("years", "age")
|
||||
assert.Equal(t, 40, Get("years"))
|
||||
Set("years", 45)
|
||||
assert.Equal(t, 45, Get("age"))
|
||||
}
|
||||
|
||||
func TestAliasInConfigFile(t *testing.T) {
|
||||
// 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"))
|
||||
}
|
||||
|
||||
func TestYML(t *testing.T) {
|
||||
initYAML()
|
||||
assert.Equal(t, "steve", Get("name"))
|
||||
}
|
||||
|
||||
func TestJSON(t *testing.T) {
|
||||
initJSON()
|
||||
assert.Equal(t, "0001", Get("id"))
|
||||
}
|
||||
|
||||
func TestProperties(t *testing.T) {
|
||||
initProperties()
|
||||
assert.Equal(t, "0001", Get("p_id"))
|
||||
}
|
||||
|
||||
func TestTOML(t *testing.T) {
|
||||
initTOML()
|
||||
assert.Equal(t, "TOML Example", Get("title"))
|
||||
}
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
func TestRemotePrecedence(t *testing.T) {
|
||||
initJSON()
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
func TestEnv(t *testing.T) {
|
||||
initJSON()
|
||||
|
||||
BindEnv("id")
|
||||
BindEnv("f", "FOOD")
|
||||
|
||||
os.Setenv("ID", "13")
|
||||
os.Setenv("FOOD", "apple")
|
||||
os.Setenv("NAME", "crunk")
|
||||
|
||||
assert.Equal(t, "13", Get("id"))
|
||||
assert.Equal(t, "apple", Get("f"))
|
||||
assert.Equal(t, "Cake", Get("name"))
|
||||
|
||||
AutomaticEnv()
|
||||
|
||||
assert.Equal(t, "crunk", Get("name"))
|
||||
|
||||
}
|
||||
|
||||
func TestEnvPrefix(t *testing.T) {
|
||||
initJSON()
|
||||
|
||||
SetEnvPrefix("foo") // will be uppercased automatically
|
||||
BindEnv("id")
|
||||
BindEnv("f", "FOOD") // not using prefix
|
||||
|
||||
os.Setenv("FOO_ID", "13")
|
||||
os.Setenv("FOOD", "apple")
|
||||
os.Setenv("FOO_NAME", "crunk")
|
||||
|
||||
assert.Equal(t, "13", Get("id"))
|
||||
assert.Equal(t, "apple", Get("f"))
|
||||
assert.Equal(t, "Cake", Get("name"))
|
||||
|
||||
AutomaticEnv()
|
||||
|
||||
assert.Equal(t, "crunk", Get("name"))
|
||||
}
|
||||
|
||||
func TestAutoEnv(t *testing.T) {
|
||||
Reset()
|
||||
|
||||
AutomaticEnv()
|
||||
os.Setenv("FOO_BAR", "13")
|
||||
assert.Equal(t, "13", Get("foo_bar"))
|
||||
}
|
||||
|
||||
func TestAutoEnvWithPrefix(t *testing.T) {
|
||||
Reset()
|
||||
|
||||
AutomaticEnv()
|
||||
SetEnvPrefix("Baz")
|
||||
os.Setenv("BAZ_BAR", "13")
|
||||
assert.Equal(t, "13", Get("bar"))
|
||||
}
|
||||
|
||||
func TestSetEnvReplacer(t *testing.T) {
|
||||
Reset()
|
||||
|
||||
AutomaticEnv()
|
||||
os.Setenv("REFRESH_INTERVAL", "30s")
|
||||
|
||||
replacer := strings.NewReplacer("-", "_")
|
||||
SetEnvKeyReplacer(replacer)
|
||||
|
||||
assert.Equal(t, "30s", Get("refresh-interval"))
|
||||
}
|
||||
|
||||
func TestAllKeys(t *testing.T) {
|
||||
initConfigs()
|
||||
|
||||
ks := sort.StringSlice{"title", "newkey", "owner", "name", "beard", "ppu", "batters", "hobbies", "clothing", "age", "hacker", "id", "type", "eyes", "p_id", "p_ppu", "p_batters.batter.type", "p_type", "p_name", "foos"}
|
||||
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
|
||||
all := map[string]interface{}{"owner": map[string]interface{}{"organization": "MongoDB", "Bio": "MongoDB Chief Developer Advocate & Hacker at Large", "dob": dob}, "title": "TOML Example", "ppu": 0.55, "eyes": "brown", "clothing": map[interface{}]interface{}{"trousers": "denim", "jacket": "leather", "pants": map[interface{}]interface{}{"size": "large"}}, "id": "0001", "batters": map[string]interface{}{"batter": []interface{}{map[string]interface{}{"type": "Regular"}, map[string]interface{}{"type": "Chocolate"}, map[string]interface{}{"type": "Blueberry"}, map[string]interface{}{"type": "Devil's Food"}}}, "hacker": true, "beard": true, "hobbies": []interface{}{"skateboarding", "snowboarding", "go"}, "age": 35, "type": "donut", "newkey": "remote", "name": "Cake", "p_id": "0001", "p_ppu": "0.55", "p_name": "Cake", "p_batters.batter.type": "Regular", "p_type": "donut", "foos": []map[string]interface{}{map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"key": 1}, map[string]interface{}{"key": 2}, map[string]interface{}{"key": 3}, map[string]interface{}{"key": 4}}}}}
|
||||
|
||||
var allkeys sort.StringSlice
|
||||
allkeys = AllKeys()
|
||||
allkeys.Sort()
|
||||
ks.Sort()
|
||||
|
||||
assert.Equal(t, ks, allkeys)
|
||||
assert.Equal(t, all, AllSettings())
|
||||
}
|
||||
|
||||
func TestCaseInSensitive(t *testing.T) {
|
||||
assert.Equal(t, true, Get("hacker"))
|
||||
Set("Title", "Checking Case")
|
||||
assert.Equal(t, "Checking Case", Get("tItle"))
|
||||
}
|
||||
|
||||
func TestAliasesOfAliases(t *testing.T) {
|
||||
RegisterAlias("Foo", "Bar")
|
||||
RegisterAlias("Bar", "Title")
|
||||
assert.Equal(t, "Checking Case", Get("FOO"))
|
||||
}
|
||||
|
||||
func TestRecursiveAliases(t *testing.T) {
|
||||
RegisterAlias("Baz", "Roo")
|
||||
RegisterAlias("Roo", "baz")
|
||||
}
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
SetDefault("port", 1313)
|
||||
Set("name", "Steve")
|
||||
|
||||
type config struct {
|
||||
Port int
|
||||
Name string
|
||||
}
|
||||
|
||||
var C config
|
||||
|
||||
err := Unmarshal(&C)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decode into struct, %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, &C, &config{Name: "Steve", Port: 1313})
|
||||
|
||||
Set("port", 1234)
|
||||
err = Unmarshal(&C)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decode into struct, %v", err)
|
||||
}
|
||||
assert.Equal(t, &C, &config{Name: "Steve", Port: 1234})
|
||||
}
|
||||
|
||||
func TestBindPFlags(t *testing.T) {
|
||||
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
var testValues = map[string]*string{
|
||||
"host": nil,
|
||||
"port": nil,
|
||||
"endpoint": nil,
|
||||
}
|
||||
|
||||
var mutatedTestValues = map[string]string{
|
||||
"host": "localhost",
|
||||
"port": "6060",
|
||||
"endpoint": "/public",
|
||||
}
|
||||
|
||||
for name, _ := range testValues {
|
||||
testValues[name] = flagSet.String(name, "", "test")
|
||||
}
|
||||
|
||||
err := BindPFlags(flagSet)
|
||||
if err != nil {
|
||||
t.Fatalf("error binding flag set, %v", err)
|
||||
}
|
||||
|
||||
flagSet.VisitAll(func(flag *pflag.Flag) {
|
||||
flag.Value.Set(mutatedTestValues[flag.Name])
|
||||
flag.Changed = true
|
||||
})
|
||||
|
||||
for name, expected := range mutatedTestValues {
|
||||
assert.Equal(t, Get(name), expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBindPFlag(t *testing.T) {
|
||||
var testString = "testing"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "testflag",
|
||||
Value: testValue,
|
||||
Changed: false,
|
||||
}
|
||||
|
||||
BindPFlag("testvalue", flag)
|
||||
|
||||
assert.Equal(t, testString, Get("testvalue"))
|
||||
|
||||
flag.Value.Set("testing_mutate")
|
||||
flag.Changed = true //hack for pflag usage
|
||||
|
||||
assert.Equal(t, "testing_mutate", Get("testvalue"))
|
||||
|
||||
}
|
||||
|
||||
func TestBoundCaseSensitivity(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "brown", Get("eyes"))
|
||||
|
||||
BindEnv("eYEs", "TURTLE_EYES")
|
||||
os.Setenv("TURTLE_EYES", "blue")
|
||||
|
||||
assert.Equal(t, "blue", Get("eyes"))
|
||||
|
||||
var testString = "green"
|
||||
var testValue = newStringValue(testString, &testString)
|
||||
|
||||
flag := &pflag.Flag{
|
||||
Name: "eyeballs",
|
||||
Value: testValue,
|
||||
Changed: true,
|
||||
}
|
||||
|
||||
BindPFlag("eYEs", flag)
|
||||
assert.Equal(t, "green", Get("eyes"))
|
||||
|
||||
}
|
||||
|
||||
func TestSizeInBytes(t *testing.T) {
|
||||
input := map[string]uint{
|
||||
"": 0,
|
||||
"b": 0,
|
||||
"12 bytes": 0,
|
||||
"200000000000gb": 0,
|
||||
"12 b": 12,
|
||||
"43 MB": 43 * (1 << 20),
|
||||
"10mb": 10 * (1 << 20),
|
||||
"1gb": 1 << 30,
|
||||
}
|
||||
|
||||
for str, expected := range input {
|
||||
assert.Equal(t, expected, parseSizeInBytes(str), str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindsNestedKeys(t *testing.T) {
|
||||
initConfigs()
|
||||
dob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
|
||||
|
||||
Set("super", map[string]interface{}{
|
||||
"deep": map[string]interface{}{
|
||||
"nested": "value",
|
||||
},
|
||||
})
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"super": map[string]interface{}{
|
||||
"deep": map[string]interface{}{
|
||||
"nested": "value",
|
||||
},
|
||||
},
|
||||
"super.deep": map[string]interface{}{
|
||||
"nested": "value",
|
||||
},
|
||||
"super.deep.nested": "value",
|
||||
"owner.organization": "MongoDB",
|
||||
"batters.batter": []interface{}{
|
||||
map[string]interface{}{
|
||||
"type": "Regular",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Chocolate",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Blueberry",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Devil's Food",
|
||||
},
|
||||
},
|
||||
"hobbies": []interface{}{
|
||||
"skateboarding", "snowboarding", "go",
|
||||
},
|
||||
"title": "TOML Example",
|
||||
"newkey": "remote",
|
||||
"batters": map[string]interface{}{
|
||||
"batter": []interface{}{
|
||||
map[string]interface{}{
|
||||
"type": "Regular",
|
||||
},
|
||||
map[string]interface{}{
|
||||
"type": "Chocolate",
|
||||
}, map[string]interface{}{
|
||||
"type": "Blueberry",
|
||||
}, map[string]interface{}{
|
||||
"type": "Devil's Food",
|
||||
},
|
||||
},
|
||||
},
|
||||
"eyes": "brown",
|
||||
"age": 35,
|
||||
"owner": map[string]interface{}{
|
||||
"organization": "MongoDB",
|
||||
"Bio": "MongoDB Chief Developer Advocate & Hacker at Large",
|
||||
"dob": dob,
|
||||
},
|
||||
"owner.Bio": "MongoDB Chief Developer Advocate & Hacker at Large",
|
||||
"type": "donut",
|
||||
"id": "0001",
|
||||
"name": "Cake",
|
||||
"hacker": true,
|
||||
"ppu": 0.55,
|
||||
"clothing": map[interface{}]interface{}{
|
||||
"jacket": "leather",
|
||||
"trousers": "denim",
|
||||
"pants": map[interface{}]interface{}{
|
||||
"size": "large",
|
||||
},
|
||||
},
|
||||
"clothing.jacket": "leather",
|
||||
"clothing.pants.size": "large",
|
||||
"clothing.trousers": "denim",
|
||||
"owner.dob": dob,
|
||||
"beard": true,
|
||||
"foos": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"foo": []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"key": 1,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"key": 2,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"key": 3,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"key": 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for key, expectedValue := range expected {
|
||||
|
||||
assert.Equal(t, expectedValue, v.Get(key))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReadBufConfig(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yaml")
|
||||
v.ReadConfig(bytes.NewBuffer(yamlExample))
|
||||
t.Log(v.AllKeys())
|
||||
|
||||
assert.True(t, v.InConfig("name"))
|
||||
assert.False(t, v.InConfig("state"))
|
||||
assert.Equal(t, "steve", v.Get("name"))
|
||||
assert.Equal(t, []interface{}{"skateboarding", "snowboarding", "go"}, v.Get("hobbies"))
|
||||
assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[interface{}]interface{}{"size": "large"}}, v.Get("clothing"))
|
||||
assert.Equal(t, 35, v.Get("age"))
|
||||
}
|
||||
|
||||
func TestIsSet(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yaml")
|
||||
v.ReadConfig(bytes.NewBuffer(yamlExample))
|
||||
assert.True(t, v.IsSet("clothing.jacket"))
|
||||
assert.False(t, v.IsSet("clothing.jackets"))
|
||||
assert.False(t, v.IsSet("helloworld"))
|
||||
v.Set("helloworld", "fubar")
|
||||
assert.True(t, v.IsSet("helloworld"))
|
||||
}
|
||||
|
||||
func TestDirsSearch(t *testing.T) {
|
||||
|
||||
root, config, cleanup := initDirs(t)
|
||||
defer cleanup()
|
||||
|
||||
v := New()
|
||||
v.SetConfigName(config)
|
||||
v.SetDefault(`key`, `default`)
|
||||
|
||||
entries, err := ioutil.ReadDir(root)
|
||||
for _, e := range entries {
|
||||
if e.IsDir() {
|
||||
v.AddConfigPath(e.Name())
|
||||
}
|
||||
}
|
||||
|
||||
err = v.ReadInConfig()
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, `value is `+path.Base(v.configPaths[0]), v.GetString(`key`))
|
||||
}
|
||||
|
||||
func TestWrongDirsSearchNotFound(t *testing.T) {
|
||||
|
||||
_, config, cleanup := initDirs(t)
|
||||
defer cleanup()
|
||||
|
||||
v := New()
|
||||
v.SetConfigName(config)
|
||||
v.SetDefault(`key`, `default`)
|
||||
|
||||
v.AddConfigPath(`whattayoutalkingbout`)
|
||||
v.AddConfigPath(`thispathaintthere`)
|
||||
|
||||
err := v.ReadInConfig()
|
||||
assert.Equal(t, reflect.TypeOf(UnsupportedConfigError("")), reflect.TypeOf(err))
|
||||
|
||||
// Even though config did not load and the error might have
|
||||
// been ignored by the client, the default still loads
|
||||
assert.Equal(t, `default`, v.GetString(`key`))
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yaml")
|
||||
v.ReadConfig(bytes.NewBuffer(yamlExample))
|
||||
|
||||
subv := v.Sub("clothing")
|
||||
assert.Equal(t, v.Get("clothing.pants.size"), subv.Get("pants.size"))
|
||||
|
||||
subv = v.Sub("clothing.pants")
|
||||
assert.Equal(t, v.Get("clothing.pants.size"), subv.Get("size"))
|
||||
|
||||
subv = v.Sub("clothing.pants.size")
|
||||
assert.Equal(t, subv, (*Viper)(nil))
|
||||
}
|
||||
|
||||
var yamlMergeExampleTgt = []byte(`
|
||||
hello:
|
||||
pop: 37890
|
||||
world:
|
||||
- us
|
||||
- uk
|
||||
- fr
|
||||
- de
|
||||
`)
|
||||
|
||||
var yamlMergeExampleSrc = []byte(`
|
||||
hello:
|
||||
pop: 45000
|
||||
universe:
|
||||
- mw
|
||||
- ad
|
||||
fu: bar
|
||||
`)
|
||||
|
||||
func TestMergeConfig(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yml")
|
||||
if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pop := v.GetInt("hello.pop"); pop != 37890 {
|
||||
t.Fatalf("pop != 37890, = %d", pop)
|
||||
}
|
||||
|
||||
if world := v.GetStringSlice("hello.world"); len(world) != 4 {
|
||||
t.Fatalf("len(world) != 4, = %d", len(world))
|
||||
}
|
||||
|
||||
if fu := v.GetString("fu"); fu != "" {
|
||||
t.Fatalf("fu != \"\", = %s", fu)
|
||||
}
|
||||
|
||||
if err := v.MergeConfig(bytes.NewBuffer(yamlMergeExampleSrc)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pop := v.GetInt("hello.pop"); pop != 45000 {
|
||||
t.Fatalf("pop != 45000, = %d", pop)
|
||||
}
|
||||
|
||||
if world := v.GetStringSlice("hello.world"); len(world) != 4 {
|
||||
t.Fatalf("len(world) != 4, = %d", len(world))
|
||||
}
|
||||
|
||||
if universe := v.GetStringSlice("hello.universe"); len(universe) != 2 {
|
||||
t.Fatalf("len(universe) != 2, = %d", len(universe))
|
||||
}
|
||||
|
||||
if fu := v.GetString("fu"); fu != "bar" {
|
||||
t.Fatalf("fu != \"bar\", = %s", fu)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeConfigNoMerge(t *testing.T) {
|
||||
v := New()
|
||||
v.SetConfigType("yml")
|
||||
if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleTgt)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pop := v.GetInt("hello.pop"); pop != 37890 {
|
||||
t.Fatalf("pop != 37890, = %d", pop)
|
||||
}
|
||||
|
||||
if world := v.GetStringSlice("hello.world"); len(world) != 4 {
|
||||
t.Fatalf("len(world) != 4, = %d", len(world))
|
||||
}
|
||||
|
||||
if fu := v.GetString("fu"); fu != "" {
|
||||
t.Fatalf("fu != \"\", = %s", fu)
|
||||
}
|
||||
|
||||
if err := v.ReadConfig(bytes.NewBuffer(yamlMergeExampleSrc)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pop := v.GetInt("hello.pop"); pop != 45000 {
|
||||
t.Fatalf("pop != 45000, = %d", pop)
|
||||
}
|
||||
|
||||
if world := v.GetStringSlice("hello.world"); len(world) != 0 {
|
||||
t.Fatalf("len(world) != 0, = %d", len(world))
|
||||
}
|
||||
|
||||
if universe := v.GetStringSlice("hello.universe"); len(universe) != 2 {
|
||||
t.Fatalf("len(universe) != 2, = %d", len(universe))
|
||||
}
|
||||
|
||||
if fu := v.GetString("fu"); fu != "bar" {
|
||||
t.Fatalf("fu != \"bar\", = %s", fu)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalingWithAliases(t *testing.T) {
|
||||
SetDefault("Id", 1)
|
||||
Set("name", "Steve")
|
||||
Set("lastname", "Owen")
|
||||
|
||||
RegisterAlias("UserID", "Id")
|
||||
RegisterAlias("Firstname", "name")
|
||||
RegisterAlias("Surname", "lastname")
|
||||
|
||||
type config struct {
|
||||
Id int
|
||||
FirstName string
|
||||
Surname string
|
||||
}
|
||||
|
||||
var C config
|
||||
|
||||
err := Unmarshal(&C)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to decode into struct, %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, &C, &config{Id: 1, FirstName: "Steve", Surname: "Owen"})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue