1 package tests
2
3 import (
4 "bytes"
5 "encoding/json"
6 "net/http/httptest"
7 "reflect"
8 "testing"
9
10 "github.com/mailru/easyjson"
11 "github.com/mailru/easyjson/jwriter"
12 )
13
14 type testType interface {
15 json.Marshaler
16 json.Unmarshaler
17 }
18
19 var testCases = []struct {
20 Decoded testType
21 Encoded string
22 }{
23 {&primitiveTypesValue, primitiveTypesString},
24 {&namedPrimitiveTypesValue, namedPrimitiveTypesString},
25 {&structsValue, structsString},
26 {&omitEmptyValue, omitEmptyString},
27 {&snakeStructValue, snakeStructString},
28 {&omitEmptyDefaultValue, omitEmptyDefaultString},
29 {&optsValue, optsString},
30 {&rawValue, rawString},
31 {&stdMarshalerValue, stdMarshalerString},
32 {&userMarshalerValue, userMarshalerString},
33 {&unexportedStructValue, unexportedStructString},
34 {&excludedFieldValue, excludedFieldString},
35 {&sliceValue, sliceString},
36 {&arrayValue, arrayString},
37 {&mapsValue, mapsString},
38 {&deepNestValue, deepNestString},
39 {&IntsValue, IntsString},
40 {&mapStringStringValue, mapStringStringString},
41 {&namedTypeValue, namedTypeValueString},
42 {&customMapKeyTypeValue, customMapKeyTypeValueString},
43 {&embeddedTypeValue, embeddedTypeValueString},
44 {&mapMyIntStringValue, mapMyIntStringValueString},
45 {&mapIntStringValue, mapIntStringValueString},
46 {&mapInt32StringValue, mapInt32StringValueString},
47 {&mapInt64StringValue, mapInt64StringValueString},
48 {&mapUintStringValue, mapUintStringValueString},
49 {&mapUint32StringValue, mapUint32StringValueString},
50 {&mapUint64StringValue, mapUint64StringValueString},
51 {&mapUintptrStringValue, mapUintptrStringValueString},
52 {&intKeyedMapStructValue, intKeyedMapStructValueString},
53 {&intArrayStructValue, intArrayStructValueString},
54 {&myUInt8SliceValue, myUInt8SliceString},
55 {&myUInt8ArrayValue, myUInt8ArrayString},
56 {&mapWithEncodingMarshaler, mapWithEncodingMarshalerString},
57 {&myGenDeclaredValue, myGenDeclaredString},
58 {&myGenDeclaredWithCommentValue, myGenDeclaredWithCommentString},
59 {&myTypeDeclaredValue, myTypeDeclaredString},
60 {&myTypeNotSkippedValue, myTypeNotSkippedString},
61 {&intern, internString},
62 }
63
64 func TestMarshal(t *testing.T) {
65 for i, test := range testCases {
66 data, err := test.Decoded.MarshalJSON()
67 if err != nil {
68 t.Errorf("[%d, %T] MarshalJSON() error: %v", i, test.Decoded, err)
69 }
70
71 got := string(data)
72 if got != test.Encoded {
73 t.Errorf("[%d, %T] MarshalJSON(): got \n%v\n\t\t want \n%v", i, test.Decoded, got, test.Encoded)
74 }
75 }
76 }
77
78 func TestUnmarshal(t *testing.T) {
79 for i, test := range testCases {
80 v1 := reflect.New(reflect.TypeOf(test.Decoded).Elem()).Interface()
81 v := v1.(testType)
82
83 err := v.UnmarshalJSON([]byte(test.Encoded))
84 if err != nil {
85 t.Errorf("[%d, %T] UnmarshalJSON() error: %v", i, test.Decoded, err)
86 }
87
88 if !reflect.DeepEqual(v, test.Decoded) {
89 t.Errorf("[%d, %T] UnmarshalJSON(): got \n%+v\n\t\t want \n%+v", i, test.Decoded, v, test.Decoded)
90 }
91 }
92 }
93
94 func TestRawMessageSTD(t *testing.T) {
95 type T struct {
96 F easyjson.RawMessage
97 Fnil easyjson.RawMessage
98 }
99
100 val := T{F: easyjson.RawMessage([]byte(`"test"`))}
101 str := `{"F":"test","Fnil":null}`
102
103 data, err := json.Marshal(val)
104 if err != nil {
105 t.Errorf("json.Marshal() error: %v", err)
106 }
107 got := string(data)
108 if got != str {
109 t.Errorf("json.Marshal() = %v; want %v", got, str)
110 }
111
112 wantV := T{F: easyjson.RawMessage([]byte(`"test"`)), Fnil: easyjson.RawMessage([]byte("null"))}
113 var gotV T
114
115 err = json.Unmarshal([]byte(str), &gotV)
116 if err != nil {
117 t.Errorf("json.Unmarshal() error: %v", err)
118 }
119 if !reflect.DeepEqual(gotV, wantV) {
120 t.Errorf("json.Unmarshal() = %v; want %v", gotV, wantV)
121 }
122 }
123
124 func TestParseNull(t *testing.T) {
125 var got, want SubStruct
126 if err := easyjson.Unmarshal([]byte("null"), &got); err != nil {
127 t.Errorf("Unmarshal() error: %v", err)
128 }
129
130 if !reflect.DeepEqual(got, want) {
131 t.Errorf("Unmarshal() = %+v; want %+v", got, want)
132 }
133 }
134
135 var testSpecialCases = []struct {
136 EncodedString string
137 Value string
138 }{
139 {`"Username \u003cuser@example.com\u003e"`, `Username <user@example.com>`},
140 {`"Username\ufffd"`, "Username\xc5"},
141 {`"тестzтест"`, "тестzтест"},
142 {`"тест\ufffdтест"`, "тест\xc5тест"},
143 {`"绿茶"`, "绿茶"},
144 {`"绿\ufffd茶"`, "绿\xc5茶"},
145 {`"тест\u2028"`, "тест\xE2\x80\xA8"},
146 {`"\\\r\n\t\""`, "\\\r\n\t\""},
147 {`"text\\\""`, "text\\\""},
148 {`"ü"`, "ü"},
149 }
150
151 func TestSpecialCases(t *testing.T) {
152 for i, test := range testSpecialCases {
153 w := jwriter.Writer{}
154 w.String(test.Value)
155 got := string(w.Buffer.BuildBytes())
156 if got != test.EncodedString {
157 t.Errorf("[%d] Encoded() = %+v; want %+v", i, got, test.EncodedString)
158 }
159 }
160 }
161
162 func TestOverflowArray(t *testing.T) {
163 var a Arrays
164 err := easyjson.Unmarshal([]byte(arrayOverflowString), &a)
165 if err != nil {
166 t.Error(err)
167 }
168 if a != arrayValue {
169 t.Errorf("Unmarshal(%v) = %+v; want %+v", arrayOverflowString, a, arrayValue)
170 }
171 }
172
173 func TestUnderflowArray(t *testing.T) {
174 var a Arrays
175 err := easyjson.Unmarshal([]byte(arrayUnderflowString), &a)
176 if err != nil {
177 t.Error(err)
178 }
179 if a != arrayUnderflowValue {
180 t.Errorf("Unmarshal(%v) = %+v; want %+v", arrayUnderflowString, a, arrayUnderflowValue)
181 }
182 }
183
184 func TestEncodingFlags(t *testing.T) {
185 for i, test := range []struct {
186 Flags jwriter.Flags
187 In easyjson.Marshaler
188 Want string
189 }{
190 {0, EncodingFlagsTestMap{}, `{"F":null}`},
191 {0, EncodingFlagsTestSlice{}, `{"F":null}`},
192 {jwriter.NilMapAsEmpty, EncodingFlagsTestMap{}, `{"F":{}}`},
193 {jwriter.NilSliceAsEmpty, EncodingFlagsTestSlice{}, `{"F":[]}`},
194 } {
195 w := &jwriter.Writer{Flags: test.Flags}
196 test.In.MarshalEasyJSON(w)
197
198 data, err := w.BuildBytes()
199 if err != nil {
200 t.Errorf("[%v] easyjson.Marshal(%+v) error: %v", i, test.In, err)
201 }
202
203 v := string(data)
204 if v != test.Want {
205 t.Errorf("[%v] easyjson.Marshal(%+v) = %v; want %v", i, test.In, v, test.Want)
206 }
207 }
208
209 }
210
211 func TestNestedEasyJsonMarshal(t *testing.T) {
212 n := map[string]*NestedEasyMarshaler{
213 "Value": {},
214 "Slice1": {},
215 "Slice2": {},
216 "Map1": {},
217 "Map2": {},
218 }
219
220 ni := NestedInterfaces{
221 Value: n["Value"],
222 Slice: []interface{}{n["Slice1"], n["Slice2"]},
223 Map: map[string]interface{}{"1": n["Map1"], "2": n["Map2"]},
224 }
225 easyjson.Marshal(ni)
226
227 for k, v := range n {
228 if !v.EasilyMarshaled {
229 t.Errorf("Nested interface %s wasn't easily marshaled", k)
230 }
231 }
232 }
233
234 func TestNestedMarshaler(t *testing.T) {
235 s := NestedMarshaler{
236 Value: &StructWithMarshaler{
237 Value: 5,
238 },
239 Value2: 10,
240 }
241
242 data, err := s.MarshalJSON()
243 if err != nil {
244 t.Errorf("Can't marshal NestedMarshaler: %s", err)
245 }
246
247 s2 := NestedMarshaler {
248 Value: &StructWithMarshaler{},
249 }
250
251 err = s2.UnmarshalJSON(data)
252 if err != nil {
253 t.Errorf("Can't unmarshal NestedMarshaler: %s", err)
254 }
255
256 if !reflect.DeepEqual(s2, s) {
257 t.Errorf("easyjson.Unmarshal() = %#v; want %#v", s2, s)
258 }
259 }
260
261 func TestUnmarshalStructWithEmbeddedPtrStruct(t *testing.T) {
262 var s = StructWithInterface{Field2: &EmbeddedStruct{}}
263 var err error
264 err = easyjson.Unmarshal([]byte(structWithInterfaceString), &s)
265 if err != nil {
266 t.Errorf("easyjson.Unmarshal() error: %v", err)
267 }
268 if !reflect.DeepEqual(s, structWithInterfaceValueFilled) {
269 t.Errorf("easyjson.Unmarshal() = %#v; want %#v", s, structWithInterfaceValueFilled)
270 }
271 }
272
273 func TestDisallowUnknown(t *testing.T) {
274 var d DisallowUnknown
275 err := easyjson.Unmarshal([]byte(disallowUnknownString), &d)
276 if err == nil {
277 t.Error("want error, got nil")
278 }
279 }
280
281 var testNotGeneratedTypeCases = []interface{}{
282 TypeNotDeclared{},
283 TypeSkipped{},
284 }
285
286 func TestMethodsNoGenerated(t *testing.T) {
287 var ok bool
288 for i, instance := range testNotGeneratedTypeCases {
289 _, ok = instance.(json.Marshaler)
290 if ok {
291 t.Errorf("[%d, %T] Unexpected MarshalJSON()", i, instance)
292 }
293
294 _, ok = instance.(json.Unmarshaler)
295 if ok {
296 t.Errorf("[%d, %T] Unexpected Unmarshaler()", i, instance)
297 }
298 }
299 }
300
301 func TestNil(t *testing.T) {
302 var p *PrimitiveTypes
303
304 data, err := easyjson.Marshal(p)
305 if err != nil {
306 t.Errorf("easyjson.Marshal() error: %v", err)
307 }
308 if string(data) != "null" {
309 t.Errorf("Wanted null, got %q", string(data))
310 }
311
312 var b bytes.Buffer
313 if n, err := easyjson.MarshalToWriter(p, &b); err != nil || n != 4 {
314 t.Errorf("easyjson.MarshalToWriter() error: %v, written %d", err, n)
315 }
316
317 if s := b.String(); s != "null" {
318 t.Errorf("Wanted null, got %q", s)
319 }
320
321 w := httptest.NewRecorder()
322 started, written, err := easyjson.MarshalToHTTPResponseWriter(p, w)
323 if !started || written != 4 || err != nil {
324 t.Errorf("easyjson.MarshalToHTTPResponseWriter() error: %v, written %d, started %t",
325 err, written, started)
326 }
327
328 if s := w.Body.String(); s != "null" {
329 t.Errorf("Wanted null, got %q", s)
330 }
331 }
332
View as plain text