json_test.go 3.1 KB

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