From 7b2a8b570e272ed479961840803bc89197f6707e Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Tue, 5 Sep 2017 18:40:07 +0200 Subject: [PATCH] Fix default values for pointers (print) Signed-off-by: Emile Vauge --- flaeg.go | 56 ++++++++++++++++++++++++++++----------------------- flaeg_test.go | 51 +++++++++++++++++++++++----------------------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/flaeg.go b/flaeg.go index 10aac07..93d7bdc 100644 --- a/flaeg.go +++ b/flaeg.go @@ -232,13 +232,11 @@ func getDefaultValue(defaultValue reflect.Value, defaultPointersValue reflect.Va case reflect.Ptr: if !defaultPointersValue.IsNil() { if len(key) != 0 { - //turn ptr fields to nil - defaultPointersNilValue, err := setPointersNil(defaultPointersValue) - if err != nil { - return err + if !defaultValue.IsNil() { + defaultValmap[name] = reflect.ValueOf(true) + } else { + defaultValmap[name] = reflect.ValueOf(false) } - defaultValmap[name] = defaultPointersNilValue - // fmt.Printf("%s: got default value %+v\n", name, defaultPointersNilValue) } if !defaultValue.IsNil() { if err := getDefaultValue(defaultValue.Elem(), defaultPointersValue.Elem(), defaultValmap, name); err != nil { @@ -252,8 +250,11 @@ func getDefaultValue(defaultValue reflect.Value, defaultPointersValue reflect.Va } else { instValue := reflect.New(defaultPointersValue.Type().Elem()) if len(key) != 0 { - defaultValmap[name] = instValue - // fmt.Printf("%s: got default value %+v\n", name, instValue) + if !defaultValue.IsNil() { + defaultValmap[name] = reflect.ValueOf(true) + } else { + defaultValmap[name] = reflect.ValueOf(false) + } } if !defaultValue.IsNil() { if err := getDefaultValue(defaultValue.Elem(), instValue.Elem(), defaultValmap, name); err != nil { @@ -296,14 +297,14 @@ func setPointersNil(objValue reflect.Value) (reflect.Value, error) { } //FillStructRecursive initialize a value of any taged Struct given by reference -func fillStructRecursive(objValue reflect.Value, defaultPointerValmap map[string]reflect.Value, valmap map[string]Parser, key string) error { +func fillStructRecursive(objValue reflect.Value, defaultPointersValue reflect.Value, defaultValmap map[string]reflect.Value, valmap map[string]Parser, key string) error { name := key switch objValue.Kind() { case reflect.Struct: for i := 0; i < objValue.Type().NumField(); i++ { if objValue.Type().Field(i).Anonymous { - if err := fillStructRecursive(objValue.Field(i), defaultPointerValmap, valmap, name); err != nil { + if err := fillStructRecursive(objValue.Field(i), defaultPointersValue.Field(i), defaultValmap, valmap, name); err != nil { return err } } else if len(objValue.Type().Field(i).Tag.Get("description")) > 0 { @@ -327,7 +328,7 @@ func fillStructRecursive(objValue reflect.Value, defaultPointerValmap map[string } } } - if err := fillStructRecursive(objValue.Field(i), defaultPointerValmap, valmap, name); err != nil { + if err := fillStructRecursive(objValue.Field(i), defaultPointersValue.Field(i), defaultValmap, valmap, name); err != nil { return err } } @@ -335,7 +336,7 @@ func fillStructRecursive(objValue reflect.Value, defaultPointerValmap map[string case reflect.Ptr: if len(key) == 0 && !objValue.IsNil() { - if err := fillStructRecursive(objValue.Elem(), defaultPointerValmap, valmap, name); err != nil { + if err := fillStructRecursive(objValue.Elem(), defaultPointersValue.Elem(), defaultValmap, valmap, name); err != nil { return err } return nil @@ -357,17 +358,20 @@ func fillStructRecursive(objValue reflect.Value, defaultPointerValmap map[string } if needDefault { - if defVal, ok := defaultPointerValmap[name]; ok { - //set default pointer value - // fmt.Printf("%s : set default value %+v\n", name, defVal) - objValue.Set(defVal) + //turn ptr fields to nil + defaultPointersNilValue, err := setPointersNil(defaultPointersValue) + if err != nil { + return fmt.Errorf("Error setting nil pointers to %s: %s", name, err) + } + if defaultPointersNilValue.Kind() == reflect.Bool { + objValue.Set(reflect.New(objValue.Type().Elem())) } else { - return fmt.Errorf("flag %s default value not provided", name) + objValue.Set(defaultPointersNilValue) } } if !objValue.IsNil() && contains { if objValue.Type().Elem().Kind() == reflect.Struct { - if err := fillStructRecursive(objValue.Elem(), defaultPointerValmap, valmap, name); err != nil { + if err := fillStructRecursive(objValue.Elem(), defaultPointersValue.Elem(), defaultValmap, valmap, name); err != nil { return err } } @@ -458,7 +462,7 @@ func LoadWithCommand(cmd *Command, cmdArgs []string, customParsers map[reflect.T return PrintErrorWithCommand(errParseArgs, tagsmap, defaultValmap, parsers, cmd, subCommand) } - if err := fillStructRecursive(reflect.ValueOf(cmd.Config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(cmd.Config), reflect.ValueOf(cmd.DefaultPointersConfig), defaultValmap, valmap, ""); err != nil { return err } @@ -545,13 +549,14 @@ func printFlagsDescriptionsDefaultValues(flagmap map[string]reflect.StructField, if defVal, ok := defaultValmap[flag]; ok { if defVal.Kind() != reflect.Ptr { // Set defaultValue on parsers - parsers[field.Type].SetValue(defaultValmap[flag].Interface()) - } - - if defVal := parsers[field.Type].String(); len(defVal) > 0 { - defaultValues = append(defaultValues, fmt.Sprintf("(default \"%s\")", defVal)) + parsers[field.Type].SetValue(defVal.Interface()) + if defValStr := parsers[field.Type].String(); len(defValStr) > 0 { + defaultValues = append(defaultValues, fmt.Sprintf("(default \"%s\")", defValStr)) + } else { + defaultValues = append(defaultValues, "") + } } else { - defaultValues = append(defaultValues, "") + defaultValues = append(defaultValues, fmt.Sprintf("(default \"%s\")", defVal)) } } @@ -565,6 +570,7 @@ func printFlagsDescriptionsDefaultValues(flagmap map[string]reflect.StructField, } } } + //add help flag shortFlagsWithDash = append(shortFlagsWithDash, "-h,") flagsWithDashs = append(flagsWithDashs, "--help") diff --git a/flaeg_test.go b/flaeg_test.go index 3239c8b..a017a81 100644 --- a/flaeg_test.go +++ b/flaeg_test.go @@ -724,21 +724,19 @@ func TestGetDefaultValueInitConfigAllDefault(t *testing.T) { t.Fatalf("Error %s", err.Error()) } //CHECK - checkDefaultStr := "DefaultOwnerNamePointer" - checkDefaultDob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") checkDob, _ := time.Parse(time.RFC3339, "1993-09-12T07:32:00Z") checkValue := map[string]reflect.Value{ "loglevel": reflect.ValueOf("DEBUG"), "timeout": reflect.ValueOf(Duration(time.Second)), - "db": reflect.ValueOf(&DatabaseInfo{ServerInfo: ServerInfo{Watch: true, IP: "192.168.1.2", Load: 32, Load64: 64}, ConnectionMax: 3200000000, ConnectionMax64: 6400000000000000000}), + "db": reflect.ValueOf(false), "db.watch": reflect.ValueOf(true), "db.ip": reflect.ValueOf("192.168.1.2"), "db.load": reflect.ValueOf(32), "db.load64": reflect.ValueOf(int64(64)), "db.comax": reflect.ValueOf(uint(3200000000)), "db.connectionmax64": reflect.ValueOf(uint64(6400000000000000000)), - "owner": reflect.ValueOf(&OwnerInfo{Name: nil, DateOfBirth: checkDefaultDob, Rate: 0.111, Servers: []ServerInfo{ServerInfo{Watch: false, IP: "192.168.1.2", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.3", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.4", Load: 0, Load64: 0}}}), - "owner.name": reflect.ValueOf(&checkDefaultStr), + "owner": reflect.ValueOf(true), + "owner.name": reflect.ValueOf(true), "owner.dob": reflect.ValueOf(checkDob), "owner.rate": reflect.ValueOf(float64(0.999)), "owner.servers": reflect.ValueOf(*new([]ServerInfo)), @@ -770,15 +768,15 @@ func TestGetDefaultValueNoConfigNoDefault(t *testing.T) { checkValue := map[string]reflect.Value{ "loglevel": reflect.ValueOf(""), "timeout": reflect.ValueOf(Duration(0)), - "db": reflect.ValueOf(&DatabaseInfo{}), + "db": reflect.ValueOf(false), "db.watch": reflect.ValueOf(false), "db.ip": reflect.ValueOf(""), "db.load": reflect.ValueOf(0), "db.load64": reflect.ValueOf(int64(0)), "db.comax": reflect.ValueOf(uint(0)), "db.connectionmax64": reflect.ValueOf(uint64(0)), - "owner": reflect.ValueOf(&OwnerInfo{}), - "owner.name": reflect.ValueOf(new(string)), + "owner": reflect.ValueOf(false), + "owner.name": reflect.ValueOf(false), "owner.dob": reflect.ValueOf(time.Time{}), "owner.rate": reflect.ValueOf(float64(0)), "owner.servers": reflect.ValueOf(*new([]ServerInfo)), @@ -812,15 +810,15 @@ func TestGetDefaultValueInitConfigNoDefault(t *testing.T) { checkValue := map[string]reflect.Value{ "loglevel": reflect.ValueOf(""), "timeout": reflect.ValueOf(Duration(time.Millisecond)), - "db": reflect.ValueOf(&DatabaseInfo{}), + "db": reflect.ValueOf(false), "db.watch": reflect.ValueOf(false), "db.ip": reflect.ValueOf(""), "db.load": reflect.ValueOf(0), "db.load64": reflect.ValueOf(int64(0)), "db.comax": reflect.ValueOf(uint(0)), "db.connectionmax64": reflect.ValueOf(uint64(0)), - "owner": reflect.ValueOf(&OwnerInfo{}), - "owner.name": reflect.ValueOf(new(string)), + "owner": reflect.ValueOf(false), + "owner.name": reflect.ValueOf(false), "owner.dob": reflect.ValueOf(time.Time{}), "owner.rate": reflect.ValueOf(float64(0)), "owner.servers": reflect.ValueOf(*new([]ServerInfo)), @@ -845,20 +843,19 @@ func TestGetDefaultNoConfigAllDefault(t *testing.T) { if err := getDefaultValue(reflect.ValueOf(config), reflect.ValueOf(defPointerConfig), defaultValmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } - checkStr := "DefaultOwnerNamePointer" checkDob, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") checkValue := map[string]reflect.Value{ "loglevel": reflect.ValueOf(""), "timeout": reflect.ValueOf(Duration(time.Duration(0))), - "db": reflect.ValueOf(&DatabaseInfo{ServerInfo: ServerInfo{Watch: true, IP: "192.168.1.2", Load: 32, Load64: 64}, ConnectionMax: 3200000000, ConnectionMax64: 6400000000000000000}), + "db": reflect.ValueOf(false), "db.watch": reflect.ValueOf(true), "db.ip": reflect.ValueOf("192.168.1.2"), "db.load": reflect.ValueOf(32), "db.load64": reflect.ValueOf(int64(64)), "db.comax": reflect.ValueOf(uint(3200000000)), "db.connectionmax64": reflect.ValueOf(uint64(6400000000000000000)), - "owner": reflect.ValueOf(&OwnerInfo{Name: nil, DateOfBirth: checkDob, Rate: 0.111, Servers: []ServerInfo{ServerInfo{Watch: false, IP: "192.168.1.2", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.3", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.4", Load: 0, Load64: 0}}}), - "owner.name": reflect.ValueOf(&checkStr), + "owner": reflect.ValueOf(false), + "owner.name": reflect.ValueOf(true), "owner.dob": reflect.ValueOf(checkDob), "owner.rate": reflect.ValueOf(float64(0.111)), "owner.servers": reflect.ValueOf([]ServerInfo{ServerInfo{Watch: false, IP: "192.168.1.2", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.3", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.4", Load: 0, Load64: 0}}), @@ -925,7 +922,7 @@ func TestFillStructRecursiveNoConfigNoDefaultTrivialValmap(t *testing.T) { } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1015,13 +1012,14 @@ func TestFillStructRecursiveNoConfigNoDefaultAllValmap(t *testing.T) { } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } //CHECK // fmt.Printf("Got : %+v\n", config) checkDob, _ := time.Parse(time.RFC3339, "2016-04-20T17:39:00Z") + str := "DefaultOwnerNamePointer" check := &Configuration{ LogLevel: "INFO", Timeout: Duration(time.Second), @@ -1036,7 +1034,7 @@ func TestFillStructRecursiveNoConfigNoDefaultAllValmap(t *testing.T) { ConnectionMax64: uint64(264), }, Owner: &OwnerInfo{ - Name: new(string), + Name: &str, DateOfBirth: checkDob, Rate: float64(0.222), Servers: []ServerInfo{ServerInfo{IP: "1.0.0.1"}}, @@ -1098,7 +1096,7 @@ func TestFillStructRecursiveNoConfigAllDefaultNoValmap(t *testing.T) { "owner.servers": reflect.ValueOf([]ServerInfo{ServerInfo{Watch: false, IP: "192.168.1.2", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.3", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.4", Load: 0, Load64: 0}}), } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1162,7 +1160,7 @@ func TestFillStructRecursiveInitConfigAllDefaultNoValmap(t *testing.T) { } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1233,7 +1231,7 @@ func TestFillStructRecursiveInitConfigAllDefaultPointerValmap(t *testing.T) { } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1320,7 +1318,7 @@ func TestFillStructRecursiveInitConfigAllDefaultPointerUnderPointerValmap(t *tes } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1401,7 +1399,7 @@ func TestFillStructRecursiveNoConfigAllDefaultSomeValmap(t *testing.T) { "owner.servers": reflect.ValueOf([]ServerInfo{ServerInfo{Watch: false, IP: "192.168.1.2", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.3", Load: 0, Load64: 0}, ServerInfo{Watch: false, IP: "192.168.1.4", Load: 0, Load64: 0}}), } //test - if err := fillStructRecursive(reflect.ValueOf(config), defaultValmap, valmap, ""); err != nil { + if err := fillStructRecursive(reflect.ValueOf(config), reflect.ValueOf(newDefaultPointersConfiguration()), defaultValmap, valmap, ""); err != nil { t.Errorf("Error %s", err.Error()) } @@ -1488,7 +1486,7 @@ func TestLoadWithParsersInitConfigNoDefaultAllFlag(t *testing.T) { //init config config := newConfiguration() //init default pointers - defaultPointers := &Configuration{} + defaultPointers := newDefaultPointersConfiguration() //init custom parsers customParsers := map[reflect.Type]Parser{ reflect.TypeOf([]ServerInfo{}): &sliceServerValue{}, @@ -1519,6 +1517,7 @@ func TestLoadWithParsersInitConfigNoDefaultAllFlag(t *testing.T) { //CHECK // fmt.Printf("Got : %+v\n", config) checkDob, _ := time.Parse(time.RFC3339, "2016-04-20T17:39:00Z") + str := "DefaultOwnerNamePointer" check := &Configuration{ Name: "initName", LogLevel: "INFO", @@ -1534,7 +1533,7 @@ func TestLoadWithParsersInitConfigNoDefaultAllFlag(t *testing.T) { ConnectionMax64: uint64(264), }, Owner: &OwnerInfo{ - Name: new(string), + Name: &str, DateOfBirth: checkDob, Rate: float64(0.222), Servers: []ServerInfo{ServerInfo{IP: "1.0.0.1"}}, @@ -2556,7 +2555,7 @@ func TestGetDefaultValueUnexportedFieldUnderPointer(t *testing.T) { } //check checkValue := map[string]reflect.Value{ - "ptrsubconfig": reflect.ValueOf(&SubConfigWithUnexportedField{"ExportedSubFieldDefault", nil}), + "ptrsubconfig": reflect.ValueOf(false), "ptrsubconfig.exported": reflect.ValueOf("ExportedSubFieldDefault"), } if len(checkValue) != len(defaultValmap) {