diff options
Diffstat (limited to '')
-rw-r--r-- | dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults_test.go | 722 |
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) + } +} |