mirror of
https://github.com/json-iterator/go.git
synced 2025-04-20 11:28:49 +02:00
support asymmetric tests
This commit is contained in:
parent
6fded6eb5f
commit
0ed9de94f2
@ -1,84 +0,0 @@
|
|||||||
// NOTE: This test is different than most of the other JSON roundtrip tests.
|
|
||||||
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_CaselessUnmarshal(t *testing.T) {
|
|
||||||
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
var before typeForTest1
|
|
||||||
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 typeForTest2
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest2
|
|
||||||
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()
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
type typeForTest1 struct {
|
|
||||||
Field string
|
|
||||||
}
|
|
||||||
|
|
||||||
type typeForTest2 struct {
|
|
||||||
FIELD string
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type keyType string
|
|
||||||
|
|
||||||
func (k keyType) MarshalText() ([]byte, error) {
|
|
||||||
return []byte("MANUAL__" + k), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *keyType) UnmarshalText(text []byte) error {
|
|
||||||
*k = keyType(strings.TrimPrefix(string(text), "MANUAL__"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = keyType("")
|
|
||||||
var _ encoding.TextUnmarshaler = new(keyType)
|
|
||||||
|
|
||||||
type typeForTest map[keyType]string
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type keyType struct {
|
|
||||||
X string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k keyType) MarshalText() ([]byte, error) {
|
|
||||||
return []byte("MANUAL__" + k.X), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *keyType) UnmarshalText(text []byte) error {
|
|
||||||
k.X = strings.TrimPrefix(string(text), "MANUAL__")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = keyType{}
|
|
||||||
var _ encoding.TextUnmarshaler = &keyType{}
|
|
||||||
|
|
||||||
type typeForTest map[keyType]string
|
|
@ -1,23 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type typeForTest struct {
|
|
||||||
F *float64
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var obj typeForTest
|
|
||||||
|
|
||||||
jb1, _ := json.Marshal(obj)
|
|
||||||
jb2, _ := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj)
|
|
||||||
if !reflect.DeepEqual(jb1, jb2) {
|
|
||||||
fmt.Printf("results differ:\n expected: `%s`\n got: `%s`\n", string(jb1), string(jb2))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
// NOTE: This test is different than most of the other JSON roundtrip tests.
|
|
||||||
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_PartialUnmarshal(t *testing.T) {
|
|
||||||
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
var before typeForTest1
|
|
||||||
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 typeForTest2
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest2
|
|
||||||
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()
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
type typeForTest1 struct {
|
|
||||||
F1 string
|
|
||||||
F2 string
|
|
||||||
F3 string
|
|
||||||
}
|
|
||||||
|
|
||||||
type typeForTest2 struct {
|
|
||||||
F1 string
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type marshalerForTest string
|
|
||||||
|
|
||||||
func encode(str string) string {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
|
||||||
if _, err := b64.Write([]byte(str)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := b64.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(str string) string {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
|
||||||
bs := make([]byte, len(str))
|
|
||||||
if n, err := b64.Read(bs); err != nil {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
bs = bs[:n]
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m marshalerForTest) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(`MANUAL__` + encode(string(m))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *marshalerForTest) UnmarshalText(text []byte) error {
|
|
||||||
*m = marshalerForTest(decode(strings.TrimPrefix(string(text), "MANUAL__")))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = *new(marshalerForTest)
|
|
||||||
var _ encoding.TextUnmarshaler = new(marshalerForTest)
|
|
||||||
|
|
||||||
type typeForTest marshalerForTest
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type marshalerForTest struct {
|
|
||||||
X string
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(str string) string {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
|
||||||
if _, err := b64.Write([]byte(str)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := b64.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(str string) string {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
|
||||||
bs := make([]byte, len(str))
|
|
||||||
if n, err := b64.Read(bs); err != nil {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
bs = bs[:n]
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m marshalerForTest) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(`MANUAL__` + encode(m.X)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *marshalerForTest) UnmarshalText(text []byte) error {
|
|
||||||
m.X = decode(strings.TrimPrefix(string(text), "MANUAL__"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = marshalerForTest{}
|
|
||||||
var _ encoding.TextUnmarshaler = &marshalerForTest{}
|
|
||||||
|
|
||||||
type typeForTest marshalerForTest
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type marshalerForTest struct {
|
|
||||||
X string
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(str string) string {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
|
||||||
if _, err := b64.Write([]byte(str)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := b64.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(str string) string {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
|
||||||
bs := make([]byte, len(str))
|
|
||||||
if n, err := b64.Read(bs); err != nil {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
bs = bs[:n]
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m marshalerForTest) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(`MANUAL__` + encode(m.X)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *marshalerForTest) UnmarshalText(text []byte) error {
|
|
||||||
m.X = decode(strings.TrimPrefix(string(text), "MANUAL__"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = marshalerForTest{}
|
|
||||||
var _ encoding.TextUnmarshaler = &marshalerForTest{}
|
|
||||||
|
|
||||||
type marshalerAlias marshalerForTest
|
|
||||||
|
|
||||||
type typeForTest marshalerAlias
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type marshalerForTest struct {
|
|
||||||
X string
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(str string) string {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
|
||||||
if _, err := b64.Write([]byte(str)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := b64.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(str string) string {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
|
||||||
bs := make([]byte, len(str))
|
|
||||||
if n, err := b64.Read(bs); err != nil {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
bs = bs[:n]
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m marshalerForTest) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(`MANUAL__` + encode(m.X)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *marshalerForTest) UnmarshalText(text []byte) error {
|
|
||||||
m.X = decode(strings.TrimPrefix(string(text), "MANUAL__"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = marshalerForTest{}
|
|
||||||
var _ encoding.TextUnmarshaler = &marshalerForTest{}
|
|
||||||
|
|
||||||
type typeForTest struct {
|
|
||||||
S string
|
|
||||||
M marshalerForTest
|
|
||||||
I int8
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
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 < 100; i++ {
|
|
||||||
var before typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
err = json.Unmarshal(jbIter, &afterStd)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
|
||||||
err, indent(jbIter, " "))
|
|
||||||
}
|
|
||||||
var afterIter typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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 typeForTest
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type marshalerForTest struct {
|
|
||||||
X string
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(str string) string {
|
|
||||||
buf := bytes.Buffer{}
|
|
||||||
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
|
||||||
if _, err := b64.Write([]byte(str)); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if err := b64.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode(str string) string {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
|
||||||
bs := make([]byte, len(str))
|
|
||||||
if n, err := b64.Read(bs); err != nil {
|
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
bs = bs[:n]
|
|
||||||
}
|
|
||||||
return string(bs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m marshalerForTest) MarshalText() ([]byte, error) {
|
|
||||||
return []byte(`MANUAL__` + encode(m.X)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *marshalerForTest) UnmarshalText(text []byte) error {
|
|
||||||
m.X = decode(strings.TrimPrefix(string(text), "MANUAL__"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ encoding.TextMarshaler = marshalerForTest{}
|
|
||||||
var _ encoding.TextUnmarshaler = &marshalerForTest{}
|
|
||||||
|
|
||||||
type marshalerAlias marshalerForTest
|
|
||||||
|
|
||||||
type typeForTest struct {
|
|
||||||
S string
|
|
||||||
M marshalerAlias
|
|
||||||
I int8
|
|
||||||
}
|
|
44
type_tests/map_key_test.go
Normal file
44
type_tests/map_key_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"encoding"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testCases = append(testCases,
|
||||||
|
(*map[stringKeyType]string)(nil),
|
||||||
|
(*map[structKeyType]string)(nil),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringKeyType string
|
||||||
|
|
||||||
|
func (k stringKeyType) MarshalText() ([]byte, error) {
|
||||||
|
return []byte("MANUAL__" + k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *stringKeyType) UnmarshalText(text []byte) error {
|
||||||
|
*k = stringKeyType(strings.TrimPrefix(string(text), "MANUAL__"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ encoding.TextMarshaler = stringKeyType("")
|
||||||
|
var _ encoding.TextUnmarshaler = new(stringKeyType)
|
||||||
|
|
||||||
|
|
||||||
|
type structKeyType struct {
|
||||||
|
X string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k structKeyType) MarshalText() ([]byte, error) {
|
||||||
|
return []byte("MANUAL__" + k.X), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *structKeyType) UnmarshalText(text []byte) error {
|
||||||
|
k.X = strings.TrimPrefix(string(text), "MANUAL__")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ encoding.TextMarshaler = structKeyType{}
|
||||||
|
var _ encoding.TextUnmarshaler = &structKeyType{}
|
24
type_tests/struct_field_case_test.go
Normal file
24
type_tests/struct_field_case_test.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
asymmetricTestCases = append(asymmetricTestCases, [][2]interface{}{
|
||||||
|
{
|
||||||
|
(*struct {
|
||||||
|
Field string
|
||||||
|
})(nil),
|
||||||
|
(*struct {
|
||||||
|
FIELD string
|
||||||
|
})(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
(*struct {
|
||||||
|
F1 string
|
||||||
|
F2 string
|
||||||
|
F3 string
|
||||||
|
})(nil),
|
||||||
|
(*struct {
|
||||||
|
F1 string
|
||||||
|
})(nil),
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
}
|
@ -7,6 +7,12 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testCases = append(testCases,
|
||||||
|
(*StringTextMarshaler)(nil),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// StringTextMarshaler TEST ONLY
|
// StringTextMarshaler TEST ONLY
|
||||||
type StringTextMarshaler string
|
type StringTextMarshaler string
|
||||||
|
|
||||||
|
69
type_tests/text_marshaler_struct_test.go
Normal file
69
type_tests/text_marshaler_struct_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"strings"
|
||||||
|
"encoding"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testCases = append(testCases,
|
||||||
|
(*structTextMarshaler)(nil),
|
||||||
|
(*structTextMarshalerAlias)(nil),
|
||||||
|
(*struct {
|
||||||
|
S string
|
||||||
|
M structTextMarshaler
|
||||||
|
I int8
|
||||||
|
})(nil),
|
||||||
|
(*struct {
|
||||||
|
S string
|
||||||
|
M structTextMarshalerAlias
|
||||||
|
I int8
|
||||||
|
})(nil),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type structTextMarshaler struct {
|
||||||
|
X string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m structTextMarshaler) encode(str string) string {
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
b64 := base64.NewEncoder(base64.StdEncoding, &buf)
|
||||||
|
if _, err := b64.Write([]byte(str)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := b64.Close(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m structTextMarshaler) decode(str string) string {
|
||||||
|
if len(str) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str))
|
||||||
|
bs := make([]byte, len(str))
|
||||||
|
if n, err := b64.Read(bs); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
bs = bs[:n]
|
||||||
|
}
|
||||||
|
return string(bs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m structTextMarshaler) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(`MANUAL__` + m.encode(m.X)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *structTextMarshaler) UnmarshalText(text []byte) error {
|
||||||
|
m.X = m.decode(strings.TrimPrefix(string(text), "MANUAL__"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ encoding.TextMarshaler = structTextMarshaler{}
|
||||||
|
var _ encoding.TextUnmarshaler = &structTextMarshaler{}
|
||||||
|
|
||||||
|
type structTextMarshalerAlias structTextMarshaler
|
@ -13,8 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var testCases []interface{}
|
var testCases []interface{}
|
||||||
|
var asymmetricTestCases [][2]interface{}
|
||||||
|
|
||||||
func Test(t *testing.T) {
|
func Test_symmetric(t *testing.T) {
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
valType := reflect.TypeOf(testCase).Elem()
|
valType := reflect.TypeOf(testCase).Elem()
|
||||||
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
|
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
|
||||||
@ -67,6 +68,60 @@ func Test(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_asymmetric(t *testing.T) {
|
||||||
|
for _, testCase := range asymmetricTestCases {
|
||||||
|
fromType := reflect.TypeOf(testCase[0]).Elem()
|
||||||
|
toType := reflect.TypeOf(testCase[1]).Elem()
|
||||||
|
fz := fuzz.New().MaxDepth(10).NilChance(0.3)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
beforePtrVal := reflect.New(fromType)
|
||||||
|
beforePtr := beforePtrVal.Interface()
|
||||||
|
fz.Fuzz(beforePtr)
|
||||||
|
before := beforePtrVal.Elem().Interface()
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
afterStdPtrVal := reflect.New(toType)
|
||||||
|
afterStdPtr := afterStdPtrVal.Interface()
|
||||||
|
err = json.Unmarshal(jbIter, afterStdPtr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
|
||||||
|
err, indent(jbIter, " "))
|
||||||
|
}
|
||||||
|
afterIterPtrVal := reflect.New(toType)
|
||||||
|
afterIterPtr := afterIterPtrVal.Interface()
|
||||||
|
err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, afterIterPtr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
|
||||||
|
err, indent(jbIter, " "))
|
||||||
|
}
|
||||||
|
afterStd := afterStdPtrVal.Elem().Interface()
|
||||||
|
afterIter := afterIterPtrVal.Elem().Interface()
|
||||||
|
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 = "> "
|
const indentStr = "> "
|
||||||
|
|
||||||
func fingerprint(obj interface{}) string {
|
func fingerprint(obj interface{}) string {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user