From 67af8c5feabe842e36363e653579160d4aa3d649 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Mon, 8 Jun 2020 22:00:02 -0500 Subject: [PATCH 01/16] add support for float32 ensure support for both float32 and float64 lint fixes add tests for float64 & add test for nil pointer --- faker.go | 61 +++++++++++--- faker_test.go | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+), 10 deletions(-) diff --git a/faker.go b/faker.go index 0e00bcf..8c928b2 100644 --- a/faker.go +++ b/faker.go @@ -115,7 +115,7 @@ const ( comma = "," colon = ":" ONEOF = "oneof" - // period = "." + //period = "." ) var defaultTag = map[string]string{ @@ -239,6 +239,7 @@ var ( ErrUnsupportedTagArguments = "Tag arguments are not compatible with field type." ErrDuplicateSeparator = "Duplicate separator for tag arguments." ErrNotEnoughTagArguments = "Not enough arguments for tag." + ErrUnsupportedNumberType = "Unsupported Number type." ) // Compiled regexp @@ -865,17 +866,57 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { if len(args) < 2 { return nil, fmt.Errorf(ErrNotEnoughTagArguments) } - var numberValues []int - for _, i := range args { - k := strings.TrimSpace(i) - j, err := strconv.Atoi(k) - if err != nil { - return nil, fmt.Errorf(ErrUnsupportedTagArguments) + switch t.Kind() { + case reflect.Float32: + { + bytes := 32 + var floatValues []float32 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseFloat(k, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, float32(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil + } + case reflect.Float64: + { + bytes := 64 + var floatValues []float64 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseFloat(k, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, j) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + { + var numberValues []int + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.Atoi(k) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + numberValues = append(numberValues, j) + } + toRet := numberValues[rand.Intn(len(numberValues))] + return toRet, nil + } + default: + { + return nil, fmt.Errorf(ErrUnsupportedNumberType) } - numberValues = append(numberValues, j) } - toRet := numberValues[rand.Intn(len(numberValues))] - return toRet, nil } // handling boundary tags diff --git a/faker_test.go b/faker_test.go index bfcc8f2..1a3b183 100644 --- a/faker_test.go +++ b/faker_test.go @@ -4,6 +4,7 @@ import ( "fmt" "math/rand" "reflect" + "strings" "testing" "time" "unicode/utf8" @@ -1480,6 +1481,230 @@ func TestOneOfTag(t *testing.T) { } }) + type CustomFloat1 struct { + Price float32 `faker:"oneof: 3.14, 15.92"` + } + + t.Run("correctly picks one of the float32s", func(t *testing.T) { + a := CustomFloat1{} + err := FakeData(&a) + if err != nil { + t.Error("expected no error but got ", err) + } + one := a.Price == 3.14 + two := a.Price == 15.92 + + if !one && !two { + t.Errorf("expected either %v or %v but got %v", 3.14, 15.92, a.Price) + } + }) + + type CustomWrongFloat1 struct { + Price float32 `faker:"oneof:"` + } + + t.Run("errors when tag is not used correctly no args float32", func(t *testing.T) { + a := CustomWrongFloat1{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error, but got no error") + } + actual := err.Error() + expected := ErrNotEnoughTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat2 struct { + Price float32 `faker:"oneof: 15.5: 18.9, 35.4747"` + } + + t.Run("errors when tag is not used correctly float32 invalid argument separator", func(t *testing.T) { + a := CustomWrongFloat2{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error, but got no error") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat3 struct { + Price float32 `faker:"oneof: 1648.4564673, 894572.997376, oops"` + } + + t.Run("errors when tag is not used correctly float32 invalid argument type", func(t *testing.T) { + a := CustomWrongFloat3{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat4 struct { + Price float32 `faker:"oneof: 1848205.48483727"` + } + + t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { + a := CustomWrongFloat4{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrNotEnoughTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat5 struct { + Price float32 `faker:"oneof: 15,,16,17"` + } + + t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { + a := CustomWrongFloat5{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrDuplicateSeparator + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomFloat6 struct { + Price float64 `faker:"oneof: 34566872.57446732, 969525372.57563314"` + } + + t.Run("correctly picks one of the float64s", func(t *testing.T) { + a := CustomFloat6{} + err := FakeData(&a) + if err != nil { + t.Error("expected no error but got ", err) + } + const first = 34566872.57446732 + const second = 969525372.57563314 + one := a.Price == first + two := a.Price == second + + if !one && !two { + t.Errorf("expected either %v or %v but got %v", first, second, a.Price) + } + }) + + type CustomWrongFloat7 struct { + Price float64 `faker:"oneof:"` + } + + t.Run("errors when tag is not used correctly no args float64", func(t *testing.T) { + a := CustomWrongFloat7{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error, but got no error") + } + actual := err.Error() + expected := ErrNotEnoughTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat8 struct { + Price float64 `faker:"oneof: 157285.842725: 184028.474729, 3574626.4747"` + } + + t.Run("errors when tag is not used correctly float64 invalid argument separator", func(t *testing.T) { + a := CustomWrongFloat8{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error, but got no error") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat9 struct { + Price float64 `faker:"oneof: 1648.4564673, 894572.997376, oops"` + } + + t.Run("errors when tag is not used correctly float64 invalid argument type", func(t *testing.T) { + a := CustomWrongFloat9{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat10 struct { + Price float64 `faker:"oneof: 1848205.48483727"` + } + + t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { + a := CustomWrongFloat10{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrNotEnoughTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + + type CustomWrongFloat11 struct { + Price float64 `faker:"oneof: 15,,16,17"` + } + + t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { + a := CustomWrongFloat11{} + err := FakeData(&a) + if err == nil { + t.Fatal("expected error, but got no error") + } + actual := err.Error() + expected := ErrDuplicateSeparator + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + +} + +func TestFakeData3(t *testing.T) { + t.Run("test nil pointer", func(t *testing.T) { + var a *int + err := FakeData(a) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected1 := "Use sample:=new" + expected2 := "faker.FakeData(sample) instead" + if !strings.Contains(actual, expected1) && !strings.Contains(actual, expected2) { + t.Errorf("expected %v to contain %v & %v", actual, expected1, expected2) + } + }) } // getStringLen for language independent string length From b241d9d874244a5417803b4a7b2e134173067fae Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Mon, 8 Jun 2020 23:25:56 -0500 Subject: [PATCH 02/16] update documentation --- README.md | 2 +- example_with_tags_test.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea35660..efb6c4c 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Unfortunately this library has some limitation * It does not support the `map[interface{}]interface{}`, `map[any_type]interface{}` & `map[interface{}]any_type` data types. Once again, we cannot generate values for an unknown data type. * Custom types are not fully supported. However some custom types are already supported: we are still investigating how to do this the correct way. For now, if you use `faker`, it's safer not to use any custom types in order to avoid panics. * Some extra custom types can be supported IF AND ONLY IF extended with [AddProvider()](https://github.com/bxcodec/faker/blob/9169c33ae9926e5b8f8732909790ee20b10b736a/faker.go#L320) please see [example](example_custom_faker_test.go#L46) -* The `oneof` tag currently only supports `string` & `int`. Further support is coming soon. See [example](example_with_tags_test.go#L53) for usage. +* The `oneof` tag currently only supports `string`, the `int` types, and both `float32` & `float64`. Further support is coming soon. See [example](example_with_tags_test.go#L53) for usage. ## Contribution diff --git a/example_with_tags_test.go b/example_with_tags_test.go index e392390..4ce203b 100644 --- a/example_with_tags_test.go +++ b/example_with_tags_test.go @@ -52,6 +52,8 @@ type SomeStructWithTags struct { Skip string `faker:"-"` PaymentMethod string `faker:"oneof: cc, paypal, check, money order"` // oneof will randomly pick one of the comma-separated values supplied in the tag AccountID int `faker:"oneof: 15, 27, 61"` // use commas to separate the values for now. Future support for other separator characters may be added + Price32 float32 `faker:"oneof: 4.95, 9.99, 31997.97"` + Price64 float64 `faker:"oneof: 47463.9463525, 993747.95662529, 11131997.978767990"` } func Example_withTags() { @@ -107,7 +109,9 @@ func Example_withTags() { UUIDHypenated: 8f8e4463-9560-4a38-9b0c-ef24481e4e27, UUID: 90ea6479fd0e4940af741f0a87596b73, PaymentMethod: paypal, - AccountID: 61 + AccountID: 61, + Price32: 4.95, + Price64: 993747.95662529 Skip: } */ From 8cb9b705f1d49ebbec20f91ed82db59da451b33b Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Mon, 8 Jun 2020 23:59:55 -0500 Subject: [PATCH 03/16] make sure all the int types are correctly covered and wouldn't cause a panic if used for oneof tag. --- faker.go | 43 ++++++++++++++++++++++++++++++++++++++++++- faker_test.go | 21 +++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/faker.go b/faker.go index 8c928b2..09cee2d 100644 --- a/faker.go +++ b/faker.go @@ -910,7 +910,48 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { numberValues = append(numberValues, j) } toRet := numberValues[rand.Intn(len(numberValues))] - return toRet, nil + switch t.Kind() { + case reflect.Int64: + { + return int64(toRet), nil + } + case reflect.Int32: + { + return int32(toRet), nil + } + case reflect.Int16: + { + return int16(toRet), nil + } + case reflect.Int8: + { + return int8(toRet), nil + } + case reflect.Uint64: + { + return uint64(toRet), nil + } + case reflect.Uint32: + { + return uint32(toRet), nil + } + case reflect.Uint16: + { + return uint16(toRet), nil + } + case reflect.Uint8: + { + return uint8(toRet), nil + } + case reflect.Uint: + { + return uint(toRet), nil + } + default: + { + return toRet, nil + } + } } default: { diff --git a/faker_test.go b/faker_test.go index 1a3b183..4ae7e1a 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1689,6 +1689,27 @@ func TestOneOfTag(t *testing.T) { } }) + type CustomTypeLotsOfInts struct { + Age1 int64 `faker:"oneof: 1, 2"` + Age2 int32 `faker:"oneof: 3, 5"` + Age3 int16 `faker:"oneof: 8, 13"` + Age4 int8 `faker:"oneof: 21, 34"` + Age5 int `faker:"oneof: 55, 89"` + Age6 uint64 `faker:"oneof: 2, 4"` + Age7 uint32 `faker:"oneof: 6, 8"` + Age8 uint16 `faker:"oneof: 10, 12"` + Age9 uint8 `faker:"oneof: 3, 5"` + Age0 uint `faker:"oneof: 7, 9"` + } + + t.Run("Should support all the int types", func(t *testing.T) { + a := CustomTypeLotsOfInts{} + err := FakeData(&a) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + }) + } func TestFakeData3(t *testing.T) { From c495e5558483ebe4b68949cbd6bbc896bb31863b Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Tue, 9 Jun 2020 00:07:34 -0500 Subject: [PATCH 04/16] update examples --- example_with_tags_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/example_with_tags_test.go b/example_with_tags_test.go index 4ce203b..09b8a8e 100644 --- a/example_with_tags_test.go +++ b/example_with_tags_test.go @@ -54,6 +54,15 @@ type SomeStructWithTags struct { AccountID int `faker:"oneof: 15, 27, 61"` // use commas to separate the values for now. Future support for other separator characters may be added Price32 float32 `faker:"oneof: 4.95, 9.99, 31997.97"` Price64 float64 `faker:"oneof: 47463.9463525, 993747.95662529, 11131997.978767990"` + NumS64 int64 `faker:"oneof: 1, 2"` + NumS32 int32 `faker:"oneof: 3, 4"` + NumS16 int16 `faker:"oneof: 5, 6"` + NumS8 int8 `faker:"oneof: 7, 8"` + NumU64 uint64 `faker:"oneof: 9, 10"` + NumU32 uint32 `faker:"oneof: 11, 12"` + NumU16 uint16 `faker:"oneof: 13, 14"` + NumU8 uint8 `faker:"oneof: 15, 16"` + NumU uint `faker:"oneof: 17, 18"` } func Example_withTags() { @@ -112,6 +121,15 @@ func Example_withTags() { AccountID: 61, Price32: 4.95, Price64: 993747.95662529 + NumS64: 1 + NumS32: 3 + NumS16: 5 + NumS8: 7 + NumU64: 9 + NumU32: 11 + NumU16: 13 + NumU8: 15 + NumU: 17 Skip: } */ From 4df045cddf25a284bcbdc27b543f2f82295a43f8 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Tue, 9 Jun 2020 00:21:33 -0500 Subject: [PATCH 05/16] add logic and test to check for trying to assign a signed int to a variable of unsigned int type. --- faker.go | 10 ++++++++++ faker_test.go | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/faker.go b/faker.go index 09cee2d..e5403de 100644 --- a/faker.go +++ b/faker.go @@ -116,6 +116,7 @@ const ( colon = ":" ONEOF = "oneof" //period = "." + hyphen = "-" ) var defaultTag = map[string]string{ @@ -240,6 +241,7 @@ var ( ErrDuplicateSeparator = "Duplicate separator for tag arguments." ErrNotEnoughTagArguments = "Not enough arguments for tag." ErrUnsupportedNumberType = "Unsupported Number type." + ErrMixedSignedWithUnsigned = "Passed signed int to unsigned type." ) // Compiled regexp @@ -903,6 +905,14 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { var numberValues []int for _, i := range args { k := strings.TrimSpace(i) + switch t.Kind() { + case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: + { + if strings.Contains(k, hyphen) { + return nil, fmt.Errorf(ErrMixedSignedWithUnsigned) + } + } + } j, err := strconv.Atoi(k) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) diff --git a/faker_test.go b/faker_test.go index 4ae7e1a..5406061 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1710,6 +1710,23 @@ func TestOneOfTag(t *testing.T) { } }) + type CustomTypeNegativeUnsigned struct { + Age uint `faker:"oneof: -45, -42"` + } + + t.Run("passing a negative int to an unsigned int should cause error", func(t *testing.T) { + a := CustomTypeNegativeUnsigned{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrMixedSignedWithUnsigned + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + } func TestFakeData3(t *testing.T) { From 9055eca80b55ed30221123240d86a0619841aafd Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Tue, 9 Jun 2020 00:23:42 -0500 Subject: [PATCH 06/16] update examples to include some negative numbers. --- example_with_tags_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/example_with_tags_test.go b/example_with_tags_test.go index 09b8a8e..3fa4b29 100644 --- a/example_with_tags_test.go +++ b/example_with_tags_test.go @@ -55,9 +55,9 @@ type SomeStructWithTags struct { Price32 float32 `faker:"oneof: 4.95, 9.99, 31997.97"` Price64 float64 `faker:"oneof: 47463.9463525, 993747.95662529, 11131997.978767990"` NumS64 int64 `faker:"oneof: 1, 2"` - NumS32 int32 `faker:"oneof: 3, 4"` - NumS16 int16 `faker:"oneof: 5, 6"` - NumS8 int8 `faker:"oneof: 7, 8"` + NumS32 int32 `faker:"oneof: -3, 4"` + NumS16 int16 `faker:"oneof: -5, 6"` + NumS8 int8 `faker:"oneof: 7, -8"` NumU64 uint64 `faker:"oneof: 9, 10"` NumU32 uint32 `faker:"oneof: 11, 12"` NumU16 uint16 `faker:"oneof: 13, 14"` @@ -122,9 +122,9 @@ func Example_withTags() { Price32: 4.95, Price64: 993747.95662529 NumS64: 1 - NumS32: 3 + NumS32: -3 NumS16: 5 - NumS8: 7 + NumS8: -8 NumU64: 9 NumU32: 11 NumU16: 13 From 362e943ba7fe229d5950ddd9fad381dc9bd108af Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 14:35:03 -0500 Subject: [PATCH 07/16] use PareUint for unsigned int types --- faker.go | 37 +++++++++++++++++++++---------------- faker_test.go | 2 +- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/faker.go b/faker.go index e5403de..dd27199 100644 --- a/faker.go +++ b/faker.go @@ -116,7 +116,7 @@ const ( colon = ":" ONEOF = "oneof" //period = "." - hyphen = "-" + //hyphen = "-" ) var defaultTag = map[string]string{ @@ -241,7 +241,6 @@ var ( ErrDuplicateSeparator = "Duplicate separator for tag arguments." ErrNotEnoughTagArguments = "Not enough arguments for tag." ErrUnsupportedNumberType = "Unsupported Number type." - ErrMixedSignedWithUnsigned = "Passed signed int to unsigned type." ) // Compiled regexp @@ -899,20 +898,11 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { toRet := floatValues[rand.Intn(len(floatValues))] return toRet, nil } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: { var numberValues []int for _, i := range args { k := strings.TrimSpace(i) - switch t.Kind() { - case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: - { - if strings.Contains(k, hyphen) { - return nil, fmt.Errorf(ErrMixedSignedWithUnsigned) - } - } - } j, err := strconv.Atoi(k) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) @@ -937,6 +927,25 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { { return int8(toRet), nil } + default: + { + return toRet, nil + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + { + var numberValues []uint + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 10, 0) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + numberValues = append(numberValues, uint(j)) + } + toRet := numberValues[rand.Intn(len(numberValues))] + switch t.Kind() { case reflect.Uint64: { return uint64(toRet), nil @@ -953,10 +962,6 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { { return uint8(toRet), nil } - case reflect.Uint: - { - return uint(toRet), nil - } default: { return toRet, nil diff --git a/faker_test.go b/faker_test.go index 5406061..456e0be 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1720,7 +1720,7 @@ func TestOneOfTag(t *testing.T) { if err == nil { t.Errorf("expected error but got nil") } - expected := ErrMixedSignedWithUnsigned + expected := ErrUnsupportedTagArguments actual := err.Error() if expected != actual { t.Errorf("expected %v but got %v", expected, actual) From 54363b1211b71c60526a7ec355476d8048e61b57 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 16:59:32 -0500 Subject: [PATCH 08/16] extract functions for each numeric type, use them in faker for an easier reading experience --- faker.go | 166 ++++++++++++++++----------------- tag_argument_extractor.go | 188 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+), 85 deletions(-) create mode 100644 tag_argument_extractor.go diff --git a/faker.go b/faker.go index dd27199..711ebb9 100644 --- a/faker.go +++ b/faker.go @@ -868,105 +868,101 @@ func extractNumberFromTag(tag string, t reflect.Type) (interface{}, error) { return nil, fmt.Errorf(ErrNotEnoughTagArguments) } switch t.Kind() { + case reflect.Float64: + { + toRet, err := extractFloat64FromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(float64), nil + } case reflect.Float32: { - bytes := 32 - var floatValues []float32 - for _, i := range args { - k := strings.TrimSpace(i) - j, err := strconv.ParseFloat(k, bytes) - if err != nil { - return nil, fmt.Errorf(ErrUnsupportedTagArguments) - } - floatValues = append(floatValues, float32(j)) + toRet, err := extractFloat32FromTagArgs(args) + if err != nil { + return nil, err } - toRet := floatValues[rand.Intn(len(floatValues))] - return toRet, nil + return toRet.(float32), nil } - case reflect.Float64: + case reflect.Int64: { - bytes := 64 - var floatValues []float64 - for _, i := range args { - k := strings.TrimSpace(i) - j, err := strconv.ParseFloat(k, bytes) - if err != nil { - return nil, fmt.Errorf(ErrUnsupportedTagArguments) - } - floatValues = append(floatValues, j) + toRet, err := extractInt64FromTagArgs(args) + if err != nil { + return nil, err } - toRet := floatValues[rand.Intn(len(floatValues))] - return toRet, nil + return toRet.(int64), nil } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + case reflect.Int32: { - var numberValues []int - for _, i := range args { - k := strings.TrimSpace(i) - j, err := strconv.Atoi(k) - if err != nil { - return nil, fmt.Errorf(ErrUnsupportedTagArguments) - } - numberValues = append(numberValues, j) + toRet, err := extractInt32FromTagArgs(args) + if err != nil { + return nil, err } - toRet := numberValues[rand.Intn(len(numberValues))] - switch t.Kind() { - case reflect.Int64: - { - return int64(toRet), nil - } - case reflect.Int32: - { - return int32(toRet), nil - } - case reflect.Int16: - { - return int16(toRet), nil - } - case reflect.Int8: - { - return int8(toRet), nil - } - default: - { - return toRet, nil - } + return toRet.(int32), nil + } + case reflect.Int16: + { + toRet, err := extractInt16FromTagArgs(args) + if err != nil { + return nil, err } + return toRet.(int16), nil } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case reflect.Int8: { - var numberValues []uint - for _, i := range args { - k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 10, 0) - if err != nil { - return nil, fmt.Errorf(ErrUnsupportedTagArguments) - } - numberValues = append(numberValues, uint(j)) + toRet, err := extractInt8FromTagArgs(args) + if err != nil { + return nil, err } - toRet := numberValues[rand.Intn(len(numberValues))] - switch t.Kind() { - case reflect.Uint64: - { - return uint64(toRet), nil - } - case reflect.Uint32: - { - return uint32(toRet), nil - } - case reflect.Uint16: - { - return uint16(toRet), nil - } - case reflect.Uint8: - { - return uint8(toRet), nil - } - default: - { - return toRet, nil - } + return toRet.(int8), nil + } + case reflect.Int: + { + toRet, err := extractIntFromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(int), nil + } + case reflect.Uint64: + { + toRet, err := extractUint64FromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(uint64), nil + } + case reflect.Uint32: + { + toRet, err := extractUint32FromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(uint32), nil + } + case reflect.Uint16: + { + toRet, err := extractUint16FromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(uint16), nil + } + case reflect.Uint8: + { + toRet, err := extractUint8FromTagArgs(args) + if err != nil { + return nil, err + } + return toRet.(uint8), nil + } + case reflect.Uint: + { + toRet, err := extractUintFromTagArgs(args) + if err != nil { + return nil, err } + return toRet.(uint), nil } default: { diff --git a/tag_argument_extractor.go b/tag_argument_extractor.go new file mode 100644 index 0000000..e8d96be --- /dev/null +++ b/tag_argument_extractor.go @@ -0,0 +1,188 @@ +package faker + +import ( + "fmt" + "math/rand" + "strconv" + "strings" +) + +func extractFloat64FromTagArgs(args []string) (interface{}, error) { + bytes := 64 + var floatValues []float64 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseFloat(k, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, j) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractFloat32FromTagArgs(args []string) (interface{}, error) { + bytes := 32 + var floatValues []float32 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseFloat(k, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, float32(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractInt64FromTagArgs(args []string) (interface{}, error) { + bytes := 64 + var floatValues []int64 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseInt(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, j) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractInt32FromTagArgs(args []string) (interface{}, error) { + bytes := 32 + var floatValues []int32 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseInt(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, int32(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractInt16FromTagArgs(args []string) (interface{}, error) { + bytes := 16 + var floatValues []int16 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseInt(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, int16(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractInt8FromTagArgs(args []string) (interface{}, error) { + bytes := 8 + var floatValues []int8 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseInt(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, int8(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractIntFromTagArgs(args []string) (interface{}, error) { + bytes := 0 + var floatValues []int + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseInt(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, int(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractUint64FromTagArgs(args []string) (interface{}, error) { + bytes := 64 + var floatValues []uint64 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, j) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractUint32FromTagArgs(args []string) (interface{}, error) { + bytes := 32 + var floatValues []uint32 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, uint32(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractUint16FromTagArgs(args []string) (interface{}, error) { + bytes := 16 + var floatValues []uint16 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, uint16(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractUint8FromTagArgs(args []string) (interface{}, error) { + bytes := 8 + var floatValues []uint8 + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, uint8(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} + +func extractUintFromTagArgs(args []string) (interface{}, error) { + bytes := 0 + var floatValues []uint + for _, i := range args { + k := strings.TrimSpace(i) + j, err := strconv.ParseUint(k, 0, bytes) + if err != nil { + return nil, fmt.Errorf(ErrUnsupportedTagArguments) + } + floatValues = append(floatValues, uint(j)) + } + toRet := floatValues[rand.Intn(len(floatValues))] + return toRet, nil +} From d1c83144792a626e6e4e661670cde4db99ea1588 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 17:40:11 -0500 Subject: [PATCH 09/16] begin adding tests for new convenience functions --- tag_argument_extractor_test.go | 407 +++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 tag_argument_extractor_test.go diff --git a/tag_argument_extractor_test.go b/tag_argument_extractor_test.go new file mode 100644 index 0000000..b47fcc9 --- /dev/null +++ b/tag_argument_extractor_test.go @@ -0,0 +1,407 @@ +package faker + +import ( + "fmt" + "testing" +) + +func TestExtractFloat64(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 = 658897324.4626827 + const f2 = 77592747.726643 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractFloat64FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res64, ok := res.(float64) + if !ok { + t.Errorf("expected a float64, but got something else") + } + one := res64 == f1 + two := res64 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res64, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 658897324.4626827 + const f2 = 77592747.726643 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractFloat64FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractFloat32(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 = 6500347324.4627466827 + const f2 = 7757290047.772026643 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractFloat32FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res32, ok := res.(float32) + if !ok { + t.Errorf("expected a float32, but got something else") + } + one := res32 == f1 + two := res32 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res32, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 6500034324.4646626827 + const f2 = 775743047.7757926643 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractFloat64FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractInt64(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 = 6500347324 + const f2 = 7757290047 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractInt64FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res64, ok := res.(int64) + if !ok { + t.Errorf("expected a float64, but got something else") + } + one := res64 == f1 + two := res64 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res64, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 6500347324 + const f2 = 7757290047 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractInt64FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractInt32(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 = -160347324 + const f2 = -75290047 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractInt32FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res32, ok := res.(int32) + if !ok { + t.Errorf("expected a float32, but got something else") + } + one := res32 == f1 + two := res32 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res32, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = -6500347324 + const f2 = 7757290047 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractInt32FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractInt16(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 int16 = -19474 + const f2 int16 = 5047 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractInt16FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res16, ok := res.(int16) + if !ok { + t.Errorf("expected a float16, but got something else") + } + one := res16 == f1 + two := res16 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res16, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = -65003 + const f2 = 77572 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractInt16FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + t.Run("int overflow", func(t *testing.T) { + const f1 = -650875703 // these are too big for int16 + const f2 = 775784842 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractInt16FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractInt8(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + const f1 int8 = -81 + const f2 int8 = 104 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractInt8FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res8, ok := res.(int8) + if !ok { + t.Errorf("expected a float8, but got something else") + } + one := res8 == f1 + two := res8 == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res8, + ) + } + }) + + t.Run("error path", func(t *testing.T) { + const f1 = -103 + const f2 = 72 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractInt8FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + + t.Run("int overflow", func(t *testing.T) { + const f1 = -650875703 // these are too big for int8 + const f2 = 775784842 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractInt8FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + +} + +func TestExtractInt(t *testing.T) { + +} + +func TestExtractUint64(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + + }) + + t.Run("error path", func(t *testing.T) { + + }) + +} + +func TestExtractUint32(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + + }) + + t.Run("error path", func(t *testing.T) { + + }) + +} + +func TestExtractUint16(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + + }) + + t.Run("error path", func(t *testing.T) { + + }) + +} + +func TestExtractUint8(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + + }) + + t.Run("error path", func(t *testing.T) { + + }) + +} + +func TestExtractUint(t *testing.T) { + + t.Run("happy path", func(t *testing.T) { + + }) + + t.Run("error path", func(t *testing.T) { + + }) + +} From 5417adb16e5aa4cd39144217f87ef110bbedc618 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 17:46:09 -0500 Subject: [PATCH 10/16] add more tests for new convenience funcs --- tag_argument_extractor_test.go | 44 +++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tag_argument_extractor_test.go b/tag_argument_extractor_test.go index b47fcc9..3a7dc7f 100644 --- a/tag_argument_extractor_test.go +++ b/tag_argument_extractor_test.go @@ -307,7 +307,7 @@ func TestExtractInt8(t *testing.T) { } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { const f1 = -103 const f2 = 72 const f3 = "oops" @@ -344,6 +344,48 @@ func TestExtractInt8(t *testing.T) { func TestExtractInt(t *testing.T) { + t.Run("happy path", func(t *testing.T) { + const f1 int = -17575 + const f2 int = 10467463 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractIntFromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(int) + if !ok { + t.Errorf("expected a float, but got something else") + } + one := res == f1 + two := res == f2 + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } + }) + + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = -1037474 + const f2 = 72747346 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractIntFromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + } func TestExtractUint64(t *testing.T) { From 9e24a2ab7f329b0acc78e927a8672e4f5e6e0398 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 18:55:10 -0500 Subject: [PATCH 11/16] finish off tests for new helper funcs --- tag_argument_extractor_test.go | 267 +++++++++++++++++++++++++++++++-- 1 file changed, 251 insertions(+), 16 deletions(-) diff --git a/tag_argument_extractor_test.go b/tag_argument_extractor_test.go index 3a7dc7f..200a454 100644 --- a/tag_argument_extractor_test.go +++ b/tag_argument_extractor_test.go @@ -212,8 +212,8 @@ func TestExtractInt32(t *testing.T) { func TestExtractInt16(t *testing.T) { t.Run("happy path", func(t *testing.T) { - const f1 int16 = -19474 - const f2 int16 = 5047 + const f1 = -19474 + const f2 = 5047 args := []string{ fmt.Sprintf("%v", f1), fmt.Sprintf("%v", f2), @@ -281,8 +281,8 @@ func TestExtractInt16(t *testing.T) { func TestExtractInt8(t *testing.T) { t.Run("happy path", func(t *testing.T) { - const f1 int8 = -81 - const f2 int8 = 104 + const f1 = -81 + const f2 = 104 args := []string{ fmt.Sprintf("%v", f1), fmt.Sprintf("%v", f2), @@ -345,8 +345,8 @@ func TestExtractInt8(t *testing.T) { func TestExtractInt(t *testing.T) { t.Run("happy path", func(t *testing.T) { - const f1 int = -17575 - const f2 int = 10467463 + const f1 = -17575 + const f2 = 10467463 args := []string{ fmt.Sprintf("%v", f1), fmt.Sprintf("%v", f2), @@ -391,11 +391,58 @@ func TestExtractInt(t *testing.T) { func TestExtractUint64(t *testing.T) { t.Run("happy path", func(t *testing.T) { - + const f1 = 1658584 + const f2 = 10467463 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractUint64FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(uint64) + if !ok { + t.Errorf("expected a uint64, but got something else") + } + one := res == uint64(f1) + two := res == uint64(f2) + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 175757 + const f2 = 727473474 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractUint64FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + t.Run("negatives", func(t *testing.T) { + const f1 = -1757665 + const f2 = 727473474 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractUint64FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } }) } @@ -403,11 +450,58 @@ func TestExtractUint64(t *testing.T) { func TestExtractUint32(t *testing.T) { t.Run("happy path", func(t *testing.T) { - + const f1 = 1658584 + const f2 = 10467463 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractUint32FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(uint32) + if !ok { + t.Errorf("expected a uint32, but got something else") + } + one := res == uint32(f1) + two := res == uint32(f2) + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 175757 + const f2 = 727473474 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractUint32FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + t.Run("negatives", func(t *testing.T) { + const f1 = -175757 + const f2 = 727473474 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractUint32FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } }) } @@ -415,11 +509,58 @@ func TestExtractUint32(t *testing.T) { func TestExtractUint16(t *testing.T) { t.Run("happy path", func(t *testing.T) { - + const f1 = 16580 + const f2 = 10467 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractUint16FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(uint16) + if !ok { + t.Errorf("expected a uint16, but got something else") + } + one := res == uint16(f1) + two := res == uint16(f2) + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 175757 + const f2 = 727473474 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractUint16FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + t.Run("negatives", func(t *testing.T) { + const f1 = -1757 + const f2 = 2747 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractUint16FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } }) } @@ -427,11 +568,58 @@ func TestExtractUint16(t *testing.T) { func TestExtractUint8(t *testing.T) { t.Run("happy path", func(t *testing.T) { - + const f1 = 254 + const f2 = 107 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractUint8FromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(uint8) + if !ok { + t.Errorf("expected a uint8, but got something else") + } + one := res == uint8(f1) + two := res == uint8(f2) + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 175 + const f2 = 227 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractUint8FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + t.Run("negatives", func(t *testing.T) { + const f1 = -175 + const f2 = 204 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractUint8FromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } }) } @@ -439,11 +627,58 @@ func TestExtractUint8(t *testing.T) { func TestExtractUint(t *testing.T) { t.Run("happy path", func(t *testing.T) { - + const f1 = 25467565 + const f2 = 1072562460 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + res, err := extractUintFromTagArgs(args) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + res, ok := res.(uint) + if !ok { + t.Errorf("expected a uint, but got something else") + } + one := res == uint(f1) + two := res == uint(f2) + if !one && !two { + t.Errorf( + "expected %v or %v but got %v", + f1, + f2, + res, + ) + } }) - t.Run("error path", func(t *testing.T) { + t.Run("ErrUnsupportedTagArguments", func(t *testing.T) { + const f1 = 175774290 + const f2 = 2270064663 + const f3 = "oops" + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + fmt.Sprintf("%v", f3), + } + _, err := extractUintFromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } + }) + t.Run("negatives", func(t *testing.T) { + const f1 = -1756746346 + const f2 = 204466272 + args := []string{ + fmt.Sprintf("%v", f1), + fmt.Sprintf("%v", f2), + } + _, err := extractUintFromTagArgs(args) + if err == nil { + t.Errorf("expected error but got nil") + } }) } From d7528eb90e07141a40a56d9fb711f8d9abca0c4a Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 19:05:33 -0500 Subject: [PATCH 12/16] add extra test for other wrong use of tag --- faker_test.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/faker_test.go b/faker_test.go index 456e0be..c55842b 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1323,6 +1323,23 @@ func TestOneOfTag(t *testing.T) { } }) + type CustomOneofWrongString1 struct { + PaymentType string `faker:"oneof"` + } + + t.Run("errors when tag is not used correctly string no args or even colon separator", func(t *testing.T) { + a := CustomOneofWrongString1{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error, but got no error") + } + actual := err.Error() + expected := ErrUnsupportedTagArguments + if actual != expected { + t.Errorf("expected %v, but got %v", expected, actual) + } + }) + type CustomOneofWrongString2 struct { PaymentType string `faker:"oneof: cc: check, bank"` } @@ -1745,6 +1762,10 @@ func TestFakeData3(t *testing.T) { }) } +func TestGetValueWithTag(t *testing.T) { + +} + // getStringLen for language independent string length func utfLen(value string) int { var r int From c8387f52ac9931faed9d509b9f8dcc5884679147 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 19:36:03 -0500 Subject: [PATCH 13/16] re-organize tests & be mindful of cyclomatic complexity of the test functions --- faker_test.go | 468 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 306 insertions(+), 162 deletions(-) diff --git a/faker_test.go b/faker_test.go index c55842b..85edf5f 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1255,7 +1255,7 @@ func TestUniqueFailure(t *testing.T) { } } -func TestOneOfTag(t *testing.T) { +func TestOneOfTag__GoodInputs(t *testing.T) { type CustomOneString struct { PaymentType string `faker:"oneof: credit card, paypal"` @@ -1306,12 +1306,97 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofWrongString struct { - PaymentType string `faker:"oneof:"` + type CustomOneofInt1 struct { + Age int `faker:"oneof: 16, 18, 21"` } - t.Run("errors when tag is not used correctly string no args", func(t *testing.T) { - a := CustomOneofWrongString{} + t.Run("should pick one of the number args", func(t *testing.T) { + a := CustomOneofInt1{} + err := FakeData(&a) + if err != nil { + t.Errorf("expected no error, but got %v", err) + } + one := a.Age == 16 + two := a.Age == 18 + three := a.Age == 21 + actual := a.Age + if !one && !two && !three { + t.Errorf( + "expected either %v, %v, or %v, but got %v", + 16, 18, 21, actual, + ) + } + }) + + type CustomFloat1 struct { + Price float32 `faker:"oneof: 3.14, 15.92"` + } + + t.Run("correctly picks one of the float32s", func(t *testing.T) { + a := CustomFloat1{} + err := FakeData(&a) + if err != nil { + t.Error("expected no error but got ", err) + } + one := a.Price == 3.14 + two := a.Price == 15.92 + + if !one && !two { + t.Errorf("expected either %v or %v but got %v", 3.14, 15.92, a.Price) + } + }) + + type CustomFloat6 struct { + Price float64 `faker:"oneof: 34566872.57446732, 969525372.57563314"` + } + + t.Run("correctly picks one of the float64s", func(t *testing.T) { + a := CustomFloat6{} + err := FakeData(&a) + if err != nil { + t.Error("expected no error but got ", err) + } + const first = 34566872.57446732 + const second = 969525372.57563314 + one := a.Price == first + two := a.Price == second + + if !one && !two { + t.Errorf("expected either %v or %v but got %v", first, second, a.Price) + } + }) + + type CustomTypeLotsOfInts struct { + Age1 int64 `faker:"oneof: 1, 2"` + Age2 int32 `faker:"oneof: 3, 5"` + Age3 int16 `faker:"oneof: 8, 13"` + Age4 int8 `faker:"oneof: 21, 34"` + Age5 int `faker:"oneof: 55, 89"` + Age6 uint64 `faker:"oneof: 2, 4"` + Age7 uint32 `faker:"oneof: 6, 8"` + Age8 uint16 `faker:"oneof: 10, 12"` + Age9 uint8 `faker:"oneof: 3, 5"` + Age0 uint `faker:"oneof: 7, 9"` + } + + t.Run("Should support all the int types", func(t *testing.T) { + a := CustomTypeLotsOfInts{} + err := FakeData(&a) + if err != nil { + t.Errorf("expected no error but got %v", err) + } + }) + +} + +func TestOneOfTag__BadInputsForFloats(t *testing.T) { + + type CustomWrongFloat1 struct { + Price float32 `faker:"oneof:"` + } + + t.Run("errors when tag is not used correctly no args float32", func(t *testing.T) { + a := CustomWrongFloat1{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1323,12 +1408,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofWrongString1 struct { - PaymentType string `faker:"oneof"` + type CustomWrongFloat2 struct { + Price float32 `faker:"oneof: 15.5: 18.9, 35.4747"` } - t.Run("errors when tag is not used correctly string no args or even colon separator", func(t *testing.T) { - a := CustomOneofWrongString1{} + t.Run("errors when tag is not used correctly float32 invalid argument separator", func(t *testing.T) { + a := CustomWrongFloat2{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1340,15 +1425,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofWrongString2 struct { - PaymentType string `faker:"oneof: cc: check, bank"` + type CustomWrongFloat3 struct { + Price float32 `faker:"oneof: 1648.4564673, 894572.997376, oops"` } - t.Run("errors when tag is not used correctly string invalid argument separator", func(t *testing.T) { - a := CustomOneofWrongString2{} + t.Run("errors when tag is not used correctly float32 invalid argument type", func(t *testing.T) { + a := CustomWrongFloat3{} err := FakeData(&a) if err == nil { - t.Errorf("expected error, but got no error") + t.Fatal("expected error, but got no error") } actual := err.Error() expected := ErrUnsupportedTagArguments @@ -1357,15 +1442,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongString3 struct { - PaymentType string `faker:"oneof: credit card"` + type CustomWrongFloat4 struct { + Price float32 `faker:"oneof: 1848205.48483727"` } - t.Run("errors when tag is not used correctly string only one argument", func(t *testing.T) { - a := CustomWrongString3{} + t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { + a := CustomWrongFloat4{} err := FakeData(&a) if err == nil { - t.Errorf("expected error, but got no error") + t.Fatal("expected error, but got no error") } actual := err.Error() expected := ErrNotEnoughTagArguments @@ -1374,15 +1459,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongString4 struct { - PaymentType string `faker:"oneof: ,,,cc, credit card,,"` + type CustomWrongFloat5 struct { + Price float32 `faker:"oneof: 15,,16,17"` } - t.Run("errors when tag is not used correctly string duplicate separator", func(t *testing.T) { - a := CustomWrongString4{} + t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { + a := CustomWrongFloat5{} err := FakeData(&a) if err == nil { - t.Errorf("expected error, but got no error") + t.Fatal("expected error, but got no error") } actual := err.Error() expected := ErrDuplicateSeparator @@ -1391,34 +1476,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofInt1 struct { - Age int `faker:"oneof: 16, 18, 21"` - } - - t.Run("should pick one of the number args", func(t *testing.T) { - a := CustomOneofInt1{} - err := FakeData(&a) - if err != nil { - t.Errorf("expected no error, but got %v", err) - } - one := a.Age == 16 - two := a.Age == 18 - three := a.Age == 21 - actual := a.Age - if !one && !two && !three { - t.Errorf( - "expected either %v, %v, or %v, but got %v", - 16, 18, 21, actual, - ) - } - }) - - type CustomOneofWrongInt struct { - Age int `faker:"oneof:"` + type CustomWrongFloat7 struct { + Price float64 `faker:"oneof:"` } - t.Run("errors when tag is not used correctly no args int", func(t *testing.T) { - a := CustomOneofWrongInt{} + t.Run("errors when tag is not used correctly no args float64", func(t *testing.T) { + a := CustomWrongFloat7{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1430,12 +1493,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofWrongInt2 struct { - Age int `faker:"oneof: 15: 18, 35"` + type CustomWrongFloat8 struct { + Price float64 `faker:"oneof: 157285.842725: 184028.474729, 3574626.4747"` } - t.Run("errors when tag is not used correctly int invalid argument separator", func(t *testing.T) { - a := CustomOneofWrongInt2{} + t.Run("errors when tag is not used correctly float64 invalid argument separator", func(t *testing.T) { + a := CustomWrongFloat8{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1447,12 +1510,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomOneofWrongInt3 struct { - Age int `faker:"oneof: 15, 18, oops"` + type CustomWrongFloat9 struct { + Price float64 `faker:"oneof: 1648.4564673, 894572.997376, oops"` } - t.Run("errors when tag is not used correctly int invalid argument type", func(t *testing.T) { - a := CustomOneofWrongInt3{} + t.Run("errors when tag is not used correctly float64 invalid argument type", func(t *testing.T) { + a := CustomWrongFloat9{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1464,12 +1527,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongInt4 struct { - Age int `faker:"oneof: 15"` + type CustomWrongFloat10 struct { + Price float64 `faker:"oneof: 1848205.48483727"` } - t.Run("errors when tag is not used correctly int only one argument", func(t *testing.T) { - a := CustomWrongInt4{} + t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { + a := CustomWrongFloat10{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1481,12 +1544,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongInt5 struct { - Age int `faker:"oneof: 15,,16,17"` + type CustomWrongFloat11 struct { + Price float64 `faker:"oneof: 15,,16,17"` } - t.Run("errors when tag is not used correctly int only one argument", func(t *testing.T) { - a := CustomWrongInt5{} + t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { + a := CustomWrongFloat11{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1498,30 +1561,16 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomFloat1 struct { - Price float32 `faker:"oneof: 3.14, 15.92"` - } - - t.Run("correctly picks one of the float32s", func(t *testing.T) { - a := CustomFloat1{} - err := FakeData(&a) - if err != nil { - t.Error("expected no error but got ", err) - } - one := a.Price == 3.14 - two := a.Price == 15.92 +} - if !one && !two { - t.Errorf("expected either %v or %v but got %v", 3.14, 15.92, a.Price) - } - }) +func TestOneOfTag__BadInputsForStrings(t *testing.T) { - type CustomWrongFloat1 struct { - Price float32 `faker:"oneof:"` + type CustomOneofWrongString struct { + PaymentType string `faker:"oneof:"` } - t.Run("errors when tag is not used correctly no args float32", func(t *testing.T) { - a := CustomWrongFloat1{} + t.Run("errors when tag is not used correctly string no args", func(t *testing.T) { + a := CustomOneofWrongString{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1533,12 +1582,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat2 struct { - Price float32 `faker:"oneof: 15.5: 18.9, 35.4747"` + type CustomOneofWrongString1 struct { + PaymentType string `faker:"oneof"` } - t.Run("errors when tag is not used correctly float32 invalid argument separator", func(t *testing.T) { - a := CustomWrongFloat2{} + t.Run("errors when tag is not used correctly string no args or even colon separator", func(t *testing.T) { + a := CustomOneofWrongString1{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1550,15 +1599,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat3 struct { - Price float32 `faker:"oneof: 1648.4564673, 894572.997376, oops"` + type CustomOneofWrongString2 struct { + PaymentType string `faker:"oneof: cc: check, bank"` } - t.Run("errors when tag is not used correctly float32 invalid argument type", func(t *testing.T) { - a := CustomWrongFloat3{} + t.Run("errors when tag is not used correctly string invalid argument separator", func(t *testing.T) { + a := CustomOneofWrongString2{} err := FakeData(&a) if err == nil { - t.Fatal("expected error, but got no error") + t.Errorf("expected error, but got no error") } actual := err.Error() expected := ErrUnsupportedTagArguments @@ -1567,15 +1616,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat4 struct { - Price float32 `faker:"oneof: 1848205.48483727"` + type CustomWrongString3 struct { + PaymentType string `faker:"oneof: credit card"` } - t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { - a := CustomWrongFloat4{} + t.Run("errors when tag is not used correctly string only one argument", func(t *testing.T) { + a := CustomWrongString3{} err := FakeData(&a) if err == nil { - t.Fatal("expected error, but got no error") + t.Errorf("expected error, but got no error") } actual := err.Error() expected := ErrNotEnoughTagArguments @@ -1584,15 +1633,15 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat5 struct { - Price float32 `faker:"oneof: 15,,16,17"` + type CustomWrongString4 struct { + PaymentType string `faker:"oneof: ,,,cc, credit card,,"` } - t.Run("errors when tag is not used correctly float32 only one argument", func(t *testing.T) { - a := CustomWrongFloat5{} + t.Run("errors when tag is not used correctly string duplicate separator", func(t *testing.T) { + a := CustomWrongString4{} err := FakeData(&a) if err == nil { - t.Fatal("expected error, but got no error") + t.Errorf("expected error, but got no error") } actual := err.Error() expected := ErrDuplicateSeparator @@ -1601,32 +1650,152 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomFloat6 struct { - Price float64 `faker:"oneof: 34566872.57446732, 969525372.57563314"` +} + +func TestOneOfTag__BadInputsForInts(t *testing.T) { + + type CustomTypeInt64Wrong struct { + Age int64 `faker:"oneof: 1_000_000, oops"` } - t.Run("correctly picks one of the float64s", func(t *testing.T) { - a := CustomFloat6{} + t.Run("should error for int64", func(t *testing.T) { + a := CustomTypeInt64Wrong{} err := FakeData(&a) - if err != nil { - t.Error("expected no error but got ", err) + if err == nil { + t.Errorf("expected error but got nil") } - const first = 34566872.57446732 - const second = 969525372.57563314 - one := a.Price == first - two := a.Price == second + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) - if !one && !two { - t.Errorf("expected either %v or %v but got %v", first, second, a.Price) + type CustomTypeInt32Wrong struct { + Age int32 `faker:"oneof: 1_000_000, oops"` + } + + t.Run("should error for int32", func(t *testing.T) { + a := CustomTypeInt32Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) } }) - type CustomWrongFloat7 struct { - Price float64 `faker:"oneof:"` + type CustomTypeInt16Wrong struct { + Age int16 `faker:"oneof: 1_000, oops"` } - t.Run("errors when tag is not used correctly no args float64", func(t *testing.T) { - a := CustomWrongFloat7{} + t.Run("should error for int16", func(t *testing.T) { + a := CustomTypeInt16Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomTypeInt8Wrong struct { + Age int8 `faker:"oneof: 250, oops"` + } + + t.Run("should error for int8", func(t *testing.T) { + a := CustomTypeInt8Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomTypeUint64Wrong struct { + Age uint64 `faker:"oneof: 250_000_000, oops"` + } + + t.Run("should error for uint64", func(t *testing.T) { + a := CustomTypeUint64Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomTypeUint32Wrong struct { + Age uint32 `faker:"oneof: 2_000_000, oops"` + } + + t.Run("should error for uint32", func(t *testing.T) { + a := CustomTypeUint32Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomTypeUint16Wrong struct { + Age uint16 `faker:"oneof: 2_000, oops"` + } + + t.Run("should error for uint16", func(t *testing.T) { + a := CustomTypeUint16Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomTypeUint8Wrong struct { + Age uint8 `faker:"oneof: 400, oops"` + } + + t.Run("should error for uint8", func(t *testing.T) { + a := CustomTypeUint8Wrong{} + err := FakeData(&a) + if err == nil { + t.Errorf("expected error but got nil") + } + expected := ErrUnsupportedTagArguments + actual := err.Error() + if expected != actual { + t.Errorf("expected %v but got %v", expected, actual) + } + }) + + type CustomOneofWrongInt struct { + Age int `faker:"oneof:"` + } + + t.Run("errors when tag is not used correctly no args int", func(t *testing.T) { + a := CustomOneofWrongInt{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1638,12 +1807,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat8 struct { - Price float64 `faker:"oneof: 157285.842725: 184028.474729, 3574626.4747"` + type CustomOneofWrongInt2 struct { + Age int `faker:"oneof: 15: 18, 35"` } - t.Run("errors when tag is not used correctly float64 invalid argument separator", func(t *testing.T) { - a := CustomWrongFloat8{} + t.Run("errors when tag is not used correctly int invalid argument separator", func(t *testing.T) { + a := CustomOneofWrongInt2{} err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") @@ -1655,12 +1824,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat9 struct { - Price float64 `faker:"oneof: 1648.4564673, 894572.997376, oops"` + type CustomOneofWrongInt3 struct { + Age int `faker:"oneof: 15, 18, oops"` } - t.Run("errors when tag is not used correctly float64 invalid argument type", func(t *testing.T) { - a := CustomWrongFloat9{} + t.Run("errors when tag is not used correctly int invalid argument type", func(t *testing.T) { + a := CustomOneofWrongInt3{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1672,12 +1841,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat10 struct { - Price float64 `faker:"oneof: 1848205.48483727"` + type CustomWrongInt4 struct { + Age int `faker:"oneof: 15"` } - t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { - a := CustomWrongFloat10{} + t.Run("errors when tag is not used correctly int only one argument", func(t *testing.T) { + a := CustomWrongInt4{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1689,12 +1858,12 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomWrongFloat11 struct { - Price float64 `faker:"oneof: 15,,16,17"` + type CustomWrongInt5 struct { + Age int `faker:"oneof: 15,,16,17"` } - t.Run("errors when tag is not used correctly float64 only one argument", func(t *testing.T) { - a := CustomWrongFloat11{} + t.Run("errors when tag is not used correctly int only one argument", func(t *testing.T) { + a := CustomWrongInt5{} err := FakeData(&a) if err == nil { t.Fatal("expected error, but got no error") @@ -1706,27 +1875,6 @@ func TestOneOfTag(t *testing.T) { } }) - type CustomTypeLotsOfInts struct { - Age1 int64 `faker:"oneof: 1, 2"` - Age2 int32 `faker:"oneof: 3, 5"` - Age3 int16 `faker:"oneof: 8, 13"` - Age4 int8 `faker:"oneof: 21, 34"` - Age5 int `faker:"oneof: 55, 89"` - Age6 uint64 `faker:"oneof: 2, 4"` - Age7 uint32 `faker:"oneof: 6, 8"` - Age8 uint16 `faker:"oneof: 10, 12"` - Age9 uint8 `faker:"oneof: 3, 5"` - Age0 uint `faker:"oneof: 7, 9"` - } - - t.Run("Should support all the int types", func(t *testing.T) { - a := CustomTypeLotsOfInts{} - err := FakeData(&a) - if err != nil { - t.Errorf("expected no error but got %v", err) - } - }) - type CustomTypeNegativeUnsigned struct { Age uint `faker:"oneof: -45, -42"` } @@ -1762,10 +1910,6 @@ func TestFakeData3(t *testing.T) { }) } -func TestGetValueWithTag(t *testing.T) { - -} - // getStringLen for language independent string length func utfLen(value string) int { var r int From c749bb5d17d8b88fa943dd02cd70ed545a6560c1 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Wed, 10 Jun 2020 19:44:20 -0500 Subject: [PATCH 14/16] update sub-test names to be more clear --- faker_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/faker_test.go b/faker_test.go index 85edf5f..7a9d68b 100644 --- a/faker_test.go +++ b/faker_test.go @@ -1658,7 +1658,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age int64 `faker:"oneof: 1_000_000, oops"` } - t.Run("should error for int64", func(t *testing.T) { + t.Run("should error for int64 with bad tag arguments", func(t *testing.T) { a := CustomTypeInt64Wrong{} err := FakeData(&a) if err == nil { @@ -1675,7 +1675,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age int32 `faker:"oneof: 1_000_000, oops"` } - t.Run("should error for int32", func(t *testing.T) { + t.Run("should error for int32 with bad tag arguments", func(t *testing.T) { a := CustomTypeInt32Wrong{} err := FakeData(&a) if err == nil { @@ -1692,7 +1692,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age int16 `faker:"oneof: 1_000, oops"` } - t.Run("should error for int16", func(t *testing.T) { + t.Run("should error for int16 with bad tag arguments", func(t *testing.T) { a := CustomTypeInt16Wrong{} err := FakeData(&a) if err == nil { @@ -1709,7 +1709,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age int8 `faker:"oneof: 250, oops"` } - t.Run("should error for int8", func(t *testing.T) { + t.Run("should error for int8 with bad tag arguments", func(t *testing.T) { a := CustomTypeInt8Wrong{} err := FakeData(&a) if err == nil { @@ -1726,7 +1726,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age uint64 `faker:"oneof: 250_000_000, oops"` } - t.Run("should error for uint64", func(t *testing.T) { + t.Run("should error for uint64 with bad tag arguments", func(t *testing.T) { a := CustomTypeUint64Wrong{} err := FakeData(&a) if err == nil { @@ -1743,7 +1743,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age uint32 `faker:"oneof: 2_000_000, oops"` } - t.Run("should error for uint32", func(t *testing.T) { + t.Run("should error for uint32 with bad tag arguments", func(t *testing.T) { a := CustomTypeUint32Wrong{} err := FakeData(&a) if err == nil { @@ -1760,7 +1760,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age uint16 `faker:"oneof: 2_000, oops"` } - t.Run("should error for uint16", func(t *testing.T) { + t.Run("should error for uint16 with bad tag arguments", func(t *testing.T) { a := CustomTypeUint16Wrong{} err := FakeData(&a) if err == nil { @@ -1777,7 +1777,7 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { Age uint8 `faker:"oneof: 400, oops"` } - t.Run("should error for uint8", func(t *testing.T) { + t.Run("should error for uint8 with bad tag arguments", func(t *testing.T) { a := CustomTypeUint8Wrong{} err := FakeData(&a) if err == nil { From a7ed949ac9f919793e4aa781e3d7da79e614c638 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Thu, 11 Jun 2020 10:06:42 -0500 Subject: [PATCH 15/16] change base back to base 10 and allow support for other base numbers to be added in a later PR --- tag_argument_extractor.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tag_argument_extractor.go b/tag_argument_extractor.go index e8d96be..552df7f 100644 --- a/tag_argument_extractor.go +++ b/tag_argument_extractor.go @@ -42,7 +42,7 @@ func extractInt64FromTagArgs(args []string) (interface{}, error) { var floatValues []int64 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseInt(k, 0, bytes) + j, err := strconv.ParseInt(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -57,7 +57,7 @@ func extractInt32FromTagArgs(args []string) (interface{}, error) { var floatValues []int32 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseInt(k, 0, bytes) + j, err := strconv.ParseInt(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -72,7 +72,7 @@ func extractInt16FromTagArgs(args []string) (interface{}, error) { var floatValues []int16 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseInt(k, 0, bytes) + j, err := strconv.ParseInt(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -87,7 +87,7 @@ func extractInt8FromTagArgs(args []string) (interface{}, error) { var floatValues []int8 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseInt(k, 0, bytes) + j, err := strconv.ParseInt(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -102,7 +102,7 @@ func extractIntFromTagArgs(args []string) (interface{}, error) { var floatValues []int for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseInt(k, 0, bytes) + j, err := strconv.ParseInt(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -117,7 +117,7 @@ func extractUint64FromTagArgs(args []string) (interface{}, error) { var floatValues []uint64 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 0, bytes) + j, err := strconv.ParseUint(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -132,7 +132,7 @@ func extractUint32FromTagArgs(args []string) (interface{}, error) { var floatValues []uint32 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 0, bytes) + j, err := strconv.ParseUint(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -147,7 +147,7 @@ func extractUint16FromTagArgs(args []string) (interface{}, error) { var floatValues []uint16 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 0, bytes) + j, err := strconv.ParseUint(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -162,7 +162,7 @@ func extractUint8FromTagArgs(args []string) (interface{}, error) { var floatValues []uint8 for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 0, bytes) + j, err := strconv.ParseUint(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } @@ -177,7 +177,7 @@ func extractUintFromTagArgs(args []string) (interface{}, error) { var floatValues []uint for _, i := range args { k := strings.TrimSpace(i) - j, err := strconv.ParseUint(k, 0, bytes) + j, err := strconv.ParseUint(k, 10, bytes) if err != nil { return nil, fmt.Errorf(ErrUnsupportedTagArguments) } From 94ceac276324c1887266a9d915a7d935bfc8b961 Mon Sep 17 00:00:00 2001 From: Andrew Brown <8261769+andrew-werdna@users.noreply.github.com> Date: Thu, 11 Jun 2020 10:07:55 -0500 Subject: [PATCH 16/16] update readme with small comment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index efb6c4c..f9c6af0 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Unfortunately this library has some limitation * It does not support the `map[interface{}]interface{}`, `map[any_type]interface{}` & `map[interface{}]any_type` data types. Once again, we cannot generate values for an unknown data type. * Custom types are not fully supported. However some custom types are already supported: we are still investigating how to do this the correct way. For now, if you use `faker`, it's safer not to use any custom types in order to avoid panics. * Some extra custom types can be supported IF AND ONLY IF extended with [AddProvider()](https://github.com/bxcodec/faker/blob/9169c33ae9926e5b8f8732909790ee20b10b736a/faker.go#L320) please see [example](example_custom_faker_test.go#L46) -* The `oneof` tag currently only supports `string`, the `int` types, and both `float32` & `float64`. Further support is coming soon. See [example](example_with_tags_test.go#L53) for usage. +* The `oneof` tag currently only supports `string`, the `int` types, and both `float32` & `float64`. Further support is coming soon (i.e. hex numbers, etc). See [example](example_with_tags_test.go#L53) for usage. ## Contribution