json_test.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package test
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. "testing"
  8. "github.com/davecgh/go-spew/spew"
  9. fuzz "github.com/google/gofuzz"
  10. jsoniter "github.com/json-iterator/go"
  11. )
  12. func Test_Roundtrip(t *testing.T) {
  13. fz := fuzz.New().MaxDepth(10).NilChance(0.3)
  14. for i := 0; i < 100; i++ {
  15. var before typeForTest
  16. fz.Fuzz(&before)
  17. jbStd, err := json.Marshal(before)
  18. if err != nil {
  19. t.Fatalf("failed to marshal with stdlib: %v", err)
  20. }
  21. if len(strings.TrimSpace(string(jbStd))) == 0 {
  22. t.Fatal("stdlib marshal produced empty result and no error")
  23. }
  24. jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before)
  25. if err != nil {
  26. t.Fatalf("failed to marshal with jsoniter: %v", err)
  27. }
  28. if len(strings.TrimSpace(string(jbIter))) == 0 {
  29. t.Fatal("jsoniter marshal produced empty result and no error")
  30. }
  31. if string(jbStd) != string(jbIter) {
  32. t.Fatalf("marshal expected:\n %s\ngot:\n %s\nobj:\n %s",
  33. indent(jbStd, " "), indent(jbIter, " "), dump(before))
  34. }
  35. var afterStd typeForTest
  36. err = json.Unmarshal(jbIter, &afterStd)
  37. if err != nil {
  38. t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n %s",
  39. err, indent(jbIter, " "))
  40. }
  41. var afterIter typeForTest
  42. err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter)
  43. if err != nil {
  44. t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n %s",
  45. err, indent(jbIter, " "))
  46. }
  47. if fingerprint(afterStd) != fingerprint(afterIter) {
  48. t.Fatalf("unmarshal expected:\n %s\ngot:\n %s\nvia:\n %s",
  49. dump(afterStd), dump(afterIter), indent(jbIter, " "))
  50. }
  51. }
  52. }
  53. const indentStr = "> "
  54. func fingerprint(obj interface{}) string {
  55. c := spew.ConfigState{
  56. SortKeys: true,
  57. SpewKeys: true,
  58. }
  59. return c.Sprintf("%v", obj)
  60. }
  61. func dump(obj interface{}) string {
  62. cfg := spew.ConfigState{
  63. Indent: indentStr,
  64. }
  65. return cfg.Sdump(obj)
  66. }
  67. func indent(src []byte, prefix string) string {
  68. var buf bytes.Buffer
  69. err := json.Indent(&buf, src, prefix, indentStr)
  70. if err != nil {
  71. return fmt.Sprintf("!!! %v", err)
  72. }
  73. return buf.String()
  74. }
  75. func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) {
  76. t.ReportAllocs()
  77. t.ResetTimer()
  78. var obj typeForTest
  79. fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
  80. fz.Fuzz(&obj)
  81. for i := 0; i < t.N; i++ {
  82. jb, err := fn(obj)
  83. if err != nil {
  84. t.Fatalf("%s failed to marshal:\n input: %s\n error: %v", name, dump(obj), err)
  85. }
  86. _ = jb
  87. }
  88. }
  89. func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) {
  90. t.ReportAllocs()
  91. t.ResetTimer()
  92. var before typeForTest
  93. fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3)
  94. fz.Fuzz(&before)
  95. jb, err := json.Marshal(before)
  96. if err != nil {
  97. t.Fatalf("failed to marshal: %v", err)
  98. }
  99. for i := 0; i < t.N; i++ {
  100. var after typeForTest
  101. err = fn(jb, &after)
  102. if err != nil {
  103. t.Fatalf("%s failed to unmarshal:\n input: %q\n error: %v", name, string(jb), err)
  104. }
  105. }
  106. }
  107. func BenchmarkStandardMarshal(t *testing.B) {
  108. benchmarkMarshal(t, "stdlib", json.Marshal)
  109. }
  110. func BenchmarkStandardUnmarshal(t *testing.B) {
  111. benchmarkUnmarshal(t, "stdlib", json.Unmarshal)
  112. }
  113. func BenchmarkJSONIterMarshalFastest(t *testing.B) {
  114. benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal)
  115. }
  116. func BenchmarkJSONIterUnmarshalFastest(t *testing.B) {
  117. benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal)
  118. }
  119. func BenchmarkJSONIterMarshalDefault(t *testing.B) {
  120. benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal)
  121. }
  122. func BenchmarkJSONIterUnmarshalDefault(t *testing.B) {
  123. benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal)
  124. }
  125. func BenchmarkJSONIterMarshalCompatible(t *testing.B) {
  126. benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal)
  127. }
  128. func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) {
  129. benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal)
  130. }