2
0

add test and refactor codes

This commit is contained in:
eschao 2017-12-11 23:13:02 +08:00
parent fca9c22d48
commit e7703f94bf
4 changed files with 175 additions and 39 deletions

View File

@ -78,6 +78,27 @@ func (this *anyValue) Set(v string) error {
return nil
}
type sliceValue struct {
value reflect.Value
separator string
}
func newSliceValue(v reflect.Value, separator string) *sliceValue {
return &sliceValue{value: v, separator: separator}
}
func (this *sliceValue) String() string {
return this.value.String()
}
func (this *sliceValue) Set(v string) error {
sp := this.separator
if sp == "" {
sp = ":"
}
return utils.SetValueWithSlice(this.value, v, sp)
}
var errorHandling = flag.ExitOnError
type UsageFunc func(*Command) func()
@ -161,7 +182,7 @@ func (this *Command) parseValue(v reflect.Value) error {
}
func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
cmdTag, ok := f.Tag.Lookup("cmd")
cmdTag, ok := f.Tag.Lookup("cli")
if !ok || cmdTag == "" {
return nil
}
@ -195,6 +216,9 @@ func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
reflect.Float64:
anyValue := newAnyValue(v)
this.FlagSet.Var(anyValue, name, usage)
case reflect.Slice:
sliceValue := newSliceValue(v, f.Tag.Get("separator"))
this.FlagSet.Var(sliceValue, name, usage)
default:
return fmt.Errorf("Can't support type %s", kind.String())
}
@ -203,7 +227,7 @@ func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
}
func (this *Command) createSubCommand(tag reflect.StructTag) *Command {
cmdTag, ok := tag.Lookup("cmd")
cmdTag, ok := tag.Lookup("cli")
if !ok || cmdTag == "" {
return this
}

View File

@ -207,3 +207,31 @@ func TestVariousTypeCommand(t *testing.T) {
assert.Equal(float64(2.345), typesConfig.Float64Value)
assert.Error(cmd.Parse([]string{"-float64=xxx"}))
}
func TestCommandWithSlices(t *testing.T) {
assert := assert.New(t)
conf := test.SlicesConfig{}
cmd := New("Slice")
assert.NoError(cmd.Init(&conf), "Can't init slice command")
paths := "/var:/home:/log"
debugs := "error;info;debug"
values := "100,200,300"
args := []string{"-paths", paths, "-debugs", debugs, "-values", values}
assert.NoError(cmd.Parse(args))
assert.Equal(3, len(conf.Paths))
assert.Equal("/var", conf.Paths[0])
assert.Equal("/home", conf.Paths[1])
assert.Equal("/log", conf.Paths[2])
assert.Equal(3, len(conf.Debugs))
assert.Equal("error", conf.Debugs[0])
assert.Equal("info", conf.Debugs[1])
assert.Equal("debug", conf.Debugs[2])
assert.Equal(3, len(conf.Values))
assert.Equal(100, conf.Values[0])
assert.Equal(200, conf.Values[1])
assert.Equal(300, conf.Values[2])
}

View File

@ -1,59 +1,59 @@
package test
type DBConfig struct {
Host string `json:"dbHost" yaml:"dbHost" env:"HOST" cmd:"dbHost database server hostname"`
Port int `json:"dbPort" yaml:"dbPort" env:"PORT" cmd:"dbPort database server port"`
User string `json:"dbUser" yaml:"dbUser" env:"USER" cmd:"dbUser database username"`
Password string `json:"dbPassword" yaml:"dbPassword" env:"PASSWORD" cmd:"dbPassword database user password"`
Log LogConfig `json:"log" yaml:"log" env:"LOG_" cmd:"log database log configuration"`
Host string `json:"dbHost" yaml:"dbHost" env:"HOST" cli:"dbHost database server hostname"`
Port int `json:"dbPort" yaml:"dbPort" env:"PORT" cli:"dbPort database server port"`
User string `json:"dbUser" yaml:"dbUser" env:"USER" cli:"dbUser database username"`
Password string `json:"dbPassword" yaml:"dbPassword" env:"PASSWORD" cli:"dbPassword database user password"`
Log LogConfig `json:"log" yaml:"log" env:"LOG_" cli:"log database log configuration"`
}
type LoginConfig struct {
User string `json:"user" yaml:"user" env:"USER" cmd:"user login username"`
Password string `json:"password" yaml:"password" env:"PASSWORD" cmd:"password login password"`
User string `json:"user" yaml:"user" env:"USER" prop:"user" cli:"user login username"`
Password string `json:"password" yaml:"password" env:"PASSWORD" prop:"password" cli:"password login password"`
}
type LogConfig struct {
Path string `json:"path" yaml:"path" env:"PATH" cmd:"path log path"`
Level string `json:"level" yaml:"level" env:"LEVEL" cmd:"level log level {debug|warning|error}"`
Path string `json:"path" yaml:"path" env:"PATH" prop:"path" cli:"path log path"`
Level string `json:"level" yaml:"level" env:"LEVEL" porp:"level" cli:"level log level {debug|warning|error}"`
}
type ServiceConfig struct {
Host string `env:"CONFIG_TEST_SERVICE_HOST" cmd:"hostname service hostname"`
Port int `env:"CONFIG_TEST_SERVICE_PORT" cmd:"port service port"`
DBConfig DBConfig `env:"CONFIG_TEST_SERVICE_DB_" cmd:"database database configuration"`
Login *LoginConfig `env:"CONFIG_TEST_SERVICE_LOGIN_" cmd:"login login user and password"`
Log LogConfig `env:"CONFIG_TEST_SERVICE_LOG_" cmd:"log service log configuration"`
Host string `env:"CONFIG_TEST_SERVICE_HOST" cli:"hostname service hostname"`
Port int `env:"CONFIG_TEST_SERVICE_PORT" cli:"port service port"`
DBConfig DBConfig `env:"CONFIG_TEST_SERVICE_DB_" cli:"database database configuration"`
Login *LoginConfig `env:"CONFIG_TEST_SERVICE_LOGIN_" cli:"login login user and password"`
Log LogConfig `env:"CONFIG_TEST_SERVICE_LOG_" cli:"log service log configuration"`
}
type TypesConfig struct {
BoolValue bool `env:"CONFIG_TEST_BOOL" cmd:"bool boolean value"`
StrValue string `env:"CONFIG_TEST_STR" cmd:"str string value"`
Int8Value int8 `env:"CONFIG_TEST_INT8" cmd:"int8 int8 value"`
Int16Value int16 `env:"CONFIG_TEST_INT16" cmd:"int16 int16 value"`
IntValue int `env:"CONFIG_TEST_INT" cmd:"int int value"`
Int32Value int32 `env:"CONFIG_TEST_INT32" cmd:"int32 int32 value"`
Int64Value int64 `env:"CONFIG_TEST_INT64" cmd:"int64 int64 value"`
Uint8Value uint8 `env:"CONFIG_TEST_UINT8" cmd:"uint8 uint8 value"`
Uint16Value uint16 `env:"CONFIG_TEST_UINT16" cmd:"uint16 uint16 value"`
UintValue uint `env:"CONFIG_TEST_UINT" cmd:"uint uint value"`
Uint32Value uint32 `env:"CONFIG_TEST_UINT32" cmd:"uint32 uint32 value"`
Uint64Value uint64 `env:"CONFIG_TEST_UINT64" cmd:"uint64 uint64 value"`
Float32Value float32 `env:"CONFIG_TEST_FLOAT32" cmd:"float32 float32 value"`
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cmd:"float64 float64 value"`
BoolValue bool `env:"CONFIG_TEST_BOOL" cli:"bool boolean value"`
StrValue string `env:"CONFIG_TEST_STR" cli:"str string value"`
Int8Value int8 `env:"CONFIG_TEST_INT8" cli:"int8 int8 value"`
Int16Value int16 `env:"CONFIG_TEST_INT16" cli:"int16 int16 value"`
IntValue int `env:"CONFIG_TEST_INT" cli:"int int value"`
Int32Value int32 `env:"CONFIG_TEST_INT32" cli:"int32 int32 value"`
Int64Value int64 `env:"CONFIG_TEST_INT64" cli:"int64 int64 value"`
Uint8Value uint8 `env:"CONFIG_TEST_UINT8" cli:"uint8 uint8 value"`
Uint16Value uint16 `env:"CONFIG_TEST_UINT16" cli:"uint16 uint16 value"`
UintValue uint `env:"CONFIG_TEST_UINT" cli:"uint uint value"`
Uint32Value uint32 `env:"CONFIG_TEST_UINT32" cli:"uint32 uint32 value"`
Uint64Value uint64 `env:"CONFIG_TEST_UINT64" cli:"uint64 uint64 value"`
Float32Value float32 `env:"CONFIG_TEST_FLOAT32" cli:"float32 float32 value"`
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cli:"float64 float64 value"`
}
type DefValueConfig struct {
BoolValue bool `env:"CONFIG_TEST_BOOL" cmd:"bool boolean value" default:"true"`
IntValue int `env:"CONFIG_TEST_INT" cmd:"int int value" default:"123"`
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cmd:"float64 float64 value" default:"123.4567"`
StrValue string `env:"CONFIG_TEST_STR" cmd:"str string value" default:"default-string"`
SliceValue []string `env:"CONFIG_TEST_SLICE" cmd:"slice slice values" default:"xx:yy:zz"`
NoDefValue string `env:"CONFIG_TEST_NO_DEFVALUE" cmd:"nodefvalue no default value"`
BoolValue bool `env:"CONFIG_TEST_BOOL" cli:"bool boolean value" default:"true"`
IntValue int `env:"CONFIG_TEST_INT" cli:"int int value" default:"123"`
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cli:"float64 float64 value" default:"123.4567"`
StrValue string `env:"CONFIG_TEST_STR" cli:"str string value" default:"default-string"`
SliceValue []string `env:"CONFIG_TEST_SLICE" cli:"slice slice values" default:"xx:yy:zz"`
NoDefValue string `env:"CONFIG_TEST_NO_DEFVALUE" cli:"nodefvalue no default value"`
}
type SlicesConfig struct {
Paths []string `env:"CONFIG_TEST_SLICES_PATHS"`
Debugs []string `env:"CONFIG_TEST_SLICES_DEBUG" separator:";"`
Values []int `env:"CONFIG_TEST_SLICES_VALUES" separator:","`
Paths []string `env:"CONFIG_TEST_SLICES_PATHS" cli:"paths multiple path"`
Debugs []string `env:"CONFIG_TEST_SLICES_DEBUG" cli:"debugs multiple debug" separator:";"`
Values []int `env:"CONFIG_TEST_SLICES_VALUES" cli:"values multiple value" separator:","`
}

84
utils/utils_test.go Normal file
View File

@ -0,0 +1,84 @@
package utils
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
type data struct {
BoolValue bool
Int8Value int8
IntValue int
Uint16Value uint16
UintValue uint
Float32Value float32
Names []string
}
func TestSetValueWithBool(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("BoolValue")
assert := assert.New(t)
assert.NoError(SetValueWithBool(v, "true"))
assert.Equal(true, d.BoolValue)
}
func TestSetValueWithFloat32(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("Float32Value")
assert := assert.New(t)
assert.NoError(SetValueWithFloatX(v, "123.456", 32))
assert.Equal(float32(123.456), d.Float32Value)
}
func TestSetValueWithInt8(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("Int8Value")
assert := assert.New(t)
assert.NoError(SetValueWithIntX(v, "10", 8))
assert.Equal(int8(10), d.Int8Value)
}
func TestSetValueWithInt(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("IntValue")
assert := assert.New(t)
assert.NoError(SetValueWithIntX(v, "10000", 32))
assert.Equal(10000, d.IntValue)
}
func TestSetValueWithUint16(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("Uint16Value")
assert := assert.New(t)
assert.NoError(SetValueWithUintX(v, "100", 16))
assert.Equal(uint16(100), d.Uint16Value)
}
func TestSetValueWithUint(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("UintValue")
assert := assert.New(t)
assert.NoError(SetValueWithUintX(v, "2000", 32))
assert.Equal(uint(2000), d.UintValue)
}
func TestSetValueWithSlice(t *testing.T) {
d := data{}
v := reflect.ValueOf(&d).Elem().FieldByName("Names")
assert := assert.New(t)
assert.NoError(SetValueWithSlice(v, "xx:yy:zz", ":"))
assert.Equal(3, len(d.Names))
assert.Equal("xx", d.Names[0])
assert.Equal("yy", d.Names[1])
assert.Equal("zz", d.Names[2])
}