summaryrefslogtreecommitdiffstats
path: root/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go')
-rw-r--r--dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go722
1 files changed, 722 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go
new file mode 100644
index 0000000..5bfba7b
--- /dev/null
+++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go
@@ -0,0 +1,722 @@
+package defaults
+
+import (
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/creasty/defaults/internal/fixture"
+)
+
+type (
+ MyInt int
+ MyInt8 int8
+ MyInt16 int16
+ MyInt32 int32
+ MyInt64 int64
+ MyUint uint
+ MyUint8 uint8
+ MyUint16 uint16
+ MyUint32 uint32
+ MyUint64 uint64
+ MyUintptr uintptr
+ MyFloat32 float32
+ MyFloat64 float64
+ MyBool bool
+ MyString string
+ MyMap map[string]int
+ MySlice []int
+)
+
+type Sample struct {
+ Int int `default:"1"`
+ Int8 int8 `default:"8"`
+ Int16 int16 `default:"16"`
+ Int32 int32 `default:"32"`
+ Int64 int64 `default:"64"`
+ Uint uint `default:"1"`
+ Uint8 uint8 `default:"8"`
+ Uint16 uint16 `default:"16"`
+ Uint32 uint32 `default:"32"`
+ Uint64 uint64 `default:"64"`
+ Uintptr uintptr `default:"1"`
+ Float32 float32 `default:"1.32"`
+ Float64 float64 `default:"1.64"`
+ BoolTrue bool `default:"true"`
+ BoolFalse bool `default:"false"`
+ String string `default:"hello"`
+ Duration time.Duration `default:"10s"`
+
+ IntOct int `default:"0o1"`
+ Int8Oct int8 `default:"0o10"`
+ Int16Oct int16 `default:"0o20"`
+ Int32Oct int32 `default:"0o40"`
+ Int64Oct int64 `default:"0o100"`
+ UintOct uint `default:"0o1"`
+ Uint8Oct uint8 `default:"0o10"`
+ Uint16Oct uint16 `default:"0o20"`
+ Uint32Oct uint32 `default:"0o40"`
+ Uint64Oct uint64 `default:"0o100"`
+
+ IntHex int `default:"0x1"`
+ Int8Hex int8 `default:"0x8"`
+ Int16Hex int16 `default:"0x10"`
+ Int32Hex int32 `default:"0x20"`
+ Int64Hex int64 `default:"0x40"`
+ UintHex uint `default:"0x1"`
+ Uint8Hex uint8 `default:"0x8"`
+ Uint16Hex uint16 `default:"0x10"`
+ Uint32Hex uint32 `default:"0x20"`
+ Uint64Hex uint64 `default:"0x40"`
+
+ IntBin int `default:"0b1"`
+ Int8Bin int8 `default:"0b1000"`
+ Int16Bin int16 `default:"0b10000"`
+ Int32Bin int32 `default:"0b100000"`
+ Int64Bin int64 `default:"0b1000000"`
+ UintBin uint `default:"0b1"`
+ Uint8Bin uint8 `default:"0b1000"`
+ Uint16Bin uint16 `default:"0b10000"`
+ Uint32Bin uint32 `default:"0b100000"`
+ Uint64Bin uint64 `default:"0b1000000"`
+
+ Struct Struct `default:"{}"`
+ Map map[string]int `default:"{}"`
+ Slice []string `default:"[]"`
+
+ IntPtr *int `default:"1"`
+ UintPtr *uint `default:"1"`
+ Float32Ptr *float32 `default:"1"`
+ BoolPtr *bool `default:"true"`
+ StringPtr *string `default:"hello"`
+ StructPtr *Struct `default:"{}"`
+ MapPtr *map[string]int `default:"{}"`
+ SlicePtr *[]string `default:"[]"`
+
+ MyInt MyInt `default:"1"`
+ MyInt8 MyInt8 `default:"8"`
+ MyInt16 MyInt16 `default:"16"`
+ MyInt32 MyInt32 `default:"32"`
+ MyInt64 MyInt64 `default:"64"`
+ MyUint MyUint `default:"1"`
+ MyUint8 MyUint8 `default:"8"`
+ MyUint16 MyUint16 `default:"16"`
+ MyUint32 MyUint32 `default:"32"`
+ MyUint64 MyUint64 `default:"64"`
+ MyUintptr MyUintptr `default:"1"`
+ MyFloat32 MyFloat32 `default:"1.32"`
+ MyFloat64 MyFloat64 `default:"1.64"`
+ MyBoolTrue MyBool `default:"true"`
+ MyBoolFalse MyBool `default:"false"`
+ MyString MyString `default:"hello"`
+ MyMap MyMap `default:"{}"`
+ MySlice MySlice `default:"[]"`
+
+ StructWithJSON Struct `default:"{\"Foo\": 123}"`
+ StructPtrWithJSON *Struct `default:"{\"Foo\": 123}"`
+ MapWithJSON map[string]int `default:"{\"foo\": 123}"`
+
+ MapOfPtrStruct map[string]*Struct
+ MapOfStruct map[string]Struct
+ MapOfStructWithTag map[string]Struct `default:"{\"Struct3\": {\"Foo\":123}}"`
+
+ SliceWithJSON []string `default:"[\"foo\"]"`
+
+ Empty string `default:""`
+
+ NoDefault *string `default:"-"`
+ NoDefaultStruct Struct `default:"-"`
+
+ MapWithNoTag map[string]int
+ SliceWithNoTag []string
+ StructPtrWithNoTag *Struct
+ StructWithNoTag Struct
+ DeepSliceOfStructWithNoTag [][][]Struct
+
+ NonInitialString string `default:"foo"`
+ NonInitialSlice []int `default:"[123]"`
+ NonInitialStruct Struct `default:"{}"`
+ NonInitialStructPtr *Struct `default:"{}"`
+}
+
+type Struct struct {
+ Embedded `default:"{}"`
+
+ Foo int
+ Bar int
+ WithDefault string `default:"foo"`
+}
+
+func (s *Struct) SetDefaults() {
+ s.Bar = 456
+}
+
+type Embedded struct {
+ Int int `default:"1"`
+}
+
+func TestMustSet(t *testing.T) {
+
+ t.Run("right way", func(t *testing.T) {
+ defer func() {
+ if err := recover(); err != nil {
+ t.Fatalf("it should not panic error: %v", err)
+ }
+ }()
+ sample := &Sample{
+ NonInitialString: "string",
+ NonInitialSlice: []int{1, 2, 3},
+ NonInitialStruct: Struct{Foo: 123},
+ NonInitialStructPtr: &Struct{Foo: 123},
+ DeepSliceOfStructWithNoTag: [][][]Struct{{{{Foo: 123}}}},
+ }
+ MustSet(sample)
+ })
+
+ t.Run("not struct", func(t *testing.T) {
+ defer func() {
+ if err := recover(); err != nil {
+ t.Logf("panic error: %v", err)
+ }
+ }()
+ var a int
+ MustSet(&a)
+ })
+
+ t.Run("not pointer", func(t *testing.T) {
+ defer func() {
+ if err := recover(); err != nil {
+ t.Logf("panic error: %v", err)
+ }
+ }()
+ sample := Sample{
+ NonInitialString: "string",
+ NonInitialSlice: []int{1, 2, 3},
+ NonInitialStruct: Struct{Foo: 123},
+ NonInitialStructPtr: &Struct{Foo: 123},
+ DeepSliceOfStructWithNoTag: [][][]Struct{{{{Foo: 123}}}},
+ }
+ MustSet(sample)
+ })
+
+}
+
+func TestInit(t *testing.T) {
+ sample := &Sample{
+ NonInitialString: "string",
+ NonInitialSlice: []int{1, 2, 3},
+ NonInitialStruct: Struct{Foo: 123},
+ NonInitialStructPtr: &Struct{Foo: 123},
+ DeepSliceOfStructWithNoTag: [][][]Struct{{{{Foo: 123}}}},
+ MapOfStruct: map[string]Struct{
+ "Struct1": {Foo: 1},
+ },
+ MapOfPtrStruct: map[string]*Struct{
+ "Struct1": {Foo: 1},
+ "Struct2": {Bar: 5},
+ },
+ }
+
+ if err := Set(sample); err != nil {
+ t.Fatalf("it should not return an error: %v", err)
+ }
+
+ nonPtrVal := 1
+
+ if err := Set(nonPtrVal); err == nil {
+ t.Fatalf("it should return an error when used for a non-pointer type")
+ }
+ if err := Set(&nonPtrVal); err == nil {
+ t.Fatalf("it should return an error when used for a non-pointer type")
+ }
+
+ Set(&fixture.Sample{}) // should not panic
+
+ t.Run("primitive types", func(t *testing.T) {
+ if sample.Int != 1 {
+ t.Errorf("it should initialize int")
+ }
+ if sample.Int8 != 8 {
+ t.Errorf("it should initialize int8")
+ }
+ if sample.Int16 != 16 {
+ t.Errorf("it should initialize int16")
+ }
+ if sample.Int32 != 32 {
+ t.Errorf("it should initialize int32")
+ }
+ if sample.Int64 != 64 {
+ t.Errorf("it should initialize int64")
+ }
+ if sample.Uint != 1 {
+ t.Errorf("it should initialize uint")
+ }
+ if sample.Uint8 != 8 {
+ t.Errorf("it should initialize uint8")
+ }
+ if sample.Uint16 != 16 {
+ t.Errorf("it should initialize uint16")
+ }
+ if sample.Uint32 != 32 {
+ t.Errorf("it should initialize uint32")
+ }
+ if sample.Uint64 != 64 {
+ t.Errorf("it should initialize uint64")
+ }
+ if sample.Uintptr != 1 {
+ t.Errorf("it should initialize uintptr")
+ }
+ if sample.Float32 != 1.32 {
+ t.Errorf("it should initialize float32")
+ }
+ if sample.Float64 != 1.64 {
+ t.Errorf("it should initialize float64")
+ }
+ if sample.BoolTrue != true {
+ t.Errorf("it should initialize bool (true)")
+ }
+ if sample.BoolFalse != false {
+ t.Errorf("it should initialize bool (false)")
+ }
+ if *sample.BoolPtr != true {
+ t.Errorf("it should initialize bool (true)")
+ }
+ if sample.String != "hello" {
+ t.Errorf("it should initialize string")
+ }
+
+ if sample.IntOct != 0o1 {
+ t.Errorf("it should initialize int with octal literal")
+ }
+ if sample.Int8Oct != 0o10 {
+ t.Errorf("it should initialize int8 with octal literal")
+ }
+ if sample.Int16Oct != 0o20 {
+ t.Errorf("it should initialize int16 with octal literal")
+ }
+ if sample.Int32Oct != 0o40 {
+ t.Errorf("it should initialize int32 with octal literal")
+ }
+ if sample.Int64Oct != 0o100 {
+ t.Errorf("it should initialize int64 with octal literal")
+ }
+ if sample.UintOct != 0o1 {
+ t.Errorf("it should initialize uint with octal literal")
+ }
+ if sample.Uint8Oct != 0o10 {
+ t.Errorf("it should initialize uint8 with octal literal")
+ }
+ if sample.Uint16Oct != 0o20 {
+ t.Errorf("it should initialize uint16 with octal literal")
+ }
+ if sample.Uint32Oct != 0o40 {
+ t.Errorf("it should initialize uint32 with octal literal")
+ }
+ if sample.Uint64Oct != 0o100 {
+ t.Errorf("it should initialize uint64 with octal literal")
+ }
+
+ if sample.IntHex != 0x1 {
+ t.Errorf("it should initialize int with hexadecimal literal")
+ }
+ if sample.Int8Hex != 0x8 {
+ t.Errorf("it should initialize int8 with hexadecimal literal")
+ }
+ if sample.Int16Hex != 0x10 {
+ t.Errorf("it should initialize int16 with hexadecimal literal")
+ }
+ if sample.Int32Hex != 0x20 {
+ t.Errorf("it should initialize int32 with hexadecimal literal")
+ }
+ if sample.Int64Hex != 0x40 {
+ t.Errorf("it should initialize int64 with hexadecimal literal")
+ }
+ if sample.UintHex != 0x1 {
+ t.Errorf("it should initialize uint with hexadecimal literal")
+ }
+ if sample.Uint8Hex != 0x8 {
+ t.Errorf("it should initialize uint8 with hexadecimal literal")
+ }
+ if sample.Uint16Hex != 0x10 {
+ t.Errorf("it should initialize uint16 with hexadecimal literal")
+ }
+ if sample.Uint32Hex != 0x20 {
+ t.Errorf("it should initialize uint32 with hexadecimal literal")
+ }
+ if sample.Uint64Hex != 0x40 {
+ t.Errorf("it should initialize uint64 with hexadecimal literal")
+ }
+
+ if sample.IntBin != 0b1 {
+ t.Errorf("it should initialize int with binary literal")
+ }
+ if sample.Int8Bin != 0b1000 {
+ t.Errorf("it should initialize int8 with binary literal")
+ }
+ if sample.Int16Bin != 0b10000 {
+ t.Errorf("it should initialize int16 with binary literal")
+ }
+ if sample.Int32Bin != 0b100000 {
+ t.Errorf("it should initialize int32 with binary literal")
+ }
+ if sample.Int64Bin != 0b1000000 {
+ t.Errorf("it should initialize int64 with binary literal")
+ }
+ if sample.UintBin != 0b1 {
+ t.Errorf("it should initialize uint with binary literal")
+ }
+ if sample.Uint8Bin != 0b1000 {
+ t.Errorf("it should initialize uint8 with binary literal")
+ }
+ if sample.Uint16Bin != 0b10000 {
+ t.Errorf("it should initialize uint16 with binary literal")
+ }
+ if sample.Uint32Bin != 0b100000 {
+ t.Errorf("it should initialize uint32 with binary literal")
+ }
+ if sample.Uint64Bin != 0b1000000 {
+ t.Errorf("it should initialize uint64 with binary literal")
+ }
+ })
+
+ t.Run("complex types", func(t *testing.T) {
+ if sample.StructPtr == nil {
+ t.Errorf("it should initialize struct pointer")
+ }
+ if sample.Map == nil {
+ t.Errorf("it should initialize map")
+ }
+ if sample.Slice == nil {
+ t.Errorf("it should initialize slice")
+ }
+ })
+
+ t.Run("pointer types", func(t *testing.T) {
+ if sample.IntPtr == nil || *sample.IntPtr != 1 {
+ t.Errorf("it should initialize int pointer")
+ }
+ if sample.UintPtr == nil || *sample.UintPtr != 1 {
+ t.Errorf("it should initialize uint pointer")
+ }
+ if sample.Float32Ptr == nil || *sample.Float32Ptr != 1 {
+ t.Errorf("it should initialize float32 pointer")
+ }
+ if sample.BoolPtr == nil || *sample.BoolPtr != true {
+ t.Errorf("it should initialize bool pointer")
+ }
+ if sample.StringPtr == nil || *sample.StringPtr != "hello" {
+ t.Errorf("it should initialize string pointer")
+ }
+ if sample.MapPtr == nil {
+ t.Errorf("it should initialize map ptr")
+ }
+ if sample.SlicePtr == nil {
+ t.Errorf("it should initialize slice ptr")
+ }
+ })
+
+ t.Run("aliased types", func(t *testing.T) {
+ if sample.MyInt != 1 {
+ t.Errorf("it should initialize int")
+ }
+ if sample.MyInt8 != 8 {
+ t.Errorf("it should initialize int8")
+ }
+ if sample.MyInt16 != 16 {
+ t.Errorf("it should initialize int16")
+ }
+ if sample.MyInt32 != 32 {
+ t.Errorf("it should initialize int32")
+ }
+ if sample.MyInt64 != 64 {
+ t.Errorf("it should initialize int64")
+ }
+ if sample.MyUint != 1 {
+ t.Errorf("it should initialize uint")
+ }
+ if sample.MyUint8 != 8 {
+ t.Errorf("it should initialize uint8")
+ }
+ if sample.MyUint16 != 16 {
+ t.Errorf("it should initialize uint16")
+ }
+ if sample.MyUint32 != 32 {
+ t.Errorf("it should initialize uint32")
+ }
+ if sample.MyUint64 != 64 {
+ t.Errorf("it should initialize uint64")
+ }
+ if sample.MyUintptr != 1 {
+ t.Errorf("it should initialize uintptr")
+ }
+ if sample.MyFloat32 != 1.32 {
+ t.Errorf("it should initialize float32")
+ }
+ if sample.MyFloat64 != 1.64 {
+ t.Errorf("it should initialize float64")
+ }
+ if sample.MyBoolTrue != true {
+ t.Errorf("it should initialize bool (true)")
+ }
+ if sample.MyBoolFalse != false {
+ t.Errorf("it should initialize bool (false)")
+ }
+ if sample.MyString != "hello" {
+ t.Errorf("it should initialize string")
+ }
+
+ if sample.MyMap == nil {
+ t.Errorf("it should initialize map")
+ }
+ if sample.MySlice == nil {
+ t.Errorf("it should initialize slice")
+ }
+ })
+
+ t.Run("nested", func(t *testing.T) {
+ if sample.Struct.WithDefault != "foo" {
+ t.Errorf("it should set default on inner field in struct")
+ }
+ if sample.StructPtr == nil || sample.StructPtr.WithDefault != "foo" {
+ t.Errorf("it should set default on inner field in struct pointer")
+ }
+ if sample.Struct.Embedded.Int != 1 {
+ t.Errorf("it should set default on an Embedded struct")
+ }
+ })
+
+ t.Run("complex types with json", func(t *testing.T) {
+ if sample.StructWithJSON.Foo != 123 {
+ t.Errorf("it should initialize struct with json")
+ }
+ if sample.StructPtrWithJSON == nil || sample.StructPtrWithJSON.Foo != 123 {
+ t.Errorf("it should initialize struct pointer with json")
+ }
+ if sample.MapWithJSON["foo"] != 123 {
+ t.Errorf("it should initialize map with json")
+ }
+ if len(sample.SliceWithJSON) == 0 || sample.SliceWithJSON[0] != "foo" {
+ t.Errorf("it should initialize slice with json")
+ }
+
+ t.Run("invalid json", func(t *testing.T) {
+ if err := Set(&struct {
+ I []int `default:"[!]"`
+ }{}); err == nil {
+ t.Errorf("it should return error")
+ }
+
+ if err := Set(&struct {
+ I map[string]int `default:"{1}"`
+ }{}); err == nil {
+ t.Errorf("it should return error")
+ }
+
+ if err := Set(&struct {
+ S struct {
+ I []int
+ } `default:"{!}"`
+ }{}); err == nil {
+ t.Errorf("it should return error")
+ }
+
+ if err := Set(&struct {
+ S struct {
+ I []int `default:"[!]"`
+ }
+ }{}); err == nil {
+ t.Errorf("it should return error")
+ }
+ })
+ })
+
+ t.Run("Setter interface", func(t *testing.T) {
+ if sample.Struct.Bar != 456 {
+ t.Errorf("it should initialize struct")
+ }
+ if sample.StructPtr == nil || sample.StructPtr.Bar != 456 {
+ t.Errorf("it should initialize struct pointer")
+ }
+ })
+
+ t.Run("non-initial value", func(t *testing.T) {
+ if sample.NonInitialString != "string" {
+ t.Errorf("it should not override non-initial value")
+ }
+ if !reflect.DeepEqual(sample.NonInitialSlice, []int{1, 2, 3}) {
+ t.Errorf("it should not override non-initial value")
+ }
+ if !reflect.DeepEqual(sample.NonInitialStruct, Struct{Embedded: Embedded{Int: 1}, Foo: 123, Bar: 456, WithDefault: "foo"}) {
+ t.Errorf("it should not override non-initial value but set defaults for fields")
+ }
+ if !reflect.DeepEqual(sample.NonInitialStructPtr, &Struct{Embedded: Embedded{Int: 1}, Foo: 123, Bar: 456, WithDefault: "foo"}) {
+ t.Errorf("it should not override non-initial value but set defaults for fields")
+ }
+ })
+
+ t.Run("no tag", func(t *testing.T) {
+ if sample.MapWithNoTag != nil {
+ t.Errorf("it should not initialize pointer type (map)")
+ }
+ if sample.SliceWithNoTag != nil {
+ t.Errorf("it should not initialize pointer type (slice)")
+ }
+ if sample.StructPtrWithNoTag != nil {
+ t.Errorf("it should not initialize pointer type (struct)")
+ }
+ if sample.StructWithNoTag.WithDefault != "foo" {
+ t.Errorf("it should automatically recurse into a struct even without a tag")
+ }
+ if !reflect.DeepEqual(sample.DeepSliceOfStructWithNoTag, [][][]Struct{{{{Embedded: Embedded{Int: 1}, Foo: 123, Bar: 456, WithDefault: "foo"}}}}) {
+ t.Errorf("it should automatically recurse into a slice of structs even without a tag")
+ }
+ })
+
+ t.Run("map of struct", func(t *testing.T) {
+ if sample.MapOfStruct == nil {
+ t.Errorf("it should not unset an initiated map")
+ }
+ if len(sample.MapOfStruct) != 1 {
+ t.Errorf("it should not override an initiated map")
+ }
+ if sample.MapOfStruct["Struct1"].Foo != 1 {
+ t.Errorf("it should not override Foo field in Struct1 item")
+ }
+ if sample.MapOfStruct["Struct1"].Bar != 456 {
+ t.Errorf("it should set default for Bar field in Struct1 item")
+ }
+ if sample.MapOfStruct["Struct1"].WithDefault != "foo" {
+ t.Errorf("it should set default for WithDefault field in Struct1 item")
+ }
+ })
+
+ t.Run("map of ptr struct", func(t *testing.T) {
+ if sample.MapOfPtrStruct == nil {
+ t.Errorf("it should not unset an initiated map")
+ }
+ if len(sample.MapOfPtrStruct) != 2 {
+ t.Errorf("it should not override an initiated map")
+ }
+ if sample.MapOfPtrStruct["Struct1"].Foo != 1 {
+ t.Errorf("it should not override Foo field in Struct1 item")
+ }
+ if sample.MapOfPtrStruct["Struct1"].Bar != 456 {
+ t.Errorf("it should set default for Bar field in Struct1 item")
+ }
+ if sample.MapOfPtrStruct["Struct1"].WithDefault != "foo" {
+ t.Errorf("it should set default for WithDefault field in Struct1 item")
+ }
+ if sample.MapOfPtrStruct["Struct2"].Foo != 0 {
+ t.Errorf("it should not override Foo field in Struct2 item")
+ }
+ if sample.MapOfPtrStruct["Struct2"].Bar != 456 {
+ t.Errorf("it should using setter to set default for Bar field in a Struct2 item")
+ }
+ if sample.MapOfPtrStruct["Struct2"].WithDefault != "foo" {
+ t.Errorf("it should set default for WithDefault field in Struct2 item")
+ }
+ })
+
+ t.Run("map of struct with tag", func(t *testing.T) {
+ if sample.MapOfStructWithTag == nil {
+ t.Errorf("it should set default")
+ }
+ if len(sample.MapOfStructWithTag) != 1 {
+ t.Errorf("it should set default with correct value")
+ }
+ if sample.MapOfStructWithTag["Struct3"].Foo != 123 {
+ t.Errorf("it should set default with correct value (Foo)")
+ }
+ if sample.MapOfStructWithTag["Struct1"].Bar != 0 {
+ t.Errorf("it should set default with correct value (Bar)")
+ }
+ if sample.MapOfStructWithTag["Struct1"].WithDefault != "" {
+ t.Errorf("it should set default with correct value (WithDefault)")
+ }
+ })
+
+ t.Run("opt-out", func(t *testing.T) {
+ if sample.NoDefault != nil {
+ t.Errorf("it should not be set")
+ }
+ if sample.NoDefaultStruct.WithDefault != "" {
+ t.Errorf("it should not initialize a struct with default values")
+ }
+ })
+}
+
+func TestCanUpdate(t *testing.T) {
+ type st struct{ Int int }
+
+ var myStructPtr *st
+
+ pairs := map[interface{}]bool{
+ 0: true,
+ 123: false,
+ float64(0): true,
+ float64(123): false,
+ "": true,
+ "string": false,
+ false: true,
+ true: false,
+ st{}: true,
+ st{Int: 123}: false,
+ myStructPtr: true,
+ &st{}: false,
+ }
+ for input, expect := range pairs {
+ output := CanUpdate(input)
+ if output != expect {
+ t.Errorf("CanUpdate(%v) returns %v, expected %v", input, output, expect)
+ }
+ }
+}
+
+type Child struct {
+ Name string `default:"Tom"`
+ Age int `default:"20"`
+}
+
+type Parent struct {
+ Child *Child
+}
+
+func TestPointerStructMember(t *testing.T) {
+ m := Parent{Child: &Child{Name: "Jim"}}
+ Set(&m)
+ if m.Child.Age != 20 {
+ t.Errorf("20 is expected")
+ }
+}
+
+type Main struct {
+ MainInt int `default:"-"`
+ *Other `default:"{}"`
+}
+
+type Other struct {
+ OtherInt int `default:"-"`
+}
+
+func (s *Main) SetDefaults() {
+ if CanUpdate(s.MainInt) {
+ s.MainInt = 1
+ }
+}
+
+func (s *Other) SetDefaults() {
+ if CanUpdate(s.OtherInt) {
+ s.OtherInt = 1
+ }
+}
+
+func TestDefaultsSetter(t *testing.T) {
+ main := &Main{}
+ Set(main)
+ if main.OtherInt != 1 {
+ t.Errorf("expected 1 for OtherInt, got %d", main.OtherInt)
+ }
+ if main.MainInt != 1 {
+ t.Errorf("expected 1 for MainInt, got %d", main.MainInt)
+ }
+}