text: 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)
  }
  