update
This commit is contained in:
parent
816f4f97dc
commit
8f6edca654
51
.gitignore
vendored
51
.gitignore
vendored
@ -1,14 +1,47 @@
|
|||||||
# Binaries for programs and plugins
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
*.exe
|
*.o
|
||||||
*.dll
|
*.a
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# OS generated files #
|
||||||
*.out
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Eclipse generated files #
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings
|
||||||
|
**/target/
|
||||||
|
*/bin/
|
||||||
|
.metadata/
|
||||||
|
clientdb.xml
|
||||||
|
# jazz files #
|
||||||
|
.jazzignore
|
||||||
|
.factorypath
|
||||||
|
.gitignore
|
||||||
|
|
||||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
|
||||||
.glide/
|
|
||||||
|
118
cli/cli.go
Normal file
118
cli/cli.go
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CliFlag struct {
|
||||||
|
Name string
|
||||||
|
Usage string
|
||||||
|
DefValue *string
|
||||||
|
CliFlags *[]CliFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueFlag struct {
|
||||||
|
Value reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ValueFlag) String() string {
|
||||||
|
return this.Value.Kind().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ValueFlag) Set(v string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(i interface{}, cliFlag *CliFlag) error {
|
||||||
|
ptrRef := reflect.ValueOf(i)
|
||||||
|
|
||||||
|
if ptrRef.IsNil() || ptrRef.Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("Expect a structure pointer type instead of %s",
|
||||||
|
ptrRef.Kind().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
valueOfStruct := ptrRef.Elem()
|
||||||
|
if valueOfStruct.Kind() != reflect.Struct {
|
||||||
|
return fmt.Errorf("Expect a structure type instead of %s",
|
||||||
|
valueOfStruct.Kind().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseValue(valueOfStruct, cliFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseValue(v reflect.Value, cliParent *CliFlag) error {
|
||||||
|
cliFlags := []CliFlag{}
|
||||||
|
typeOfStruct := v.Type()
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
valueOfField := v.Field(i)
|
||||||
|
kindOfField := valueOfField.Kind()
|
||||||
|
structOfField := typeOfStruct.Field(i)
|
||||||
|
|
||||||
|
if kindOfField == reflect.Ptr {
|
||||||
|
if !valueOfField.IsNil() && valueOfField.CanSet() {
|
||||||
|
cliFlag := createCliFlagFromTag(structOfField.Tag)
|
||||||
|
if cliFlag != nil {
|
||||||
|
cliFlags = append(cliFlags, *cliFlag)
|
||||||
|
} else {
|
||||||
|
cliFlag = cliParent
|
||||||
|
}
|
||||||
|
Parse(valueOfField.Interface(), cliFlag)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if kindOfField == reflect.Struct {
|
||||||
|
cliFlag := createCliFlagFromTag(structOfField.Tag)
|
||||||
|
if cliFlag != nil {
|
||||||
|
cliFlags = append(cliFlags, *cliFlag)
|
||||||
|
} else {
|
||||||
|
cliFlag = cliParent
|
||||||
|
}
|
||||||
|
parseValue(valueOfField, cliFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cliFlag := installFlag(valueOfField, structOfField); cliFlag != nil {
|
||||||
|
cliFlags = append(cliFlags, *cliFlag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cliFlags) > 0 {
|
||||||
|
cliParent.CliFlags = &cliFlags
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func installFlag(v reflect.Value, f reflect.StructField) *CliFlag {
|
||||||
|
cliFlag := createCliFlagFromTag(f.Tag)
|
||||||
|
if cliFlag != nil {
|
||||||
|
vFlag := ValueFlag{Value: v}
|
||||||
|
flag.Var(&vFlag, cliFlag.Name, cliFlag.Usage)
|
||||||
|
}
|
||||||
|
fmt.Printf("Installed flag: %d", cliFlag.Name)
|
||||||
|
return cliFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
func createCliFlagFromTag(tag reflect.StructTag) *CliFlag {
|
||||||
|
cliTag, ok := tag.Lookup("cli")
|
||||||
|
if !ok || cliTag == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cliFlag := CliFlag{}
|
||||||
|
firstSpace := strings.Index(cliTag, " ")
|
||||||
|
cliFlag.Name = cliTag
|
||||||
|
if firstSpace > 0 {
|
||||||
|
cliFlag.Name = cliTag[0:firstSpace]
|
||||||
|
cliFlag.Usage = cliTag[firstSpace+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
defValue, ok := tag.Lookup("default")
|
||||||
|
if !ok {
|
||||||
|
cliFlag.DefValue = &defValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cliFlag
|
||||||
|
}
|
38
cli/cli_test.go
Normal file
38
cli/cli_test.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DBCli struct {
|
||||||
|
Host string `cli:"hostname database server hostname"`
|
||||||
|
Port string `cli:"port database server port"`
|
||||||
|
User string `cli:"user database username"`
|
||||||
|
Password string `cli:"password database user password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MyCli struct {
|
||||||
|
Server string `cli:"-server server URL"`
|
||||||
|
DBCli DBCli `cli:"database database information"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCli(t *testing.T) {
|
||||||
|
|
||||||
|
hostname := flag.String("hostanme", "127.0.0.1", "hostanme value")
|
||||||
|
fmt.Printf("Hostname: %s", hostname)
|
||||||
|
|
||||||
|
cli := DBCli{}
|
||||||
|
root := CliFlag{}
|
||||||
|
err := Parse(&cli, &root)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't parse cli. %s", err.Error())
|
||||||
|
}
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
}
|
47
config.go
Normal file
47
config.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
JsonName string
|
||||||
|
YamlName string
|
||||||
|
PropName string
|
||||||
|
EnvName string
|
||||||
|
CliName string
|
||||||
|
Value reflect.Value
|
||||||
|
DefaultValue string
|
||||||
|
Separator string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Fields []Field
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) Init() *Config {
|
||||||
|
if this.Fields == nil {
|
||||||
|
this.Fields = []Field{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Config) ParseJSON(jsonFile string, data interface{}) error {
|
||||||
|
raw, err := ioutil.ReadFile(jsonFile)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Can't open json file. Err: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(raw, data)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Failed unmarshal json. Err: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Printf("Data: %v", *data.(*interface{}))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
27
config_test.go
Normal file
27
config_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestConfig struct {
|
||||||
|
Name string `json:"name" default:"test-name"`
|
||||||
|
Path string `json:"path" default:"./"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONConfig(t *testing.T) {
|
||||||
|
config := Config{}
|
||||||
|
myConfig := TestConfig{}
|
||||||
|
err := config.Init().ParseJSON("test.json", &myConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("JSON config test failed. ", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if myConfig.Name != "jsonconfig" {
|
||||||
|
t.Errorf("Name json value: %s != jsonconfig", myConfig.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if myConfig.Path != "/var" {
|
||||||
|
t.Errorf("Path json value: %s != /var", myConfig.Path)
|
||||||
|
}
|
||||||
|
}
|
243
env/env.go
vendored
Normal file
243
env/env.go
vendored
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Unmarshal(i interface{}) error {
|
||||||
|
ptrRef := reflect.ValueOf(i)
|
||||||
|
|
||||||
|
if ptrRef.IsNil() || ptrRef.Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("Expect a structure pointer type instead of %s",
|
||||||
|
ptrRef.Kind().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
valueOfStruct := ptrRef.Elem()
|
||||||
|
if valueOfStruct.Kind() != reflect.Struct {
|
||||||
|
return fmt.Errorf("Expect a structure pointer type instead of %s",
|
||||||
|
valueOfStruct.Kind().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshal(valueOfStruct)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshal(v reflect.Value) error {
|
||||||
|
typeOfStruct := v.Type()
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
valueOfField := v.Field(i)
|
||||||
|
kindOfField := valueOfField.Kind()
|
||||||
|
structOfField := typeOfStruct.Field(i)
|
||||||
|
//fmt.Printf("Name: %s, Type: %s\n", structOfField.Name, kindOfField.String())
|
||||||
|
|
||||||
|
// recursively unmarshal if value is ptr type
|
||||||
|
if kindOfField == reflect.Ptr {
|
||||||
|
if !valueOfField.IsNil() && valueOfField.CanSet() {
|
||||||
|
Unmarshal(valueOfField.Interface())
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if kindOfField == reflect.Struct {
|
||||||
|
unmarshal(valueOfField)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFieldValue(valueOfField, structOfField); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnvValue(envName string, f reflect.StructField) (string, bool) {
|
||||||
|
envValue, ok := os.LookupEnv(envName)
|
||||||
|
if !ok {
|
||||||
|
envValue, ok = f.Tag.Lookup("default")
|
||||||
|
}
|
||||||
|
|
||||||
|
return envValue, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValue(v reflect.Value, f reflect.StructField) error {
|
||||||
|
envName := f.Tag.Get("env")
|
||||||
|
if envName == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
envValue, ok := getEnvValue(envName, f)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !v.CanSet() {
|
||||||
|
return fmt.Errorf("%s: can't be set", f.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := v.Kind()
|
||||||
|
name := f.Name
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
return setFieldValueWithBool(name, v, envValue)
|
||||||
|
|
||||||
|
case reflect.String:
|
||||||
|
v.SetString(envValue)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case reflect.Int8:
|
||||||
|
return setFieldValueWithIntX(name, v, envValue, 8)
|
||||||
|
|
||||||
|
case reflect.Int16:
|
||||||
|
return setFieldValueWithIntX(name, v, envValue, 16)
|
||||||
|
|
||||||
|
case reflect.Int, reflect.Int32:
|
||||||
|
return setFieldValueWithIntX(name, v, envValue, 32)
|
||||||
|
|
||||||
|
case reflect.Int64:
|
||||||
|
return setFieldValueWithIntX(name, v, envValue, 64)
|
||||||
|
|
||||||
|
case reflect.Uint8:
|
||||||
|
return setFieldValueWithUintX(name, v, envValue, 8)
|
||||||
|
|
||||||
|
case reflect.Uint16:
|
||||||
|
return setFieldValueWithUintX(name, v, envValue, 16)
|
||||||
|
|
||||||
|
case reflect.Uint, reflect.Uint32:
|
||||||
|
return setFieldValueWithUintX(name, v, envValue, 32)
|
||||||
|
|
||||||
|
case reflect.Uint64:
|
||||||
|
return setFieldValueWithUintX(name, v, envValue, 64)
|
||||||
|
|
||||||
|
case reflect.Float32:
|
||||||
|
return setFieldValueWithFloatX(name, v, envValue, 32)
|
||||||
|
|
||||||
|
case reflect.Float64:
|
||||||
|
return setFieldValueWithFloatX(name, v, envValue, 64)
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
sp, ok := f.Tag.Lookup("separator")
|
||||||
|
if !ok {
|
||||||
|
sp = ":"
|
||||||
|
}
|
||||||
|
return setFieldValueWithSlice(name, v, envValue, sp)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Can't support type: %s", kind.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValueWithBool(name string, v reflect.Value,
|
||||||
|
envValue string) error {
|
||||||
|
value, err := strconv.ParseBool(envValue)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: can't convert %s to bool value. %s", name, envValue,
|
||||||
|
err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
v.SetBool(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValueWithFloatX(name string, v reflect.Value, envValue string,
|
||||||
|
bitSize int) error {
|
||||||
|
value, err := strconv.ParseFloat(envValue, bitSize)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: can't convert %s to float%d value. %s", name,
|
||||||
|
envValue, bitSize, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
v.SetFloat(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValueWithIntX(name string, v reflect.Value, envValue string,
|
||||||
|
bitSize int) error {
|
||||||
|
value, err := strconv.ParseInt(envValue, 10, bitSize)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: can't convert %s to int%d value. %s", name,
|
||||||
|
envValue, bitSize, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
v.SetInt(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValueWithUintX(name string, v reflect.Value, envValue string,
|
||||||
|
bitSize int) error {
|
||||||
|
value, err := strconv.ParseUint(envValue, 10, bitSize)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s: can't convert %s to uint%d value. %s", name,
|
||||||
|
envValue, bitSize, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
v.SetUint(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFieldValueWithSlice(name string, v reflect.Value, envValue string,
|
||||||
|
separator string) error {
|
||||||
|
data := strings.Split(envValue, separator)
|
||||||
|
size := len(data)
|
||||||
|
if size > 0 {
|
||||||
|
slice := reflect.MakeSlice(v.Type(), size, size)
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
ele := slice.Index(i)
|
||||||
|
kind := ele.Kind()
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
if err := setFieldValueWithBool(name, ele, data[i]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
ele.SetString(data[i])
|
||||||
|
case reflect.Uint8:
|
||||||
|
if err := setFieldValueWithUintX(name, ele, data[i], 8); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Uint16:
|
||||||
|
if err := setFieldValueWithUintX(name, ele, data[i], 16); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint32:
|
||||||
|
if err := setFieldValueWithUintX(name, ele, data[i], 32); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
if err := setFieldValueWithUintX(name, ele, data[i], 64); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Int8:
|
||||||
|
if err := setFieldValueWithIntX(name, ele, data[i], 8); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Int16:
|
||||||
|
if err := setFieldValueWithIntX(name, ele, data[i], 16); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Int, reflect.Int32:
|
||||||
|
if err := setFieldValueWithIntX(name, ele, data[i], 32); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
if err := setFieldValueWithIntX(name, ele, data[i], 64); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Float32:
|
||||||
|
if err := setFieldValueWithFloatX(name, ele, data[i], 32); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case reflect.Float64:
|
||||||
|
if err := setFieldValueWithFloatX(name, ele, data[i], 64); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%s: can't support type: %s", name, kind.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.Set(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
194
env/env_test.go
vendored
Normal file
194
env/env_test.go
vendored
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package env
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EnvConfig1 struct {
|
||||||
|
Hostname string `env:"CONFIG_TEST_HOSTNAME" default:"localhost"`
|
||||||
|
Port int `env:"CONFIG_TEST_PORT"`
|
||||||
|
User string `env:"CONFIG_TEST_USER"`
|
||||||
|
Password string `env:"CONFIG_TEST_PASSWORD"`
|
||||||
|
Path1 []string `env:"CONFIG_TEST_PATH1"`
|
||||||
|
Path2 []string `env:"CONFIG_TEST_PATH2" separator:";"`
|
||||||
|
Home string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TEST_HOSTNAME = "test-hostname"
|
||||||
|
TEST_PORT = 8080
|
||||||
|
TEST_USER = "test-user"
|
||||||
|
TEST_PASSWORD = "test-password"
|
||||||
|
TEST_PATH1 = "/usr:/var:/bin"
|
||||||
|
TEST_PATH2 = "/root;/home;/tmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setEnvConfig1() {
|
||||||
|
os.Setenv("CONFIG_TEST_HOSTNAME", TEST_HOSTNAME)
|
||||||
|
os.Setenv("CONFIG_TEST_PORT", strconv.Itoa(TEST_PORT))
|
||||||
|
os.Setenv("CONFIG_TEST_USER", TEST_USER)
|
||||||
|
os.Setenv("CONFIG_TEST_PASSWORD", TEST_PASSWORD)
|
||||||
|
os.Setenv("CONFIG_TEST_PATH1", TEST_PATH1)
|
||||||
|
os.Setenv("CONFIG_TEST_PATH2", TEST_PATH2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetEnvConfig1() {
|
||||||
|
os.Unsetenv("CONFIG_TEST_HOSTNAME")
|
||||||
|
os.Unsetenv("CONFIG_TEST_PORT")
|
||||||
|
os.Unsetenv("CONFIG_TEST_USER")
|
||||||
|
os.Unsetenv("CONFIG_TEST_PASSWORD")
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertEqual(expected, actual []string) (bool, error) {
|
||||||
|
if len(expected) != len(actual) {
|
||||||
|
return false, fmt.Errorf("Expected length of array is %d, but actual is %d",
|
||||||
|
len(expected), len(actual))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(expected); i++ {
|
||||||
|
if expected[i] != actual[i] {
|
||||||
|
return false, fmt.Errorf("Expected array[%d]=%s, but acutal array[%d]=%s",
|
||||||
|
i, expected[i], i, actual[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvConfig1(t *testing.T) {
|
||||||
|
setEnvConfig1()
|
||||||
|
defer unsetEnvConfig1()
|
||||||
|
|
||||||
|
conf := EnvConfig1{}
|
||||||
|
err := Unmarshal(&conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't unmarshal config1 from environemnt variables. %s",
|
||||||
|
err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Hostname != TEST_HOSTNAME {
|
||||||
|
t.Errorf("Expect Hostname: %s, but got: %s", TEST_HOSTNAME, conf.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Port != TEST_PORT {
|
||||||
|
t.Errorf("Expect Port: %d, but got: %d", TEST_PORT, conf.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.User != TEST_USER {
|
||||||
|
t.Errorf("Expect User: %s, but got: %s", TEST_USER, conf.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Password != TEST_PASSWORD {
|
||||||
|
t.Errorf("Expect Password: %s, but got: %s", TEST_PASSWORD, conf.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Home != "" {
|
||||||
|
t.Errorf("Expect Home is empty, but got: %s", conf.Home)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedPath1 := strings.Split(TEST_PATH1, ":")
|
||||||
|
if ok, err := assertEqual(expectedPath1, conf.Path1); !ok {
|
||||||
|
t.Error(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedPath2 := strings.Split(TEST_PATH2, ";")
|
||||||
|
if ok, err := assertEqual(expectedPath2, conf.Path2); !ok {
|
||||||
|
t.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvConfig1WithDefaultValue(t *testing.T) {
|
||||||
|
os.Setenv("CONFIG_TEST_PORT", strconv.Itoa(TEST_PORT))
|
||||||
|
os.Setenv("CONFIG_TEST_USER", TEST_USER)
|
||||||
|
os.Setenv("CONFIG_TEST_PASSWORD", TEST_PASSWORD)
|
||||||
|
defer unsetEnvConfig1()
|
||||||
|
|
||||||
|
conf := EnvConfig1{}
|
||||||
|
err := Unmarshal(&conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't unmarshal config1 from environemnt variables. %s",
|
||||||
|
err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Hostname != "localhost" {
|
||||||
|
t.Errorf("Expect Hostname: localhost, bug got: %s", conf.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Port != TEST_PORT {
|
||||||
|
t.Errorf("Expect Port: %d, but got: %d", TEST_PORT, conf.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.User != TEST_USER {
|
||||||
|
t.Errorf("Expect User: %s, but got: %s", TEST_USER, conf.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Password != TEST_PASSWORD {
|
||||||
|
t.Errorf("Expect Password: %s, but got: %s", TEST_PASSWORD, conf.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Home != "" {
|
||||||
|
t.Errorf("Expect Home is empty, but got: %s", conf.Home)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnvConfig2 struct {
|
||||||
|
Config1 EnvConfig1
|
||||||
|
Server string `env:"CONFIG_ENV_TEST_SERVER"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TEST_SERVER = "test-server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setEnvConfig2() {
|
||||||
|
setEnvConfig1()
|
||||||
|
os.Setenv("CONFIG_ENV_TEST_SERVER", TEST_SERVER)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetEnvConfig2() {
|
||||||
|
unsetEnvConfig1()
|
||||||
|
os.Unsetenv("CONFIG_ENV_TEST_SERVER")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvConfig2(t *testing.T) {
|
||||||
|
setEnvConfig2()
|
||||||
|
defer unsetEnvConfig2()
|
||||||
|
|
||||||
|
conf := EnvConfig2{}
|
||||||
|
err := Unmarshal(&conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can't unmarshal config2 from environemnt variables. %s",
|
||||||
|
err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Config1.Hostname != TEST_HOSTNAME {
|
||||||
|
t.Errorf("Expect Hostname: %s, but got: %s", TEST_HOSTNAME, conf.Config1.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Config1.Port != TEST_PORT {
|
||||||
|
t.Errorf("Expect Port: %d, but got: %d", TEST_PORT, conf.Config1.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Config1.User != TEST_USER {
|
||||||
|
t.Errorf("Expect User: %s, but got: %s", TEST_USER, conf.Config1.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Config1.Password != TEST_PASSWORD {
|
||||||
|
t.Errorf("Expect Password: %s, but got: %s", TEST_PASSWORD, conf.Config1.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Config1.Home != "" {
|
||||||
|
t.Errorf("Expect Home is empty, but got: %s", conf.Config1.Home)
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Server != TEST_SERVER {
|
||||||
|
t.Errorf("Expect Server: %s, but got: %s", TEST_SERVER, conf.Server)
|
||||||
|
}
|
||||||
|
}
|
10
main.go
Normal file
10
main.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cli := DBCli{}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user