...
1
16
17 package jsontesting
18
19 import (
20 "encoding/json"
21 "fmt"
22 "reflect"
23 "strings"
24
25 kjson "sigs.k8s.io/json"
26
27 "github.com/go-openapi/jsonreference"
28 "github.com/google/go-cmp/cmp"
29 "github.com/google/go-cmp/cmp/cmpopts"
30 )
31
32 func JsonCompare(got, want []byte) error {
33 if d := cmp.Diff(got, want, cmp.Transformer("JSONBytes", func(in []byte) (out interface{}) {
34 if strictErrors, err := kjson.UnmarshalStrict(in, &out); strictErrors != nil || err != nil {
35 return in
36 }
37 return out
38 })); d != "" {
39 return fmt.Errorf("JSON mismatch (-got +want):\n%s", d)
40 }
41 return nil
42 }
43
44 type RoundTripTestCase struct {
45 Name string
46 JSON string
47 Object json.Marshaler
48
49
50
51 ExpectedMarshalError string
52
53
54
55 ExpectedUnmarshalError string
56 }
57
58 type MarshalerUnmarshaler interface {
59 json.Unmarshaler
60 json.Marshaler
61 }
62
63 func (t RoundTripTestCase) RoundTripTest(example MarshalerUnmarshaler) error {
64 var jsonBytes []byte
65 var err error
66
67
68
69 expectError := func(e error, name string, expected string) (testFinished bool, err error) {
70 if len(expected) > 0 {
71 if e == nil || !strings.Contains(e.Error(), expected) {
72 return true, fmt.Errorf("expected %v error containing substring: '%s'. but got actual error '%v'", name, expected, e)
73 }
74
75
76
77
78 return true, nil
79 } else if e != nil {
80 return true, fmt.Errorf("unexpected %v error: %w", name, e)
81 }
82
83 return false, nil
84 }
85
86
87
88 if len(t.JSON) == 0 {
89 jsonBytes, err = json.Marshal(t.Object)
90 if testFinished, err := expectError(err, "marshal", t.ExpectedMarshalError); testFinished {
91 return err
92 }
93 } else {
94 jsonBytes = []byte(t.JSON)
95 }
96
97 err = example.UnmarshalJSON(jsonBytes)
98 if testFinished, err := expectError(err, "unmarshal", t.ExpectedUnmarshalError); testFinished {
99 return err
100 }
101
102 if t.Object != nil && !reflect.DeepEqual(t.Object, example) {
103 return fmt.Errorf("test case expected to unmarshal to specific value: %v", cmp.Diff(t.Object, example, cmpopts.IgnoreUnexported(jsonreference.Ref{})))
104 }
105
106 reEncoded, err := json.Marshal(example)
107 if err != nil {
108 return fmt.Errorf("failed to marshal decoded value: %w", err)
109 }
110
111
112
113 if testFinished, err := expectError(err, "marshal", t.ExpectedMarshalError); testFinished {
114 return err
115 }
116
117
118 var expected map[string]interface{}
119 var actual map[string]interface{}
120
121 if err = json.Unmarshal(jsonBytes, &expected); err != nil {
122 return fmt.Errorf("failed to unmarshal test json: %w", err)
123 }
124
125 if err = json.Unmarshal(reEncoded, &actual); err != nil {
126 return fmt.Errorf("failed to unmarshal actual data: %w", err)
127 }
128
129 if !reflect.DeepEqual(expected, actual) {
130 return fmt.Errorf("expected equal values: %v", cmp.Diff(expected, actual))
131 }
132
133 return nil
134 }
135
View as plain text