diff --git a/output_tests/struct/anonymous/no_overlap/float64/json_test.go b/output_tests/struct/anonymous/no_overlap/float64/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/float64/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/float64/types.go b/output_tests/struct/anonymous/no_overlap/float64/types.go new file mode 100644 index 0000000..e057f15 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/float64/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded float64 + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/int32/json_test.go b/output_tests/struct/anonymous/no_overlap/int32/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/int32/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/int32/types.go b/output_tests/struct/anonymous/no_overlap/int32/types.go new file mode 100644 index 0000000..2733f97 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/int32/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded int32 + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/map_string_string/json_test.go b/output_tests/struct/anonymous/no_overlap/map_string_string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/map_string_string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/map_string_string/types.go b/output_tests/struct/anonymous/no_overlap/map_string_string/types.go new file mode 100644 index 0000000..1330737 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/map_string_string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded map[string]string + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_float64/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_float64/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_float64/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_float64/types.go b/output_tests/struct/anonymous/no_overlap/ptr_float64/types.go new file mode 100644 index 0000000..827ffef --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_float64/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded float64 + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_int32/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_int32/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_int32/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_int32/types.go b/output_tests/struct/anonymous/no_overlap/ptr_int32/types.go new file mode 100644 index 0000000..e9d208b --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_int32/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded int32 + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/types.go b/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/types.go new file mode 100644 index 0000000..58d8ef2 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_map_string_string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded map[string]string + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_slice_string/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_slice_string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_slice_string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_slice_string/types.go b/output_tests/struct/anonymous/no_overlap/ptr_slice_string/types.go new file mode 100644 index 0000000..4c4294d --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_slice_string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded []string + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_string/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_string/types.go b/output_tests/struct/anonymous/no_overlap/ptr_string/types.go new file mode 100644 index 0000000..1286763 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded string + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_struct_various/json_test.go b/output_tests/struct/anonymous/no_overlap/ptr_struct_various/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_struct_various/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/ptr_struct_various/types.go b/output_tests/struct/anonymous/no_overlap/ptr_struct_various/types.go new file mode 100644 index 0000000..f025afe --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/ptr_struct_various/types.go @@ -0,0 +1,16 @@ +package test + +type Embedded struct { + String string + Int int32 + Float float64 + Struct struct { + X string + } + Slice []string + Map map[string]string +} + +type T struct { + *Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/slice_string/json_test.go b/output_tests/struct/anonymous/no_overlap/slice_string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/slice_string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/slice_string/types.go b/output_tests/struct/anonymous/no_overlap/slice_string/types.go new file mode 100644 index 0000000..0e59e70 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/slice_string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded []string + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/string/json_test.go b/output_tests/struct/anonymous/no_overlap/string/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/string/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/string/types.go b/output_tests/struct/anonymous/no_overlap/string/types.go new file mode 100644 index 0000000..008f903 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/string/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded string + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/no_overlap/string_with_tag/json_test.go b/output_tests/struct/anonymous/no_overlap/string_with_tag/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/string_with_tag/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/string_with_tag/types.go b/output_tests/struct/anonymous/no_overlap/string_with_tag/types.go new file mode 100644 index 0000000..b7e01bd --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/string_with_tag/types.go @@ -0,0 +1,7 @@ +package test + +type Embedded string + +type T struct { + Embedded `json:"othername"` +} diff --git a/output_tests/struct/anonymous/no_overlap/struct_various/json_test.go b/output_tests/struct/anonymous/no_overlap/struct_various/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/struct_various/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/no_overlap/struct_various/types.go b/output_tests/struct/anonymous/no_overlap/struct_various/types.go new file mode 100644 index 0000000..19d7328 --- /dev/null +++ b/output_tests/struct/anonymous/no_overlap/struct_various/types.go @@ -0,0 +1,16 @@ +package test + +type Embedded struct { + String string + Int int32 + Float float64 + Struct struct { + X string + } + Slice []string + Map map[string]string +} + +type T struct { + Embedded +} diff --git a/output_tests/struct/anonymous/overlap/different_levels/json_test.go b/output_tests/struct/anonymous/overlap/different_levels/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/different_levels/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/different_levels/types.go b/output_tests/struct/anonymous/overlap/different_levels/types.go new file mode 100644 index 0000000..400441d --- /dev/null +++ b/output_tests/struct/anonymous/overlap/different_levels/types.go @@ -0,0 +1,10 @@ +package test + +type Embedded struct { + F1 int32 +} + +type T struct { + F1 string + Embedded +} diff --git a/output_tests/struct/anonymous/overlap/ignore_deeper_level/json_test.go b/output_tests/struct/anonymous/overlap/ignore_deeper_level/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/ignore_deeper_level/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/ignore_deeper_level/types.go b/output_tests/struct/anonymous/overlap/ignore_deeper_level/types.go new file mode 100644 index 0000000..5417bb3 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/ignore_deeper_level/types.go @@ -0,0 +1,20 @@ +package test + +type DoubleEmbedded struct { + F1 int32 `json:"F1"` +} + +type Embedded1 struct { + DoubleEmbedded + F1 int32 +} + +type Embedded2 struct { + F1 int32 `json:"F1"` + DoubleEmbedded +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/json_test.go b/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/types.go b/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/types.go new file mode 100644 index 0000000..d93fd3c --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_both_tagged/types.go @@ -0,0 +1,14 @@ +package test + +type Embedded1 struct { + F1 int32 `json:"F1"` +} + +type Embedded2 struct { + F1 int32 `json:"F1"` +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_no_tags/json_test.go b/output_tests/struct/anonymous/overlap/same_level_1_no_tags/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_no_tags/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_no_tags/types.go b/output_tests/struct/anonymous/overlap/same_level_1_no_tags/types.go new file mode 100644 index 0000000..2a0036f --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_no_tags/types.go @@ -0,0 +1,14 @@ +package test + +type Embedded1 struct { + F1 int32 +} + +type Embedded2 struct { + F1 int32 +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_tagged/json_test.go b/output_tests/struct/anonymous/overlap/same_level_1_tagged/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_tagged/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_1_tagged/types.go b/output_tests/struct/anonymous/overlap/same_level_1_tagged/types.go new file mode 100644 index 0000000..e4cf42f --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_1_tagged/types.go @@ -0,0 +1,14 @@ +package test + +type Embedded1 struct { + F1 int32 +} + +type Embedded2 struct { + F1 int32 `json:"F1"` +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/json_test.go b/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/types.go b/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/types.go new file mode 100644 index 0000000..f434c5d --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_both_tagged/types.go @@ -0,0 +1,22 @@ +package test + +type DoubleEmbedded1 struct { + F1 int32 `json:"F1"` +} + +type Embedded1 struct { + DoubleEmbedded1 +} + +type DoubleEmbedded2 struct { + F1 int32 `json:"F1"` +} + +type Embedded2 struct { + DoubleEmbedded2 +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_no_tags/json_test.go b/output_tests/struct/anonymous/overlap/same_level_2_no_tags/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_no_tags/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_no_tags/types.go b/output_tests/struct/anonymous/overlap/same_level_2_no_tags/types.go new file mode 100644 index 0000000..e19a1be --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_no_tags/types.go @@ -0,0 +1,22 @@ +package test + +type DoubleEmbedded1 struct { + F1 int32 +} + +type Embedded1 struct { + DoubleEmbedded1 +} + +type DoubleEmbedded2 struct { + F1 int32 +} + +type Embedded2 struct { + DoubleEmbedded2 +} + +type T struct { + Embedded1 + Embedded2 +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_tagged/json_test.go b/output_tests/struct/anonymous/overlap/same_level_2_tagged/json_test.go new file mode 100644 index 0000000..8c7d795 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_tagged/json_test.go @@ -0,0 +1,152 @@ +package test + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/davecgh/go-spew/spew" + fuzz "github.com/google/gofuzz" + jsoniter "github.com/json-iterator/go" +) + +func Test_Roundtrip(t *testing.T) { + fz := fuzz.New().MaxDepth(10).NilChance(0.3) + for i := 0; i < 1000; i++ { + var before T + fz.Fuzz(&before) + + jbStd, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with stdlib: %v", err) + } + if len(strings.TrimSpace(string(jbStd))) == 0 { + t.Fatal("stdlib marshal produced empty result and no error") + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal with jsoniter: %v", err) + } + if len(strings.TrimSpace(string(jbIter))) == 0 { + t.Fatal("jsoniter marshal produced empty result and no error") + } + if string(jbStd) != string(jbIter) { + t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s", + indent(jbStd, " "), indent(jbIter, " "), dump(before)) + } + + var afterStd T + err = json.Unmarshal(jbIter, &afterStd) + if err != nil { + t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s", + err, indent(jbIter, " ")) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s", + dump(afterStd), dump(afterIter), indent(jbIter, " ")) + } + } +} + +const indentStr = "> " + +func fingerprint(obj interface{}) string { + c := spew.ConfigState{ + SortKeys: true, + SpewKeys: true, + } + return c.Sprintf("%v", obj) +} + +func dump(obj interface{}) string { + cfg := spew.ConfigState{ + Indent: indentStr, + } + return cfg.Sdump(obj) +} + +func indent(src []byte, prefix string) string { + var buf bytes.Buffer + err := json.Indent(&buf, src, prefix, indentStr) + if err != nil { + return fmt.Sprintf("!!! %v", err) + } + return buf.String() +} + +func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { + t.ReportAllocs() + t.ResetTimer() + + var obj T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&obj) + for i := 0; i < t.N; i++ { + jb, err := fn(obj) + if err != nil { + t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err) + } + _ = jb + } +} + +func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { + t.ReportAllocs() + t.ResetTimer() + + var before T + fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) + fz.Fuzz(&before) + jb, err := json.Marshal(before) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + for i := 0; i < t.N; i++ { + var after T + err = fn(jb, &after) + if err != nil { + t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err) + } + } +} + +func BenchmarkStandardMarshal(t *testing.B) { + benchmarkMarshal(t, "stdlib", json.Marshal) +} + +func BenchmarkStandardUnmarshal(t *testing.B) { + benchmarkUnmarshal(t, "stdlib", json.Unmarshal) +} + +func BenchmarkJSONIterMarshalFastest(t *testing.B) { + benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) +} + +func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) +} + +func BenchmarkJSONIterMarshalDefault(t *testing.B) { + benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) +} + +func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) +} + +func BenchmarkJSONIterMarshalCompatible(t *testing.B) { + benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) +} + +func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { + benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) +} diff --git a/output_tests/struct/anonymous/overlap/same_level_2_tagged/types.go b/output_tests/struct/anonymous/overlap/same_level_2_tagged/types.go new file mode 100644 index 0000000..eebd291 --- /dev/null +++ b/output_tests/struct/anonymous/overlap/same_level_2_tagged/types.go @@ -0,0 +1,22 @@ +package test + +type DoubleEmbedded1 struct { + F1 int32 +} + +type Embedded1 struct { + DoubleEmbedded1 +} + +type DoubleEmbedded2 struct { + F1 int32 `json:"F1"` +} + +type Embedded2 struct { + DoubleEmbedded2 +} + +type T struct { + Embedded1 + Embedded2 +}