diff --git a/cli/cmd.go b/cli/cmd.go new file mode 100644 index 0000000..ee44220 --- /dev/null +++ b/cli/cmd.go @@ -0,0 +1,257 @@ +package cli + +import ( + "flag" + "fmt" + "reflect" + "strconv" + "strings" + "unsafe" + + "github.com/eschao/config/utils" +) + +type anyValue struct { + any reflect.Value +} + +func newAnyValue(v reflect.Value) *anyValue { + return &anyValue{any: v} +} + +func (this *anyValue) String() string { + kind := this.any.Kind() + switch kind { + case reflect.Bool: + return strconv.FormatBool(this.any.Bool()) + case reflect.String: + return this.any.String() + case reflect.Int8, + reflect.Int16, + reflect.Int, + reflect.Int32, + reflect.Int64: + return strconv.FormatInt(this.any.Int(), 10) + case reflect.Uint8, + reflect.Uint16, + reflect.Uint, + reflect.Uint32, + reflect.Uint64: + return strconv.FormatUint(this.any.Uint(), 10) + case reflect.Float32: + return strconv.FormatFloat(this.any.Float(), 'E', -1, 32) + case reflect.Float64: + return strconv.FormatFloat(this.any.Float(), 'E', -1, 64) + } + return fmt.Sprintf("unsupport type %s", kind.String()) +} + +func (this *anyValue) Set(v string) error { + kind := this.any.Kind() + switch kind { + case reflect.String: + this.any.SetString(v) + case reflect.Float32: + return utils.SetValueWithFloatX(this.any, v, 32) + case reflect.Float64: + return utils.SetValueWithFloatX(this.any, v, 64) + case reflect.Int8: + return utils.SetValueWithIntX(this.any, v, 8) + case reflect.Int16: + return utils.SetValueWithIntX(this.any, v, 16) + case reflect.Int, reflect.Int32: + return utils.SetValueWithIntX(this.any, v, 32) + case reflect.Int64: + return utils.SetValueWithIntX(this.any, v, 64) + case reflect.Uint8: + return utils.SetValueWithUintX(this.any, v, 8) + case reflect.Uint16: + return utils.SetValueWithUintX(this.any, v, 16) + case reflect.Uint, reflect.Uint32: + return utils.SetValueWithUintX(this.any, v, 32) + case reflect.Uint64: + return utils.SetValueWithUintX(this.any, v, 64) + default: + return fmt.Errorf("Can't support type %s", kind.String()) + } + + return nil +} + +var errorHandling = flag.ExitOnError + +type UsageFunc func(*Command) func() + +var usageHandler UsageFunc = nil + +type Command struct { + Name string + FlagSet *flag.FlagSet + Usage string + SubCommands map[string]*Command +} + +func New(name string) *Command { + cmd := Command{ + Name: name, + FlagSet: flag.NewFlagSet(name, errorHandling), + SubCommands: make(map[string]*Command), + } + + return &cmd +} + +func NewWith(name string, errHandling flag.ErrorHandling, + usageHandling UsageFunc) *Command { + errorHandling = errHandling + usageHandler = usageHandling + + cmd := Command{ + Name: name, + FlagSet: flag.NewFlagSet(name, errorHandling), + SubCommands: make(map[string]*Command), + } + + if usageHandler != nil { + cmd.FlagSet.Usage = usageHandler(&cmd) + } + return &cmd +} + +func (this *Command) Init(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 type instead of %s", + valueOfStruct.Kind().String()) + } + + return this.parseValue(valueOfStruct) +} + +func (this *Command) parseValue(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) + + if kindOfField == reflect.Ptr { + if !valueOfField.IsNil() && valueOfField.CanSet() { + cmd := this.createCliFlagSet(structOfField.Tag) + if err := cmd.Init(valueOfField.Interface()); err != nil { + return err + } + } + } else if kindOfField == reflect.Struct { + cmd := this.createCliFlagSet(structOfField.Tag) + if err := cmd.parseValue(valueOfField); err != nil { + return err + } + } else { + if err := this.addFlag(valueOfField, structOfField); err != nil { + return err + } + } + } + + return nil +} + +func (this *Command) addFlag(v reflect.Value, f reflect.StructField) error { + cmdTag, ok := f.Tag.Lookup("cmd") + if !ok || cmdTag == "" { + return nil + } + + firstSpace := strings.Index(cmdTag, " ") + name := cmdTag + usage := "" + if firstSpace > 0 { + name = cmdTag[0:firstSpace] + usage = cmdTag[firstSpace+1:] + } + + kind := v.Kind() + switch kind { + case reflect.Bool: + this.FlagSet.BoolVar((*bool)(unsafe.Pointer(v.UnsafeAddr())), name, + false, usage) + return nil + case reflect.String, + reflect.Int8, + reflect.Int16, + reflect.Int, + reflect.Int32, + reflect.Int64, + reflect.Uint8, + reflect.Uint16, + reflect.Uint, + reflect.Uint32, + reflect.Uint64, + reflect.Float32, + reflect.Float64: + anyValue := newAnyValue(v) + this.FlagSet.Var(anyValue, name, usage) + default: + return fmt.Errorf("Can't support type %s", kind.String()) + } + + return nil +} + +func (this *Command) createCliFlagSet(tag reflect.StructTag) *Command { + cmdTag, ok := tag.Lookup("cmd") + if !ok || cmdTag == "" { + return this + } + + cmd := Command{SubCommands: make(map[string]*Command)} + firstSpace := strings.Index(cmdTag, " ") + name := cmdTag + usage := "" + if firstSpace > 0 { + name = cmdTag[0:firstSpace] + usage = cmdTag[firstSpace+1:] + } + + cmd.Name = name + cmd.FlagSet = flag.NewFlagSet(name, errorHandling) + cmd.Usage = usage + + if usageHandler != nil { + cmd.FlagSet.Usage = usageHandler(&cmd) + } + + this.SubCommands[name] = &cmd + return &cmd +} + +func (this *Command) Parse(args []string) error { + if err := this.FlagSet.Parse(args); err != nil { + return err + } + + unprocessed := this.FlagSet.Args() + if len(unprocessed) < 1 { + return nil + } + + if this.SubCommands == nil { + return fmt.Errorf("Command: %s is unsupport", unprocessed[0]) + } + + cmd := this.SubCommands[unprocessed[0]] + if cmd == nil { + return fmt.Errorf("Command: %s is unsupport", unprocessed[0]) + } + + return cmd.Parse(unprocessed[1:]) +} diff --git a/cli/cmd_test.go b/cli/cmd_test.go new file mode 100644 index 0000000..513bf9c --- /dev/null +++ b/cli/cmd_test.go @@ -0,0 +1,313 @@ +package cli + +import ( + "flag" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +type dbConfig struct { + Host string `cmd:"dbHost database server hostname"` + Port int `cmd:"dbPort database server port"` + User string `cmd:"dbUser database username"` + Password string `cmd:"dbPassword database user password"` + Log logConfig `cmd:"log database log configuration"` +} + +type loginConfig struct { + User string `cmd:"user login username"` + Password string `cmd:"password login password"` +} + +type logConfig struct { + Path string `cmd:"path log path"` + Level string `cmd:"level log level {debug|warning|error}"` +} + +type serviceConfig struct { + Host string `cmd:"hostname service hostname"` + Port int `cmd:"port service port"` + DBConfig dbConfig `cmd:"database database configuration"` + Login *loginConfig `cmd:"login login user and password"` + Log logConfig `cmd:"log service log configuration"` +} + +type typesConfig struct { + BoolValue bool `cmd:"bool boolean value"` + StrValue string `cmd:"str string value"` + Int8Value int8 `cmd:"int8 int8 value"` + Int16Value int16 `cmd:"int16 int16 value"` + IntValue int `cmd:"int int value"` + Int32Value int32 `cmd:"int32 int32 value"` + Int64Value int64 `cmd:"int64 int64 value"` + Uint8Value uint8 `cmd:"uint8 uint8 value"` + Uint16Value uint16 `cmd:"uint16 uint16 value"` + UintValue uint `cmd:"uint uint value"` + Uint32Value uint32 `cmd:"uint32 uint32 value"` + Uint64Value uint64 `cmd:"uint64 uint64 value"` + Float32Value float32 `cmd:"float32 float32 value"` + Float64Value float64 `cmd:"float64 float64 value"` +} + +type defValueConfig struct { + BoolValue bool `cmd:"bool boolean value" default:"true"` +} + +func TestServiceCommand(t *testing.T) { + assert := assert.New(t) + serviceConfig := serviceConfig{} + cmd := New("Service") + err := cmd.Init(&serviceConfig) + if err != nil { + t.Errorf("Can't init service command. %s", err.Error()) + } + + // assert service cmd + assert.NotNil(cmd.FlagSet) + assert.NotNil(cmd.FlagSet.Lookup("hostname"), + "service cmd should have {hostname} parameter") + assert.NotNil(cmd.FlagSet.Lookup("port"), + "service cmd should have {port} parameter") + assert.Equal(2, len(cmd.SubCommands), + "service cmd should have 2 sub cmds") + assert.Nil(cmd.SubCommands["login"], + "service cmd shouldn't have {login} sub cmd") + + // assert database sub cmd + dbCmd := cmd.SubCommands["database"] + assert.NotNil(dbCmd, "service cmd should have {database} sub cmd") + assert.NotNil(dbCmd.FlagSet.Lookup("dbHost"), + "database cmd should have {dbHost} parameter") + assert.NotNil(dbCmd.FlagSet.Lookup("dbPort"), + "database cmd should have {dbPort} parameter") + assert.NotNil(dbCmd.FlagSet.Lookup("dbUser"), + "database cmd should have {dbUser} parameter") + assert.NotNil(dbCmd.FlagSet.Lookup("dbPassword"), + "database cmd should have {dbPassword} parameter") + + // assert database log sub cmd + dbLogCmd := dbCmd.SubCommands["log"] + assert.NotNil(dbCmd, "database cmd should have {log} sub cmd") + assert.NotNil(dbLogCmd.FlagSet.Lookup("path"), + "database log cmd should have {path} parameter") + assert.NotNil(dbLogCmd.FlagSet.Lookup("level"), + "database log cmd should have {level} parameter") + assert.Equal(0, len(dbLogCmd.SubCommands), + "database log cmd shouldn't have sub cmd") + + // assert log cmd + logCmd := cmd.SubCommands["log"] + assert.NotNil(logCmd, "service cmd should have {log} sub cmd") + assert.NotNil(logCmd.FlagSet.Lookup("path"), + "log cmd should have {path} parameter") + assert.NotNil(logCmd.FlagSet.Lookup("level"), + "log cmd should have {level} parameter") +} + +func TestLoginSubCommand(t *testing.T) { + assert := assert.New(t) + serviceConfig := serviceConfig{Login: &loginConfig{}} + cmd := New("Service") + assert.NoError(cmd.Init(&serviceConfig), "Can't init service command") + + // assert login sub command + loginCmd := cmd.SubCommands["login"] + assert.NotNil(loginCmd, "service cmd should have {login} sub cmd") + assert.NotNil(loginCmd.FlagSet.Lookup("user"), + "login cmd should have {user} parameter") + assert.NotNil(loginCmd.FlagSet.Lookup("password"), + "login cmd should have {password} parameter") +} + +func TestLoginCommandWithValues(t *testing.T) { + assert := assert.New(t) + loginConfig := loginConfig{} + cmd := New("Login") + assert.NoError(cmd.Init(&loginConfig), "Can't init login command") + + username := "test-user" + password := "test-passwd" + args := []string{"-user", username, "--password", password} + assert.NoError(cmd.Parse(args), "Can't parse login command") + assert.Equal(username, loginConfig.User, "Failed to parse login command") + assert.Equal(password, loginConfig.Password, "Failed to parse login command") +} + +func TestServiceCommandWithValues(t *testing.T) { + assert := assert.New(t) + serviceConfig := serviceConfig{Login: &loginConfig{}} + cmd := New("Service") + assert.NoError(cmd.Init(&serviceConfig), "Can't init service command") + + serviceHost := "service-hostname" + servicePort := 8080 + serviceLogPath := "service-log-path" + serviceLogLevel := "service-log-debug" + + dbHost := "database-hostname" + dbPort := 9080 + dbUser := "database-user" + dbPassword := "database-passwd" + dbLogPath := "database-log-path" + dbLogLevel := "database-log-error" + + loginUser := "login-user" + loginPassword := "login-passwd" + + serviceArgs := []string{"--hostname", serviceHost, "--port", + strconv.Itoa(servicePort), "log", "-path", serviceLogPath, "-level", + serviceLogLevel} + assert.NoError(cmd.Parse(serviceArgs), "Can't parse service command") + assert.Equal(serviceHost, serviceConfig.Host, + "Service hostname is not equal") + assert.Equal(servicePort, serviceConfig.Port, + "Service port is not equal") + assert.Equal(serviceLogPath, serviceConfig.Log.Path, + "Service log path is not equal") + assert.Equal(serviceLogLevel, serviceConfig.Log.Level, + "Service log level is not equal") + + dbCmdArgs := []string{"database", "-dbHost", dbHost, "-dbPort", + strconv.Itoa(dbPort), "-dbUser", dbUser, "-dbPassword", dbPassword} + assert.NoError(cmd.Parse(dbCmdArgs), "Can't parse service database command") + assert.Equal(dbHost, serviceConfig.DBConfig.Host, + "Database hostname is not equal") + assert.Equal(dbPort, serviceConfig.DBConfig.Port, + "Database port is not equal") + assert.Equal(dbUser, serviceConfig.DBConfig.User, + "Database username is not equal") + assert.Equal(dbPassword, serviceConfig.DBConfig.Password, + "Database password is not equal") + + loginCmdArgs := []string{"login", "--user", loginUser, "-password", + loginPassword} + assert.NoError(cmd.Parse(loginCmdArgs), "Can't parse service login command") + assert.Equal(loginUser, serviceConfig.Login.User, + "Login username is not equal") + assert.Equal(loginPassword, serviceConfig.Login.Password, + "Login password is not equal") + + dbLogCmdArgs := []string{"database", "log", "-path", dbLogPath, "-level", + dbLogLevel} + assert.NoError(cmd.Parse(dbLogCmdArgs), "Can't parse database log command") + assert.Equal(dbLogPath, serviceConfig.DBConfig.Log.Path, + "Database log path is not equal") + assert.Equal(dbLogLevel, serviceConfig.DBConfig.Log.Level, + "Database log level is not equal") +} + +func TestVariousTypeCommand(t *testing.T) { + assert := assert.New(t) + typesConfig := typesConfig{} + cmd := NewWith("Types", flag.ContinueOnError, nil) + assert.NoError(cmd.Init(&typesConfig)) + + // bool value + assert.NoError(cmd.Parse([]string{"-bool=true"}), + "Can't parse bool value command") + assert.Equal(true, typesConfig.BoolValue, "Bool value is not true") + assert.NoError(cmd.Parse([]string{"-bool"}), + "Can't parse bool value command") + assert.Equal(true, typesConfig.BoolValue, "Bool value is not false") + assert.Error(cmd.Parse([]string{"-bool=xxx"}), + "Parsing string as bool should have an error") + + // string value + assert.NoError(cmd.Parse([]string{"-str=xxx"}), + "Can't parse string value command") + assert.Equal("xxx", typesConfig.StrValue, "String value it not equal") + assert.NoError(cmd.Parse([]string{"-str", "yyy"}), + "Can't parse string value command") + assert.Equal("yyy", typesConfig.StrValue, "String value is not equal") + + // int8 value + assert.NoError(cmd.Parse([]string{"-int8=100"}), + "Can't parse int8 value command") + assert.Equal(int8(100), typesConfig.Int8Value, "Int8 value is not equal") + assert.Error(cmd.Parse([]string{"-int8=xxx"}), + "Parsing string as int8 should have an error") + + // int16 value + assert.NoError(cmd.Parse([]string{"-int16=200"}), + "Can't parse int16 value command") + assert.Equal(int16(200), typesConfig.Int16Value, "Int16 value is not equal") + assert.Error(cmd.Parse([]string{"-int16=xxx"}), + "Parsing string as int16 should have an error") + + // int value + assert.NoError(cmd.Parse([]string{"-int=300"}), + "Can't parse int value command") + assert.Equal(int(300), typesConfig.IntValue, "Int value is not equal") + assert.Error(cmd.Parse([]string{"-int=xxx"}), + "Parsing string as int should have an error") + + // int32 value + assert.NoError(cmd.Parse([]string{"-int32=400"}), + "Can't parse int32 value command") + assert.Equal(int32(400), typesConfig.Int32Value, "Int32 value is not equal") + assert.Error(cmd.Parse([]string{"-int32=xxx"}), + "Parsing string as int32 should have an error") + + // int64 value + assert.NoError(cmd.Parse([]string{"-int64=500"}), + "Can't parse int64 value command") + assert.Equal(int64(500), typesConfig.Int64Value, "Int64 value is not equal") + assert.Error(cmd.Parse([]string{"-int64=xxx"}), + "Parsing string as int64 should have an error") + + // uint8 value + assert.NoError(cmd.Parse([]string{"-uint8=10"}), + "Can't parse uint8 value command") + assert.Equal(uint8(10), typesConfig.Uint8Value, "Uint8 value is not equal") + assert.Error(cmd.Parse([]string{"-uint8=-10"}), + "Parsing string as uint8 should have an error") + + // uint16 value + assert.NoError(cmd.Parse([]string{"-uint16=1000"}), + "Can't parse uint16 value command") + assert.Equal(uint16(1000), typesConfig.Uint16Value, + "Uint16 value is not equal") + assert.Error(cmd.Parse([]string{"-uint16=xxx"}), + "Parsing string as uint16 should have an error") + + // uint value + assert.NoError(cmd.Parse([]string{"-uint=2000"}), + "Can't parse uint value command") + assert.Equal(uint(2000), typesConfig.UintValue, "Uint value is not equal") + assert.Error(cmd.Parse([]string{"-uint=xxx"}), + "Parsing string as uint should have an error") + + // uint32 value + assert.NoError(cmd.Parse([]string{"-uint32=3000"}), + "Can't parse uint32 value command") + assert.Equal(uint32(3000), typesConfig.Uint32Value, + "Uint32 value is not equal") + assert.Error(cmd.Parse([]string{"-uint32=xxx"}), + "Parsing string as uint32 should have an error") + + // uint64 value + assert.NoError(cmd.Parse([]string{"-uint64=4000"}), + "Can't parse uint64 value command") + assert.Equal(uint64(4000), typesConfig.Uint64Value, + "Uint64 value is not equal") + assert.Error(cmd.Parse([]string{"-uint64=xxx"}), + "Parsing string as uint64 should have an error") + + // float32 value + assert.NoError(cmd.Parse([]string{"-float32=1.234"}), + "Can't parse float32 value command") + assert.Equal(float32(1.234), typesConfig.Float32Value, + "Float32 value is not equal") + assert.Error(cmd.Parse([]string{"-float32=xxx"}), + "Parsing string as float32 should have an error") + + // float64 value + assert.NoError(cmd.Parse([]string{"-float64=2.345"}), + "Can't parse float64 value command") + assert.Equal(float64(2.345), typesConfig.Float64Value, + "Float64 value is not equal") + assert.Error(cmd.Parse([]string{"-float64=xxx"}), + "Parsing string as float64 should have an error") +} diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index 9bc562e..0000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,139 +0,0 @@ -package cmd - -import ( - "flag" - "fmt" - "reflect" - "strings" - - "github.com/eschao/config/util" -) - -type anyValue struct { - any reflect.Value -} - -func newAnyValue(v Value) *anyValue { - return anyValue{any: v} -} - -func (this *anyValue) String() string { - return this.any.Kind().String() -} - -func (this *anyValue) Set(v string) error { - kind := this.any.Kind() - switch kind { - case reflect.Bool: - - } - return nil -} - -type Command struct { - Name string - FlagSet *flag.FlagSet - Usage string - SubCommands map[string]*Command -} - -func New(name string) *Command { - cmd := Command{ - Name: name, - FlagSet: flag.NewFlagSet(name, flag.ExitOnError), - SubCommands: make(map[string]*Command), - } - return &cmd -} - -func (this *Command) Init(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 type instead of %s", - valueOfStruct.Kind().String()) - } - - return this.parseValue(valueOfStruct) -} - -func (this *Command) parseValue(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) - - if kindOfField == reflect.Ptr { - if !valueOfField.IsNil() && valueOfField.CanSet() { - cmd := this.createCliFlagSet(structOfField.Tag) - if err := cmd.Init(valueOfField.Interface()); err != nil { - return err - } - } - } else if kindOfField == reflect.Struct { - cmd := this.createCliFlagSet(structOfField.Tag) - if err := cmd.parseValue(valueOfField); err != nil { - return err - } - } else { - this.addFlag(valueOfField, structOfField) - } - } - - return nil -} - -func (this *Command) addFlag(v reflect.Value, f reflect.StructField) { - cmdTag, ok := f.Tag.Lookup("cmd") - if !ok || cmdTag == "" { - return - } - - firstSpace := strings.Index(cmdTag, " ") - name := cmdTag - usage := "" - if firstSpace > 0 { - name = cmdTag[0:firstSpace] - usage = cmdTag[firstSpace+1:] - } - - //defValue, ok := f.Tag.Lookup("default") - vFlag := ValueFlag{Value: v} - this.FlagSet.Var(&vFlag, name, usage) - //fmt.Printf("[%s]: Added Flag: %s\n", this.Name, name) -} - -func (this *Command) createCliFlagSet(tag reflect.StructTag) *Command { - cmdTag, ok := tag.Lookup("cmd") - if !ok || cmdTag == "" { - return this - } - - cmd := Command{SubCommands: make(map[string]*Command)} - firstSpace := strings.Index(cmdTag, " ") - name := cmdTag - usage := "" - if firstSpace > 0 { - name = cmdTag[0:firstSpace] - usage = cmdTag[firstSpace+1:] - } - - cmd.Name = name - cmd.FlagSet = flag.NewFlagSet(name, flag.ExitOnError) - cmd.Usage = usage - this.SubCommands[name] = &cmd - return &cmd -} - -func (this *Command) Parse(i interface{}, args []string) error { - - return nil -} diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go deleted file mode 100644 index 1307f9c..0000000 --- a/cmd/cmd_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package cmd - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -type dbConfig struct { - Host string `cmd:"dbHost database server hostname"` - Port int `cmd:"dbPort database server port"` - User string `cmd:"dbUser database username"` - Password string `cmd:"dbPassword database user password"` - Log logConfig `cmd:"log database log configuration"` -} - -type loginConfig struct { - User string `cmd:"user login username"` - Password string `cmd:"password login password"` -} - -type logConfig struct { - Path string `cmd:"path log path"` - Level string `cmd:"level log level {debug|warning|error}"` -} - -type serviceConfig struct { - Host string `cmd:"hostname service hostname"` - Port int `cmd:"port service port"` - DBConfig dbConfig `cmd:"database database configuration"` - Login *loginConfig `cmd:"login login user and password"` - Log logConfig `cmd:"log service log configuration"` -} - -func TestServiceCommand(t *testing.T) { - assert := assert.New(t) - serviceConfig := serviceConfig{} - cmd := New("Service") - err := cmd.Init(&serviceConfig) - if err != nil { - t.Errorf("Can't init service command. %s", err.Error()) - } - - // assert service cmd - assert.NotNil(cmd.FlagSet) - assert.NotNil(cmd.FlagSet.Lookup("hostname"), - "service cmd should have {hostname} parameter") - assert.NotNil(cmd.FlagSet.Lookup("port"), - "service cmd should have {port} parameter") - assert.Equal(2, len(cmd.SubCommands), - "service cmd should have 2 sub cmds") - assert.Nil(cmd.SubCommands["login"], - "service cmd shouldn't have {login} sub cmd") - - // assert database sub cmd - dbCmd := cmd.SubCommands["database"] - assert.NotNil(dbCmd, "service cmd should have {database} sub cmd") - assert.NotNil(dbCmd.FlagSet.Lookup("dbHost"), - "database cmd should have {dbHost} parameter") - assert.NotNil(dbCmd.FlagSet.Lookup("dbPort"), - "database cmd should have {dbPort} parameter") - assert.NotNil(dbCmd.FlagSet.Lookup("dbUser"), - "database cmd should have {dbUser} parameter") - assert.NotNil(dbCmd.FlagSet.Lookup("dbPassword"), - "database cmd should have {dbPassword} parameter") - - // assert database log sub cmd - dbLogCmd := dbCmd.SubCommands["log"] - assert.NotNil(dbCmd, "database cmd should have {log} sub cmd") - assert.NotNil(dbLogCmd.FlagSet.Lookup("path"), - "database log cmd should have {path} parameter") - assert.NotNil(dbLogCmd.FlagSet.Lookup("level"), - "database log cmd should have {level} parameter") - assert.Equal(0, len(dbLogCmd.SubCommands), - "database log cmd shouldn't have sub cmd") - - // assert log cmd - logCmd := cmd.SubCommands["log"] - assert.NotNil(logCmd, "service cmd should have {log} sub cmd") - assert.NotNil(logCmd.FlagSet.Lookup("path"), - "log cmd should have {path} parameter") - assert.NotNil(logCmd.FlagSet.Lookup("level"), - "log cmd should have {level} parameter") -} - -func TestLoginSubCommand(t *testing.T) { - assert := assert.New(t) - serviceConfig := serviceConfig{Login: &loginConfig{}} - cmd := New("Service") - err := cmd.Init(&serviceConfig) - if err != nil { - t.Errorf("Can't init service command. %s", err.Error()) - } - - // assert login sub command - loginCmd := cmd.SubCommands["login"] - assert.NotNil(loginCmd, "service cmd should have {login} sub cmd") - assert.NotNil(loginCmd.FlagSet.Lookup("user"), - "login cmd should have {user} parameter") - assert.NotNil(loginCmd.FlagSet.Lookup("password"), - "login cmd should have {password} parameter") -} - -func TestLoginCommand(t *testing.T) { - loginConfig := loginConfig{} - cmd := New("Login") - if err := cmd.Init(&loginConfig); err != nil { - t.Errorf("Can't init login command. %s", err.Error()) - } - - args := []string{"-user", "test", "-password", "pass", "log", "database"} - if err := cmd.FlagSet.Parse(args); err != nil { - t.Errorf("Can't parse login command. %s", err.Error()) - } - - uknArgs := cmd.FlagSet.Args() - for i, arg := range uknArgs { - t.Logf("arg[%d]=%s", i, arg) - } -} diff --git a/util/util.go b/utils/utils.go similarity index 92% rename from util/util.go rename to utils/utils.go index 76011b4..57bac51 100644 --- a/util/util.go +++ b/utils/utils.go @@ -1,4 +1,4 @@ -package util +package utils import ( "reflect" @@ -26,7 +26,7 @@ func SetValueWithFloatX(v reflect.Value, floatValue string, bitSize int) error { } func SetValueWithIntX(v reflect.Value, intValue string, bitSize int) error { - value, err := strconv.ParseInt(envValue, 10, bitSize) + value, err := strconv.ParseInt(intValue, 10, bitSize) if err != nil { return err } @@ -35,8 +35,8 @@ func SetValueWithIntX(v reflect.Value, intValue string, bitSize int) error { return nil } -func SetValueWithUintX(v reflect.Value, envValue string, bitSize int) error { - value, err := strconv.ParseUint(envValue, 10, bitSize) +func SetValueWithUintX(v reflect.Value, uintValue string, bitSize int) error { + value, err := strconv.ParseUint(uintValue, 10, bitSize) if err != nil { return err }