From 0d525f17cbcdaed79c3a5a38ad5bef3638893000 Mon Sep 17 00:00:00 2001 From: Jonathan Schweder Date: Fri, 18 Aug 2023 13:31:10 +0100 Subject: [PATCH 1/4] Add Json generator --- faker.go | 5 ++++ json.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ json_test.go | 66 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 json.go create mode 100644 json_test.go diff --git a/faker.go b/faker.go index 65c7062..7102ce3 100644 --- a/faker.go +++ b/faker.go @@ -595,3 +595,8 @@ func NewWithSeed(src rand.Source) (f Faker) { func (f Faker) Blood() Blood { return Blood{&f} } + +// Json returns a fake Json instance for Faker +func (f Faker) Json() Json { + return Json{&f} +} diff --git a/json.go b/json.go new file mode 100644 index 0000000..80a0c46 --- /dev/null +++ b/json.go @@ -0,0 +1,82 @@ +package faker + +import ( + "strconv" + "encoding/json" +) + +// Json is a faker struct for json files +type Json struct { + Faker *Faker +} + +var ( + attributesTypes = []string{"string", "number", "object", "array", "boolean", "null"} + attributesTypesWithoutArrayAndObject = []string{"string", "number", "boolean", "null"} +) + +func (j *Json) randomAttributeValueFromListAsString(validAttributesTypes []string) string { + attributeType := j.Faker.RandomStringElement(validAttributesTypes) + switch attributeType { + case "string": + return "\"" + j.Faker.Lorem().Word() + "\"" + case "number": + number := strconv.Itoa(j.Faker.RandomNumber(j.Faker.RandomDigit())) + return number + case "object": + // Avoid having multiple nested objects by not using object and array as valid attribute types + return j.randomJsonObjectAsString(attributesTypesWithoutArrayAndObject) + case "array": + objects := "" + for i := 0; i < j.Faker.IntBetween(1, 10); i++ { + if objects != "" { + objects += ", " + } + // Avoid having multiple nested objects by not using object and array as valid attribute types + objects += j.randomJsonObjectAsString(attributesTypesWithoutArrayAndObject) + } + return "[" + objects + "]" + case "boolean": + return j.Faker.RandomStringElement([]string{"true", "false"}) + case "null": + return "null" + } + + panic("Invalid attribute type: " + attributeType) +} + +func (j *Json) randomJsonObjectAsString(validAttributesTypes []string) string { + numberAttributes := j.Faker.IntBetween(1, 10) + attributes := make([]string, numberAttributes) + for i := 0; i < numberAttributes; i++ { + attributeName := j.Faker.Lorem().Word() + attributeValue := j.randomAttributeValueFromListAsString(validAttributesTypes) + attributes[i] = "\"" + attributeName + "\": " + attributeValue + } + + result := "{" + for i := 0; i < len(attributes); i++ { + if i > 0 { + result += ", " + } + result += attributes[i] + } + result += "}" + return result +} + +// String generates a random json string +func (j *Json) String() string { + return j.randomJsonObjectAsString(attributesTypes) +} + +// Object generates a random json object +func (j *Json) Object() map[string]interface{} { + result := j.String() + var data map[string]interface{} + err := json.Unmarshal([]byte(result), &data) + if err != nil { + panic(err) + } + return data +} \ No newline at end of file diff --git a/json_test.go b/json_test.go new file mode 100644 index 0000000..250acd5 --- /dev/null +++ b/json_test.go @@ -0,0 +1,66 @@ +package faker + +import ( + "testing" + "encoding/json" +) + +func TestJsonString(t *testing.T) { + faker := New() + j := faker.Json() + + for i := 0; i < 10; i++ { + result := j.String() + + // Attempt to unmarshal the result into a map[string]interface{} + var data map[string]interface{} + err := json.Unmarshal([]byte(result), &data) + Expect(t, err, nil) + + // Ensure that the result is a valid JSON object + Expect(t, len(data) > 0, true) + + // Ensure that all attribute values are valid JSON types + for _, value := range data { + switch value.(type) { + case string, float64, bool, nil: + // Valid JSON types + case []interface{}: + // Valid JSON array type + case map[string]interface{}: + // Valid JSON object type + default: + t.FailNow() + } + } + } +} + +func TestJsonObject(t *testing.T) { + faker := New() + j := faker.Json() + + for i := 0; i < 10; i++ { + data := j.Object() + + // Ensure that the result is not nil + NotExpect(t, data, nil) + + // Ensure that the result is a valid JSON object + Expect(t, len(data) > 0, true) + + // Ensure that all attribute values are valid JSON types + for _, value := range data { + switch value.(type) { + case string, float64, bool, nil: + // Valid JSON types + case []interface{}: + // Valid JSON array type + case map[string]interface{}: + // Valid JSON object type + default: + t.FailNow() + } + } + } +} \ No newline at end of file From b1bf42e19a7beb6482f6282f4b91b66e98ae81c8 Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:33:14 +0000 Subject: [PATCH 2/4] style: Format code with gofumpt and gofmt --- json.go | 6 +++--- json_test.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/json.go b/json.go index 80a0c46..8d1c4b9 100644 --- a/json.go +++ b/json.go @@ -1,8 +1,8 @@ package faker import ( - "strconv" "encoding/json" + "strconv" ) // Json is a faker struct for json files @@ -11,7 +11,7 @@ type Json struct { } var ( - attributesTypes = []string{"string", "number", "object", "array", "boolean", "null"} + attributesTypes = []string{"string", "number", "object", "array", "boolean", "null"} attributesTypesWithoutArrayAndObject = []string{"string", "number", "boolean", "null"} ) @@ -79,4 +79,4 @@ func (j *Json) Object() map[string]interface{} { panic(err) } return data -} \ No newline at end of file +} diff --git a/json_test.go b/json_test.go index 250acd5..c83c622 100644 --- a/json_test.go +++ b/json_test.go @@ -1,8 +1,8 @@ package faker import ( - "testing" "encoding/json" + "testing" ) func TestJsonString(t *testing.T) { @@ -63,4 +63,4 @@ func TestJsonObject(t *testing.T) { } } } -} \ No newline at end of file +} From 83ecd3c16c2aaa7b82fd246988e888a937172926 Mon Sep 17 00:00:00 2001 From: Jonathan Schweder Date: Fri, 18 Aug 2023 13:53:21 +0100 Subject: [PATCH 3/4] Adding test for invalid type --- json.go | 5 +---- json_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/json.go b/json.go index 8d1c4b9..5e19f59 100644 --- a/json.go +++ b/json.go @@ -74,9 +74,6 @@ func (j *Json) String() string { func (j *Json) Object() map[string]interface{} { result := j.String() var data map[string]interface{} - err := json.Unmarshal([]byte(result), &data) - if err != nil { - panic(err) - } + json.Unmarshal([]byte(result), &data) return data } diff --git a/json_test.go b/json_test.go index c83c622..1c7088b 100644 --- a/json_test.go +++ b/json_test.go @@ -64,3 +64,16 @@ func TestJsonObject(t *testing.T) { } } } + +func TestRandomAttributeValueFromListAsStringPanicWhenUnsupportedTypeIsPassed(t *testing.T) { + faker := New() + j := faker.Json() + + defer func() { + if r := recover(); r == nil { + NotExpect(t, r, nil) + } + }() + + j.randomAttributeValueFromListAsString([]string{"unsupported"}) +} \ No newline at end of file From 5750c67ab14dc6c298a3bac9862ca42b1f27121d Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:53:35 +0000 Subject: [PATCH 4/4] style: Format code with gofumpt and gofmt --- json_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json_test.go b/json_test.go index 1c7088b..6b07708 100644 --- a/json_test.go +++ b/json_test.go @@ -76,4 +76,4 @@ func TestRandomAttributeValueFromListAsStringPanicWhenUnsupportedTypeIsPassed(t }() j.randomAttributeValueFromListAsString([]string{"unsupported"}) -} \ No newline at end of file +}