diff --git a/output_tests/map/string/ptr_struct/json_test.go b/output_tests/slice/bool/json_test.go similarity index 100% rename from output_tests/map/string/ptr_struct/json_test.go rename to output_tests/slice/bool/json_test.go diff --git a/output_tests/slices/builtins/bool/types.go b/output_tests/slice/bool/types.go similarity index 100% rename from output_tests/slices/builtins/bool/types.go rename to output_tests/slice/bool/types.go diff --git a/output_tests/map/string/struct/json_test.go b/output_tests/slice/byte/json_test.go similarity index 100% rename from output_tests/map/string/struct/json_test.go rename to output_tests/slice/byte/json_test.go diff --git a/output_tests/slices/builtins/byte/types.go b/output_tests/slice/byte/types.go similarity index 100% rename from output_tests/slices/builtins/byte/types.go rename to output_tests/slice/byte/types.go diff --git a/output_tests/slices/builtins/bool/json_test.go b/output_tests/slice/float64/json_test.go similarity index 100% rename from output_tests/slices/builtins/bool/json_test.go rename to output_tests/slice/float64/json_test.go diff --git a/output_tests/slices/builtins/float64/types.go b/output_tests/slice/float64/types.go similarity index 100% rename from output_tests/slices/builtins/float64/types.go rename to output_tests/slice/float64/types.go diff --git a/output_tests/slices/builtins/byte/json_test.go b/output_tests/slice/int32/json_test.go similarity index 100% rename from output_tests/slices/builtins/byte/json_test.go rename to output_tests/slice/int32/json_test.go diff --git a/output_tests/slices/builtins/int32/types.go b/output_tests/slice/int32/types.go similarity index 100% rename from output_tests/slices/builtins/int32/types.go rename to output_tests/slice/int32/types.go diff --git a/output_tests/slices/builtins/float32/json_test.go b/output_tests/slice/map/int32_string/json_test.go similarity index 100% rename from output_tests/slices/builtins/float32/json_test.go rename to output_tests/slice/map/int32_string/json_test.go diff --git a/output_tests/slice/map/int32_string/types.go b/output_tests/slice/map/int32_string/types.go new file mode 100644 index 0000000..001f0ce --- /dev/null +++ b/output_tests/slice/map/int32_string/types.go @@ -0,0 +1,3 @@ +package test + +type T []map[int32]string diff --git a/output_tests/slices/builtins/float64/json_test.go b/output_tests/slice/map/string_string/json_test.go similarity index 100% rename from output_tests/slices/builtins/float64/json_test.go rename to output_tests/slice/map/string_string/json_test.go diff --git a/output_tests/slice/map/string_string/types.go b/output_tests/slice/map/string_string/types.go new file mode 100644 index 0000000..79a1e6c --- /dev/null +++ b/output_tests/slice/map/string_string/types.go @@ -0,0 +1,3 @@ +package test + +type T []map[string]string diff --git a/output_tests/slices/builtins/int32/json_test.go b/output_tests/slice/ptr_bool/json_test.go similarity index 100% rename from output_tests/slices/builtins/int32/json_test.go rename to output_tests/slice/ptr_bool/json_test.go diff --git a/output_tests/slices/pointers/bool/types.go b/output_tests/slice/ptr_bool/types.go similarity index 100% rename from output_tests/slices/pointers/bool/types.go rename to output_tests/slice/ptr_bool/types.go diff --git a/output_tests/slices/builtins/int8/json_test.go b/output_tests/slice/ptr_float64/json_test.go similarity index 100% rename from output_tests/slices/builtins/int8/json_test.go rename to output_tests/slice/ptr_float64/json_test.go diff --git a/output_tests/slices/pointers/float64/types.go b/output_tests/slice/ptr_float64/types.go similarity index 100% rename from output_tests/slices/pointers/float64/types.go rename to output_tests/slice/ptr_float64/types.go diff --git a/output_tests/slices/builtins/string/json_test.go b/output_tests/slice/ptr_int32/json_test.go similarity index 100% rename from output_tests/slices/builtins/string/json_test.go rename to output_tests/slice/ptr_int32/json_test.go diff --git a/output_tests/slices/pointers/int32/types.go b/output_tests/slice/ptr_int32/types.go similarity index 100% rename from output_tests/slices/pointers/int32/types.go rename to output_tests/slice/ptr_int32/types.go diff --git a/output_tests/slices/builtins/uint8/json_test.go b/output_tests/slice/ptr_map/int32_string/json_test.go similarity index 100% rename from output_tests/slices/builtins/uint8/json_test.go rename to output_tests/slice/ptr_map/int32_string/json_test.go diff --git a/output_tests/slice/ptr_map/int32_string/types.go b/output_tests/slice/ptr_map/int32_string/types.go new file mode 100644 index 0000000..90ad4ca --- /dev/null +++ b/output_tests/slice/ptr_map/int32_string/types.go @@ -0,0 +1,3 @@ +package test + +type T []*map[int32]string diff --git a/output_tests/slices/pointers/bool/json_test.go b/output_tests/slice/ptr_map/string_string/json_test.go similarity index 100% rename from output_tests/slices/pointers/bool/json_test.go rename to output_tests/slice/ptr_map/string_string/json_test.go diff --git a/output_tests/slice/ptr_map/string_string/types.go b/output_tests/slice/ptr_map/string_string/types.go new file mode 100644 index 0000000..f905206 --- /dev/null +++ b/output_tests/slice/ptr_map/string_string/types.go @@ -0,0 +1,3 @@ +package test + +type T []*map[string]string diff --git a/output_tests/slices/pointers/float32/json_test.go b/output_tests/slice/ptr_slice/bool/json_test.go similarity index 100% rename from output_tests/slices/pointers/float32/json_test.go rename to output_tests/slice/ptr_slice/bool/json_test.go diff --git a/output_tests/slice/ptr_slice/bool/types.go b/output_tests/slice/ptr_slice/bool/types.go new file mode 100644 index 0000000..83af382 --- /dev/null +++ b/output_tests/slice/ptr_slice/bool/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]bool diff --git a/output_tests/slices/pointers/float64/json_test.go b/output_tests/slice/ptr_slice/byte/json_test.go similarity index 100% rename from output_tests/slices/pointers/float64/json_test.go rename to output_tests/slice/ptr_slice/byte/json_test.go diff --git a/output_tests/slice/ptr_slice/byte/types.go b/output_tests/slice/ptr_slice/byte/types.go new file mode 100644 index 0000000..57a7010 --- /dev/null +++ b/output_tests/slice/ptr_slice/byte/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]byte diff --git a/output_tests/slices/pointers/int32/json_test.go b/output_tests/slice/ptr_slice/float64/json_test.go similarity index 100% rename from output_tests/slices/pointers/int32/json_test.go rename to output_tests/slice/ptr_slice/float64/json_test.go diff --git a/output_tests/slice/ptr_slice/float64/types.go b/output_tests/slice/ptr_slice/float64/types.go new file mode 100644 index 0000000..5ef1fc0 --- /dev/null +++ b/output_tests/slice/ptr_slice/float64/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]float64 diff --git a/output_tests/slices/pointers/int8/json_test.go b/output_tests/slice/ptr_slice/int32/json_test.go similarity index 100% rename from output_tests/slices/pointers/int8/json_test.go rename to output_tests/slice/ptr_slice/int32/json_test.go diff --git a/output_tests/slice/ptr_slice/int32/types.go b/output_tests/slice/ptr_slice/int32/types.go new file mode 100644 index 0000000..22ee72a --- /dev/null +++ b/output_tests/slice/ptr_slice/int32/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]int32 diff --git a/output_tests/slices/pointers/string/json_test.go b/output_tests/slice/ptr_slice/ptr_string/json_test.go similarity index 100% rename from output_tests/slices/pointers/string/json_test.go rename to output_tests/slice/ptr_slice/ptr_string/json_test.go diff --git a/output_tests/slice/ptr_slice/ptr_string/types.go b/output_tests/slice/ptr_slice/ptr_string/types.go new file mode 100644 index 0000000..5f9188e --- /dev/null +++ b/output_tests/slice/ptr_slice/ptr_string/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]*string diff --git a/output_tests/slices/slices/bool/json_test.go b/output_tests/slice/ptr_slice/string/json_test.go similarity index 100% rename from output_tests/slices/slices/bool/json_test.go rename to output_tests/slice/ptr_slice/string/json_test.go diff --git a/output_tests/slice/ptr_slice/string/types.go b/output_tests/slice/ptr_slice/string/types.go new file mode 100644 index 0000000..ac60616 --- /dev/null +++ b/output_tests/slice/ptr_slice/string/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]string diff --git a/output_tests/slices/slices/byte/json_test.go b/output_tests/slice/ptr_slice/uint8/json_test.go similarity index 100% rename from output_tests/slices/slices/byte/json_test.go rename to output_tests/slice/ptr_slice/uint8/json_test.go diff --git a/output_tests/slice/ptr_slice/uint8/types.go b/output_tests/slice/ptr_slice/uint8/types.go new file mode 100644 index 0000000..d036526 --- /dev/null +++ b/output_tests/slice/ptr_slice/uint8/types.go @@ -0,0 +1,3 @@ +package test + +type T []*[]uint8 diff --git a/output_tests/slices/slices/float64/json_test.go b/output_tests/slice/ptr_string/json_test.go similarity index 100% rename from output_tests/slices/slices/float64/json_test.go rename to output_tests/slice/ptr_string/json_test.go diff --git a/output_tests/slices/pointers/string/types.go b/output_tests/slice/ptr_string/types.go similarity index 100% rename from output_tests/slices/pointers/string/types.go rename to output_tests/slice/ptr_string/types.go diff --git a/output_tests/slices/slices/int32/json_test.go b/output_tests/slice/ptr_struct_various/json_test.go similarity index 100% rename from output_tests/slices/slices/int32/json_test.go rename to output_tests/slice/ptr_struct_various/json_test.go diff --git a/output_tests/map/string/struct/types.go b/output_tests/slice/ptr_struct_various/types.go similarity index 73% rename from output_tests/map/string/struct/types.go rename to output_tests/slice/ptr_struct_various/types.go index 263d4a6..7f2c5a0 100644 --- a/output_tests/map/string/struct/types.go +++ b/output_tests/slice/ptr_struct_various/types.go @@ -1,6 +1,6 @@ package test -type Struct struct { +type T []*struct { String string Int int32 Float float64 @@ -10,5 +10,3 @@ type Struct struct { Slice []string Map map[string]string } - -type T map[string]Struct diff --git a/output_tests/slices/slices/int8/json_test.go b/output_tests/slice/ptr_uint8/json_test.go similarity index 100% rename from output_tests/slices/slices/int8/json_test.go rename to output_tests/slice/ptr_uint8/json_test.go diff --git a/output_tests/slice/ptr_uint8/types.go b/output_tests/slice/ptr_uint8/types.go new file mode 100644 index 0000000..61ac629 --- /dev/null +++ b/output_tests/slice/ptr_uint8/types.go @@ -0,0 +1,3 @@ +package test + +type T []*uint8 diff --git a/output_tests/slices/slices/ptr_string/json_test.go b/output_tests/slice/slice/bool/json_test.go similarity index 100% rename from output_tests/slices/slices/ptr_string/json_test.go rename to output_tests/slice/slice/bool/json_test.go diff --git a/output_tests/slices/slices/bool/types.go b/output_tests/slice/slice/bool/types.go similarity index 100% rename from output_tests/slices/slices/bool/types.go rename to output_tests/slice/slice/bool/types.go diff --git a/output_tests/slices/slices/string/json_test.go b/output_tests/slice/slice/byte/json_test.go similarity index 100% rename from output_tests/slices/slices/string/json_test.go rename to output_tests/slice/slice/byte/json_test.go diff --git a/output_tests/slices/slices/byte/types.go b/output_tests/slice/slice/byte/types.go similarity index 100% rename from output_tests/slices/slices/byte/types.go rename to output_tests/slice/slice/byte/types.go diff --git a/output_tests/slices/slices/struct_empty/json_test.go b/output_tests/slice/slice/float64/json_test.go similarity index 100% rename from output_tests/slices/slices/struct_empty/json_test.go rename to output_tests/slice/slice/float64/json_test.go diff --git a/output_tests/slices/slices/float64/types.go b/output_tests/slice/slice/float64/types.go similarity index 100% rename from output_tests/slices/slices/float64/types.go rename to output_tests/slice/slice/float64/types.go diff --git a/output_tests/slices/slices/struct_ptr_string/json_test.go b/output_tests/slice/slice/int32/json_test.go similarity index 100% rename from output_tests/slices/slices/struct_ptr_string/json_test.go rename to output_tests/slice/slice/int32/json_test.go diff --git a/output_tests/slices/slices/int32/types.go b/output_tests/slice/slice/int32/types.go similarity index 100% rename from output_tests/slices/slices/int32/types.go rename to output_tests/slice/slice/int32/types.go diff --git a/output_tests/slices/slices/struct_ptrs_string/json_test.go b/output_tests/slice/slice/ptr_string/json_test.go similarity index 100% rename from output_tests/slices/slices/struct_ptrs_string/json_test.go rename to output_tests/slice/slice/ptr_string/json_test.go diff --git a/output_tests/slices/slices/ptr_string/types.go b/output_tests/slice/slice/ptr_string/types.go similarity index 100% rename from output_tests/slices/slices/ptr_string/types.go rename to output_tests/slice/slice/ptr_string/types.go diff --git a/output_tests/slices/slices/struct_string/json_test.go b/output_tests/slice/slice/string/json_test.go similarity index 100% rename from output_tests/slices/slices/struct_string/json_test.go rename to output_tests/slice/slice/string/json_test.go diff --git a/output_tests/slices/slices/string/types.go b/output_tests/slice/slice/string/types.go similarity index 100% rename from output_tests/slices/slices/string/types.go rename to output_tests/slice/slice/string/types.go diff --git a/output_tests/slices/slices/struct_strings/json_test.go b/output_tests/slice/slice/uint8/json_test.go similarity index 100% rename from output_tests/slices/slices/struct_strings/json_test.go rename to output_tests/slice/slice/uint8/json_test.go diff --git a/output_tests/slice/slice/uint8/types.go b/output_tests/slice/slice/uint8/types.go new file mode 100644 index 0000000..35db451 --- /dev/null +++ b/output_tests/slice/slice/uint8/types.go @@ -0,0 +1,3 @@ +package test + +type T [][]uint8 diff --git a/output_tests/slice/string/json_test.go b/output_tests/slice/string/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/string/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/slices/builtins/string/types.go b/output_tests/slice/string/types.go similarity index 100% rename from output_tests/slices/builtins/string/types.go rename to output_tests/slice/string/types.go diff --git a/output_tests/slice/struct_empty/json_test.go b/output_tests/slice/struct_empty/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/struct_empty/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/slice/struct_empty/types.go b/output_tests/slice/struct_empty/types.go new file mode 100644 index 0000000..5ca1754 --- /dev/null +++ b/output_tests/slice/struct_empty/types.go @@ -0,0 +1,3 @@ +package test + +type T []struct{} diff --git a/output_tests/slice/struct_empty_alias/json_test.go b/output_tests/slice/struct_empty_alias/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/struct_empty_alias/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/slice/struct_empty_alias/types.go b/output_tests/slice/struct_empty_alias/types.go new file mode 100644 index 0000000..ecb5364 --- /dev/null +++ b/output_tests/slice/struct_empty_alias/types.go @@ -0,0 +1,5 @@ +package test + +type A struct{} + +type T []A diff --git a/output_tests/slice/struct_ptr_string/json_test.go b/output_tests/slice/struct_ptr_string/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/struct_ptr_string/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/slice/struct_ptr_string/types.go b/output_tests/slice/struct_ptr_string/types.go new file mode 100644 index 0000000..d81f60f --- /dev/null +++ b/output_tests/slice/struct_ptr_string/types.go @@ -0,0 +1,5 @@ +package test + +type T []struct { + F *string +} diff --git a/output_tests/slice/struct_various/json_test.go b/output_tests/slice/struct_various/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/struct_various/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/map/string/ptr_struct/types.go b/output_tests/slice/struct_various/types.go similarity index 73% rename from output_tests/map/string/ptr_struct/types.go rename to output_tests/slice/struct_various/types.go index 0a1c237..e9653cf 100644 --- a/output_tests/map/string/ptr_struct/types.go +++ b/output_tests/slice/struct_various/types.go @@ -1,6 +1,6 @@ package test -type Struct struct { +type T []struct { String string Int int32 Float float64 @@ -10,5 +10,3 @@ type Struct struct { Slice []string Map map[string]string } - -type T map[string]*Struct diff --git a/output_tests/slice/uint8/json_test.go b/output_tests/slice/uint8/json_test.go new file mode 100644 index 0000000..a7b1d0d --- /dev/null +++ b/output_tests/slice/uint8/json_test.go @@ -0,0 +1,139 @@ +package test + +import ( + "bytes" + "encoding/json" + "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.Errorf("failed to marshal with stdlib: %v", err) + } + jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) + if err != nil { + t.Errorf("failed to marshal with jsoniter: %v", err) + } + if string(jbStd) != string(jbIter) { + t.Errorf("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.Errorf("failed to unmarshal with stdlib: %v", err) + } + var afterIter T + err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) + if err != nil { + t.Errorf("failed to unmarshal with jsoniter: %v", err) + } + if fingerprint(afterStd) != fingerprint(afterIter) { + t.Errorf("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 + json.Indent(&buf, src, prefix, indentStr) + 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/slices/builtins/uint8/types.go b/output_tests/slice/uint8/types.go similarity index 100% rename from output_tests/slices/builtins/uint8/types.go rename to output_tests/slice/uint8/types.go diff --git a/output_tests/slices/builtins/float32/types.go b/output_tests/slices/builtins/float32/types.go deleted file mode 100644 index fba8cbe..0000000 --- a/output_tests/slices/builtins/float32/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T []float32 diff --git a/output_tests/slices/builtins/int8/types.go b/output_tests/slices/builtins/int8/types.go deleted file mode 100644 index 02ccbf2..0000000 --- a/output_tests/slices/builtins/int8/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T []int8 diff --git a/output_tests/slices/pointers/float32/types.go b/output_tests/slices/pointers/float32/types.go deleted file mode 100644 index 59207c2..0000000 --- a/output_tests/slices/pointers/float32/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T []*float32 diff --git a/output_tests/slices/pointers/int8/types.go b/output_tests/slices/pointers/int8/types.go deleted file mode 100644 index 4113c54..0000000 --- a/output_tests/slices/pointers/int8/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T []*int8 diff --git a/output_tests/slices/slices/int8/types.go b/output_tests/slices/slices/int8/types.go deleted file mode 100644 index 5027f30..0000000 --- a/output_tests/slices/slices/int8/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T [][]int8 diff --git a/output_tests/slices/slices/struct_empty/types.go b/output_tests/slices/slices/struct_empty/types.go deleted file mode 100644 index d454cb8..0000000 --- a/output_tests/slices/slices/struct_empty/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package test - -type T [][]struct{} diff --git a/output_tests/slices/slices/struct_ptr_string/types.go b/output_tests/slices/slices/struct_ptr_string/types.go deleted file mode 100644 index 3ee04c7..0000000 --- a/output_tests/slices/slices/struct_ptr_string/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package test - -type T [][]struct { - F1 *string -} diff --git a/output_tests/slices/slices/struct_ptrs_string/types.go b/output_tests/slices/slices/struct_ptrs_string/types.go deleted file mode 100644 index c795d67..0000000 --- a/output_tests/slices/slices/struct_ptrs_string/types.go +++ /dev/null @@ -1,7 +0,0 @@ -package test - -type T [][]struct { - F1 *string - F2 *string - F3 *string -} diff --git a/output_tests/slices/slices/struct_string/types.go b/output_tests/slices/slices/struct_string/types.go deleted file mode 100644 index cb5fea9..0000000 --- a/output_tests/slices/slices/struct_string/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package test - -type T [][]struct { - F1 string -} diff --git a/output_tests/slices/slices/struct_strings/types.go b/output_tests/slices/slices/struct_strings/types.go deleted file mode 100644 index b9903d9..0000000 --- a/output_tests/slices/slices/struct_strings/types.go +++ /dev/null @@ -1,7 +0,0 @@ -package test - -type T [][]struct { - F1 string - F2 string - F3 string -}