add test and refactor codes
This commit is contained in:
parent
fca9c22d48
commit
e7703f94bf
@ -78,6 +78,27 @@ func (this *anyValue) Set(v string) error {
|
|||||||
return nil
|
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
|
var errorHandling = flag.ExitOnError
|
||||||
|
|
||||||
type UsageFunc func(*Command) func()
|
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 {
|
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 == "" {
|
if !ok || cmdTag == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -195,6 +216,9 @@ func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error {
|
|||||||
reflect.Float64:
|
reflect.Float64:
|
||||||
anyValue := newAnyValue(v)
|
anyValue := newAnyValue(v)
|
||||||
this.FlagSet.Var(anyValue, name, usage)
|
this.FlagSet.Var(anyValue, name, usage)
|
||||||
|
case reflect.Slice:
|
||||||
|
sliceValue := newSliceValue(v, f.Tag.Get("separator"))
|
||||||
|
this.FlagSet.Var(sliceValue, name, usage)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Can't support type %s", kind.String())
|
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 {
|
func (this *Command) createSubCommand(tag reflect.StructTag) *Command {
|
||||||
cmdTag, ok := tag.Lookup("cmd")
|
cmdTag, ok := tag.Lookup("cli")
|
||||||
if !ok || cmdTag == "" {
|
if !ok || cmdTag == "" {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
@ -207,3 +207,31 @@ func TestVariousTypeCommand(t *testing.T) {
|
|||||||
assert.Equal(float64(2.345), typesConfig.Float64Value)
|
assert.Equal(float64(2.345), typesConfig.Float64Value)
|
||||||
assert.Error(cmd.Parse([]string{"-float64=xxx"}))
|
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])
|
||||||
|
}
|
74
test/data.go
74
test/data.go
@ -1,59 +1,59 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
type DBConfig struct {
|
type DBConfig struct {
|
||||||
Host string `json:"dbHost" yaml:"dbHost" env:"HOST" cmd:"dbHost database server hostname"`
|
Host string `json:"dbHost" yaml:"dbHost" env:"HOST" cli:"dbHost database server hostname"`
|
||||||
Port int `json:"dbPort" yaml:"dbPort" env:"PORT" cmd:"dbPort database server port"`
|
Port int `json:"dbPort" yaml:"dbPort" env:"PORT" cli:"dbPort database server port"`
|
||||||
User string `json:"dbUser" yaml:"dbUser" env:"USER" cmd:"dbUser database username"`
|
User string `json:"dbUser" yaml:"dbUser" env:"USER" cli:"dbUser database username"`
|
||||||
Password string `json:"dbPassword" yaml:"dbPassword" env:"PASSWORD" cmd:"dbPassword database user password"`
|
Password string `json:"dbPassword" yaml:"dbPassword" env:"PASSWORD" cli:"dbPassword database user password"`
|
||||||
Log LogConfig `json:"log" yaml:"log" env:"LOG_" cmd:"log database log configuration"`
|
Log LogConfig `json:"log" yaml:"log" env:"LOG_" cli:"log database log configuration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoginConfig struct {
|
type LoginConfig struct {
|
||||||
User string `json:"user" yaml:"user" env:"USER" cmd:"user login username"`
|
User string `json:"user" yaml:"user" env:"USER" prop:"user" cli:"user login username"`
|
||||||
Password string `json:"password" yaml:"password" env:"PASSWORD" cmd:"password login password"`
|
Password string `json:"password" yaml:"password" env:"PASSWORD" prop:"password" cli:"password login password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
Path string `json:"path" yaml:"path" env:"PATH" cmd:"path log path"`
|
Path string `json:"path" yaml:"path" env:"PATH" prop:"path" cli:"path log path"`
|
||||||
Level string `json:"level" yaml:"level" env:"LEVEL" cmd:"level log level {debug|warning|error}"`
|
Level string `json:"level" yaml:"level" env:"LEVEL" porp:"level" cli:"level log level {debug|warning|error}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceConfig struct {
|
type ServiceConfig struct {
|
||||||
Host string `env:"CONFIG_TEST_SERVICE_HOST" cmd:"hostname service hostname"`
|
Host string `env:"CONFIG_TEST_SERVICE_HOST" cli:"hostname service hostname"`
|
||||||
Port int `env:"CONFIG_TEST_SERVICE_PORT" cmd:"port service port"`
|
Port int `env:"CONFIG_TEST_SERVICE_PORT" cli:"port service port"`
|
||||||
DBConfig DBConfig `env:"CONFIG_TEST_SERVICE_DB_" cmd:"database database configuration"`
|
DBConfig DBConfig `env:"CONFIG_TEST_SERVICE_DB_" cli:"database database configuration"`
|
||||||
Login *LoginConfig `env:"CONFIG_TEST_SERVICE_LOGIN_" cmd:"login login user and password"`
|
Login *LoginConfig `env:"CONFIG_TEST_SERVICE_LOGIN_" cli:"login login user and password"`
|
||||||
Log LogConfig `env:"CONFIG_TEST_SERVICE_LOG_" cmd:"log service log configuration"`
|
Log LogConfig `env:"CONFIG_TEST_SERVICE_LOG_" cli:"log service log configuration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypesConfig struct {
|
type TypesConfig struct {
|
||||||
BoolValue bool `env:"CONFIG_TEST_BOOL" cmd:"bool boolean value"`
|
BoolValue bool `env:"CONFIG_TEST_BOOL" cli:"bool boolean value"`
|
||||||
StrValue string `env:"CONFIG_TEST_STR" cmd:"str string value"`
|
StrValue string `env:"CONFIG_TEST_STR" cli:"str string value"`
|
||||||
Int8Value int8 `env:"CONFIG_TEST_INT8" cmd:"int8 int8 value"`
|
Int8Value int8 `env:"CONFIG_TEST_INT8" cli:"int8 int8 value"`
|
||||||
Int16Value int16 `env:"CONFIG_TEST_INT16" cmd:"int16 int16 value"`
|
Int16Value int16 `env:"CONFIG_TEST_INT16" cli:"int16 int16 value"`
|
||||||
IntValue int `env:"CONFIG_TEST_INT" cmd:"int int value"`
|
IntValue int `env:"CONFIG_TEST_INT" cli:"int int value"`
|
||||||
Int32Value int32 `env:"CONFIG_TEST_INT32" cmd:"int32 int32 value"`
|
Int32Value int32 `env:"CONFIG_TEST_INT32" cli:"int32 int32 value"`
|
||||||
Int64Value int64 `env:"CONFIG_TEST_INT64" cmd:"int64 int64 value"`
|
Int64Value int64 `env:"CONFIG_TEST_INT64" cli:"int64 int64 value"`
|
||||||
Uint8Value uint8 `env:"CONFIG_TEST_UINT8" cmd:"uint8 uint8 value"`
|
Uint8Value uint8 `env:"CONFIG_TEST_UINT8" cli:"uint8 uint8 value"`
|
||||||
Uint16Value uint16 `env:"CONFIG_TEST_UINT16" cmd:"uint16 uint16 value"`
|
Uint16Value uint16 `env:"CONFIG_TEST_UINT16" cli:"uint16 uint16 value"`
|
||||||
UintValue uint `env:"CONFIG_TEST_UINT" cmd:"uint uint value"`
|
UintValue uint `env:"CONFIG_TEST_UINT" cli:"uint uint value"`
|
||||||
Uint32Value uint32 `env:"CONFIG_TEST_UINT32" cmd:"uint32 uint32 value"`
|
Uint32Value uint32 `env:"CONFIG_TEST_UINT32" cli:"uint32 uint32 value"`
|
||||||
Uint64Value uint64 `env:"CONFIG_TEST_UINT64" cmd:"uint64 uint64 value"`
|
Uint64Value uint64 `env:"CONFIG_TEST_UINT64" cli:"uint64 uint64 value"`
|
||||||
Float32Value float32 `env:"CONFIG_TEST_FLOAT32" cmd:"float32 float32 value"`
|
Float32Value float32 `env:"CONFIG_TEST_FLOAT32" cli:"float32 float32 value"`
|
||||||
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cmd:"float64 float64 value"`
|
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cli:"float64 float64 value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefValueConfig struct {
|
type DefValueConfig struct {
|
||||||
BoolValue bool `env:"CONFIG_TEST_BOOL" cmd:"bool boolean value" default:"true"`
|
BoolValue bool `env:"CONFIG_TEST_BOOL" cli:"bool boolean value" default:"true"`
|
||||||
IntValue int `env:"CONFIG_TEST_INT" cmd:"int int value" default:"123"`
|
IntValue int `env:"CONFIG_TEST_INT" cli:"int int value" default:"123"`
|
||||||
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cmd:"float64 float64 value" default:"123.4567"`
|
Float64Value float64 `env:"CONFIG_TEST_FLOAT64" cli:"float64 float64 value" default:"123.4567"`
|
||||||
StrValue string `env:"CONFIG_TEST_STR" cmd:"str string value" default:"default-string"`
|
StrValue string `env:"CONFIG_TEST_STR" cli:"str string value" default:"default-string"`
|
||||||
SliceValue []string `env:"CONFIG_TEST_SLICE" cmd:"slice slice values" default:"xx:yy:zz"`
|
SliceValue []string `env:"CONFIG_TEST_SLICE" cli:"slice slice values" default:"xx:yy:zz"`
|
||||||
NoDefValue string `env:"CONFIG_TEST_NO_DEFVALUE" cmd:"nodefvalue no default value"`
|
NoDefValue string `env:"CONFIG_TEST_NO_DEFVALUE" cli:"nodefvalue no default value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SlicesConfig struct {
|
type SlicesConfig struct {
|
||||||
Paths []string `env:"CONFIG_TEST_SLICES_PATHS"`
|
Paths []string `env:"CONFIG_TEST_SLICES_PATHS" cli:"paths multiple path"`
|
||||||
Debugs []string `env:"CONFIG_TEST_SLICES_DEBUG" separator:";"`
|
Debugs []string `env:"CONFIG_TEST_SLICES_DEBUG" cli:"debugs multiple debug" separator:";"`
|
||||||
Values []int `env:"CONFIG_TEST_SLICES_VALUES" separator:","`
|
Values []int `env:"CONFIG_TEST_SLICES_VALUES" cli:"values multiple value" separator:","`
|
||||||
}
|
}
|
||||||
|
84
utils/utils_test.go
Normal file
84
utils/utils_test.go
Normal 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])
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user