| package test |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "github.com/davecgh/go-spew/spew" |
| "github.com/google/gofuzz" |
| "github.com/json-iterator/go" |
| "reflect" |
| "strings" |
| "testing" |
| ) |
| |
| var testCases []interface{} |
| var asymmetricTestCases [][2]interface{} |
| |
| type selectedSymmetricCase struct { |
| testCase interface{} |
| } |
| |
| func Test_symmetric(t *testing.T) { |
| for _, testCase := range testCases { |
| selectedSymmetricCase, found := testCase.(selectedSymmetricCase) |
| if found { |
| testCases = []interface{}{selectedSymmetricCase.testCase} |
| break |
| } |
| } |
| for _, testCase := range testCases { |
| valType := reflect.TypeOf(testCase).Elem() |
| t.Run(valType.String(), func(t *testing.T) { |
| fz := fuzz.New().MaxDepth(10).NilChance(0.3) |
| for i := 0; i < 100; i++ { |
| beforePtrVal := reflect.New(valType) |
| 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(valType) |
| 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(valType) |
| 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, " ")) |
| } |
| } |
| }) |
| } |
| } |
| |
| 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 = "> " |
| |
| 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() |
| } |