diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:36:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:36:04 +0000 |
commit | b09c6d56832eb1718c07d74abf3bc6ae3fe4e030 (patch) | |
tree | d2caec2610d4ea887803ec9e9c3cd77136c448ba /dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0 | |
parent | Initial commit. (diff) | |
download | icingadb-b09c6d56832eb1718c07d74abf3bc6ae3fe4e030.tar.xz icingadb-b09c6d56832eb1718c07d74abf3bc6ae3fe4e030.zip |
Adding upstream version 1.1.0.upstream/1.1.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0')
11 files changed, 1117 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.circleci/config.yml b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.circleci/config.yml new file mode 100644 index 0000000..1ad2fc9 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.circleci/config.yml @@ -0,0 +1,26 @@ +version: 2.1 + +jobs: + build: + working_directory: ~/repo + docker: + - image: circleci/golang:1.15.8 + steps: + - checkout + - restore_cache: + keys: + - go-mod-v4-{{ checksum "go.sum" }} + - run: + name: Install Dependencies + command: go mod download + - save_cache: + key: go-mod-v4-{{ checksum "go.sum" }} + paths: + - "/go/pkg/mod" + - run: go get -u golang.org/x/lint/golint + - run: + name: Run tests + command: make ci-test + - run: + name: Upload coverage report + command: bash <(curl -s https://codecov.io/bash) diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.gitignore b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/LICENSE b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/LICENSE new file mode 100644 index 0000000..1483dd2 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2017-present Yuki Iwanaga + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/Makefile b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/Makefile new file mode 100644 index 0000000..bd42d46 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/Makefile @@ -0,0 +1,30 @@ +SHELL := /bin/bash -eu -o pipefail + +GO_TEST_FLAGS := -v + +PACKAGE_DIRS := $(shell go list ./... 2> /dev/null | grep -v /vendor/) +SRC_FILES := $(shell find . -name '*.go' -not -path './vendor/*') + + +# Tasks +#----------------------------------------------- +.PHONY: lint +lint: + @gofmt -e -d -s $(SRC_FILES) | awk '{ e = 1; print $0 } END { if (e) exit(1) }' + @echo $(SRC_FILES) | xargs -n1 golint -set_exit_status + @go vet $(PACKAGE_DIRS) + +.PHONY: test +test: lint + @go test $(GO_TEST_FLAGS) $(PACKAGE_DIRS) + +.PHONY: ci-test +ci-test: lint + @echo > coverage.txt + @for d in $(PACKAGE_DIRS); do \ + go test -coverprofile=profile.out -covermode=atomic -race -v $$d; \ + if [ -f profile.out ]; then \ + cat profile.out >> coverage.txt; \ + rm profile.out; \ + fi; \ + done diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/README.md b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/README.md new file mode 100644 index 0000000..de1ca3d --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/README.md @@ -0,0 +1,73 @@ +defaults +======== + +[![CircleCI](https://circleci.com/gh/creasty/defaults/tree/master.svg?style=svg)](https://circleci.com/gh/creasty/defaults/tree/master) +[![codecov](https://codecov.io/gh/creasty/defaults/branch/master/graph/badge.svg)](https://codecov.io/gh/creasty/defaults) +[![GitHub release](https://img.shields.io/github/release/creasty/defaults.svg)](https://github.com/creasty/defaults/releases) +[![License](https://img.shields.io/github/license/creasty/defaults.svg)](./LICENSE) + +Initialize structs with default values + +- Supports almost all kind of types + - Scalar types + - `int/8/16/32/64`, `uint/8/16/32/64`, `float32/64` + - `uintptr`, `bool`, `string` + - Complex types + - `map`, `slice`, `struct` + - Aliased types + - `time.Duration` + - e.g., `type Enum string` + - Pointer types + - e.g., `*SampleStruct`, `*int` +- Recursively initializes fields in a struct +- Dynamically sets default values by [`defaults.Setter`](./setter.go) interface +- Preserves non-initial values from being reset with a default value + + +Usage +----- + +```go +type Gender string + +type Sample struct { + Name string `default:"John Smith"` + Age int `default:"27"` + Gender Gender `default:"m"` + + Slice []string `default:"[]"` + SliceByJSON []int `default:"[1, 2, 3]"` // Supports JSON + + Map map[string]int `default:"{}"` + MapByJSON map[string]int `default:"{\"foo\": 123}"` + MapOfStruct map[string]OtherStruct + MapOfPtrStruct map[string]*OtherStruct + MapOfStructWithTag map[string]OtherStruct `default:"{\"Key1\": {\"Foo\":123}}"` + + Struct OtherStruct `default:"{}"` + StructPtr *OtherStruct `default:"{\"Foo\": 123}"` + + NoTag OtherStruct // Recurses into a nested struct by default + OptOut OtherStruct `default:"-"` // Opt-out +} + +type OtherStruct struct { + Hello string `default:"world"` // Tags in a nested struct also work + Foo int `default:"-"` + Random int `default:"-"` +} + +// SetDefaults implements defaults.Setter interface +func (s *OtherStruct) SetDefaults() { + if defaults.CanUpdate(s.Random) { // Check if it's a zero value (recommended) + s.Random = rand.Int() // Set a dynamic value + } +} +``` + +```go +obj := &Sample{} +if err := defaults.Set(obj); err != nil { + panic(err) +} +``` diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults.go b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults.go new file mode 100644 index 0000000..3bb2c22 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/defaults.go @@ -0,0 +1,221 @@ +package defaults + +import ( + "encoding/json" + "errors" + "reflect" + "strconv" + "time" +) + +var ( + errInvalidType = errors.New("not a struct pointer") +) + +const ( + fieldName = "default" +) + +// Set initializes members in a struct referenced by a pointer. +// Maps and slices are initialized by `make` and other primitive types are set with default values. +// `ptr` should be a struct pointer +func Set(ptr interface{}) error { + if reflect.TypeOf(ptr).Kind() != reflect.Ptr { + return errInvalidType + } + + v := reflect.ValueOf(ptr).Elem() + t := v.Type() + + if t.Kind() != reflect.Struct { + return errInvalidType + } + + for i := 0; i < t.NumField(); i++ { + if defaultVal := t.Field(i).Tag.Get(fieldName); defaultVal != "-" { + if err := setField(v.Field(i), defaultVal); err != nil { + return err + } + } + } + callSetter(ptr) + return nil +} + +// MustSet function is a wrapper of Set function +// It will call Set and panic if err not equals nil. +func MustSet(ptr interface{}) { + if err := Set(ptr); err != nil { + panic(err) + } +} + +func setField(field reflect.Value, defaultVal string) error { + if !field.CanSet() { + return nil + } + + if !shouldInitializeField(field, defaultVal) { + return nil + } + + isInitial := isInitialValue(field) + if isInitial { + switch field.Kind() { + case reflect.Bool: + if val, err := strconv.ParseBool(defaultVal); err == nil { + field.Set(reflect.ValueOf(val).Convert(field.Type())) + } + case reflect.Int: + if val, err := strconv.ParseInt(defaultVal, 0, strconv.IntSize); err == nil { + field.Set(reflect.ValueOf(int(val)).Convert(field.Type())) + } + case reflect.Int8: + if val, err := strconv.ParseInt(defaultVal, 0, 8); err == nil { + field.Set(reflect.ValueOf(int8(val)).Convert(field.Type())) + } + case reflect.Int16: + if val, err := strconv.ParseInt(defaultVal, 0, 16); err == nil { + field.Set(reflect.ValueOf(int16(val)).Convert(field.Type())) + } + case reflect.Int32: + if val, err := strconv.ParseInt(defaultVal, 0, 32); err == nil { + field.Set(reflect.ValueOf(int32(val)).Convert(field.Type())) + } + case reflect.Int64: + if val, err := time.ParseDuration(defaultVal); err == nil { + field.Set(reflect.ValueOf(val).Convert(field.Type())) + } else if val, err := strconv.ParseInt(defaultVal, 0, 64); err == nil { + field.Set(reflect.ValueOf(val).Convert(field.Type())) + } + case reflect.Uint: + if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil { + field.Set(reflect.ValueOf(uint(val)).Convert(field.Type())) + } + case reflect.Uint8: + if val, err := strconv.ParseUint(defaultVal, 0, 8); err == nil { + field.Set(reflect.ValueOf(uint8(val)).Convert(field.Type())) + } + case reflect.Uint16: + if val, err := strconv.ParseUint(defaultVal, 0, 16); err == nil { + field.Set(reflect.ValueOf(uint16(val)).Convert(field.Type())) + } + case reflect.Uint32: + if val, err := strconv.ParseUint(defaultVal, 0, 32); err == nil { + field.Set(reflect.ValueOf(uint32(val)).Convert(field.Type())) + } + case reflect.Uint64: + if val, err := strconv.ParseUint(defaultVal, 0, 64); err == nil { + field.Set(reflect.ValueOf(val).Convert(field.Type())) + } + case reflect.Uintptr: + if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil { + field.Set(reflect.ValueOf(uintptr(val)).Convert(field.Type())) + } + case reflect.Float32: + if val, err := strconv.ParseFloat(defaultVal, 32); err == nil { + field.Set(reflect.ValueOf(float32(val)).Convert(field.Type())) + } + case reflect.Float64: + if val, err := strconv.ParseFloat(defaultVal, 64); err == nil { + field.Set(reflect.ValueOf(val).Convert(field.Type())) + } + case reflect.String: + field.Set(reflect.ValueOf(defaultVal).Convert(field.Type())) + + case reflect.Slice: + ref := reflect.New(field.Type()) + ref.Elem().Set(reflect.MakeSlice(field.Type(), 0, 0)) + if defaultVal != "" && defaultVal != "[]" { + if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil { + return err + } + } + field.Set(ref.Elem().Convert(field.Type())) + case reflect.Map: + ref := reflect.New(field.Type()) + ref.Elem().Set(reflect.MakeMap(field.Type())) + if defaultVal != "" && defaultVal != "{}" { + if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil { + return err + } + } + field.Set(ref.Elem().Convert(field.Type())) + case reflect.Struct: + if defaultVal != "" && defaultVal != "{}" { + if err := json.Unmarshal([]byte(defaultVal), field.Addr().Interface()); err != nil { + return err + } + } + case reflect.Ptr: + field.Set(reflect.New(field.Type().Elem())) + } + } + + switch field.Kind() { + case reflect.Ptr: + if isInitial || field.Elem().Kind() == reflect.Struct { + setField(field.Elem(), defaultVal) + callSetter(field.Interface()) + } + case reflect.Struct: + if err := Set(field.Addr().Interface()); err != nil { + return err + } + case reflect.Slice: + for j := 0; j < field.Len(); j++ { + if err := setField(field.Index(j), defaultVal); err != nil { + return err + } + } + case reflect.Map: + for _, e := range field.MapKeys() { + var v = field.MapIndex(e) + + switch v.Kind() { + case reflect.Ptr: + switch v.Elem().Kind() { + case reflect.Struct, reflect.Slice, reflect.Map: + if err := setField(v.Elem(), ""); err != nil { + return err + } + } + case reflect.Struct, reflect.Slice, reflect.Map: + ref := reflect.New(v.Type()) + ref.Elem().Set(v) + if err := setField(ref.Elem(), ""); err != nil { + return err + } + field.SetMapIndex(e, ref.Elem().Convert(v.Type())) + } + } + } + + return nil +} + +func isInitialValue(field reflect.Value) bool { + return reflect.DeepEqual(reflect.Zero(field.Type()).Interface(), field.Interface()) +} + +func shouldInitializeField(field reflect.Value, tag string) bool { + switch field.Kind() { + case reflect.Struct: + return true + case reflect.Ptr: + if !field.IsNil() && field.Elem().Kind() == reflect.Struct { + return true + } + case reflect.Slice: + return field.Len() > 0 || tag != "" + case reflect.Map: + return field.Len() > 0 || tag != "" + } + + return tag != "" +} + +// CanUpdate returns true when the given value is an initial value of its type +func CanUpdate(v interface{}) bool { + return isInitialValue(reflect.ValueOf(v)) +} 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) + } +} diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.mod b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.mod new file mode 100644 index 0000000..2b71726 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.mod @@ -0,0 +1,3 @@ +module github.com/creasty/defaults + +go 1.14 diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.sum b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.sum new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/go.sum diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/internal/fixture/test.go b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/internal/fixture/test.go new file mode 100644 index 0000000..94c3d41 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/internal/fixture/test.go @@ -0,0 +1,7 @@ +package fixture + +// Sample is a struct that contains 1 exported field and 1 unexported field +type Sample struct { + ExportedFeild int + unexportedFeild int +} diff --git a/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/setter.go b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/setter.go new file mode 100644 index 0000000..1f64aa6 --- /dev/null +++ b/dependencies/pkg/mod/github.com/creasty/defaults@v1.6.0/setter.go @@ -0,0 +1,12 @@ +package defaults + +// Setter is an interface for setting default values +type Setter interface { + SetDefaults() +} + +func callSetter(v interface{}) { + if ds, ok := v.(Setter); ok { + ds.SetDefaults() + } +} |