1
2
3
4
19
20 package json
21
22 import (
23 gojson "encoding/json"
24
25 "fmt"
26 "math"
27 "reflect"
28 "strconv"
29 "strings"
30 "testing"
31 )
32
33 func TestEvaluateTypes(t *testing.T) {
34 testCases := []struct {
35 In string
36 Data interface{}
37 Out string
38 Err bool
39 }{
40
41 {
42 In: `x`,
43 Err: true,
44 },
45 {
46 In: ``,
47 Err: true,
48 },
49
50
51 {
52 In: `null`,
53 Data: nil,
54 Out: `null`,
55 },
56
57 {
58 In: `true`,
59 Data: true,
60 Out: `true`,
61 },
62 {
63 In: `false`,
64 Data: false,
65 Out: `false`,
66 },
67
68
69 {
70 In: `0`,
71 Data: int64(0),
72 Out: `0`,
73 },
74 {
75 In: `-0`,
76 Data: int64(-0),
77 Out: `0`,
78 },
79 {
80 In: `1`,
81 Data: int64(1),
82 Out: `1`,
83 },
84 {
85 In: `2147483647`,
86 Data: int64(math.MaxInt32),
87 Out: `2147483647`,
88 },
89 {
90 In: `-2147483648`,
91 Data: int64(math.MinInt32),
92 Out: `-2147483648`,
93 },
94 {
95 In: `9223372036854775807`,
96 Data: int64(math.MaxInt64),
97 Out: `9223372036854775807`,
98 },
99 {
100 In: `-9223372036854775808`,
101 Data: int64(math.MinInt64),
102 Out: `-9223372036854775808`,
103 },
104
105
106 {
107 In: `9223372036854775808`,
108 Data: float64(9223372036854775808),
109 Out: `9223372036854776000`,
110 },
111 {
112 In: `-9223372036854775809`,
113 Data: float64(math.MinInt64),
114 Out: `-9223372036854776000`,
115 },
116
117
118 {
119 In: `0.0`,
120 Data: float64(0),
121 Out: `0`,
122 },
123 {
124 In: `-0.0`,
125 Data: float64(-0.0),
126 Out: `-0`,
127 },
128 {
129 In: `0.5`,
130 Data: float64(0.5),
131 Out: `0.5`,
132 },
133 {
134 In: `1e3`,
135 Data: float64(1e3),
136 Out: `1000`,
137 },
138 {
139 In: `1.5`,
140 Data: float64(1.5),
141 Out: `1.5`,
142 },
143 {
144 In: `-0.3`,
145 Data: float64(-.3),
146 Out: `-0.3`,
147 },
148 {
149
150 In: `3.40282346638528859811704183484516925440e+38`,
151 Data: float64(math.MaxFloat32),
152 Out: strconv.FormatFloat(math.MaxFloat32, 'g', -1, 64),
153 },
154 {
155
156 In: `1.175494351e-38`,
157 Data: float64(1.175494351e-38),
158 Out: `1.175494351e-38`,
159 },
160 {
161
162 In: `1.401298464324817070923729583289916131280e-45`,
163 Data: float64(math.SmallestNonzeroFloat32),
164 Out: strconv.FormatFloat(math.SmallestNonzeroFloat32, 'g', -1, 64),
165 },
166 {
167
168 In: `1.797693134862315708145274237317043567981e+308`,
169 Data: float64(math.MaxFloat64),
170 Out: strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
171 },
172 {
173
174 In: `2.2250738585072014e-308`,
175 Data: float64(2.2250738585072014e-308),
176 Out: `2.2250738585072014e-308`,
177 },
178
179 {
180
181 In: `4.940656458412465441765687928682213723651e-324`,
182 Data: float64(math.SmallestNonzeroFloat64),
183 Out: strconv.FormatFloat(math.SmallestNonzeroFloat64, 'g', -1, 64),
184 },
185
186 {
187
188 In: `1.7976931348623159e+308`,
189 Err: true,
190 },
191
192
193 {
194 In: `""`,
195 Data: string(""),
196 Out: `""`,
197 },
198 {
199 In: `"0"`,
200 Data: string("0"),
201 Out: `"0"`,
202 },
203 {
204 In: `"A"`,
205 Data: string("A"),
206 Out: `"A"`,
207 },
208 {
209 In: `"Iñtërnâtiônàlizætiøn"`,
210 Data: string("Iñtërnâtiônàlizætiøn"),
211 Out: `"Iñtërnâtiônàlizætiøn"`,
212 },
213
214
215 {
216 In: `[]`,
217 Data: []interface{}{},
218 Out: `[]`,
219 },
220 {
221 In: `[` + strings.Join([]string{
222 `null`,
223 `true`,
224 `false`,
225 `0`,
226 `9223372036854775807`,
227 `0.0`,
228 `0.5`,
229 `1.0`,
230 `1.797693134862315708145274237317043567981e+308`,
231 `"0"`,
232 `"A"`,
233 `"Iñtërnâtiônàlizætiøn"`,
234 `[null,true,1,1.0,1.5]`,
235 `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
236 }, ",") + `]`,
237 Data: []interface{}{
238 nil,
239 true,
240 false,
241 int64(0),
242 int64(math.MaxInt64),
243 float64(0.0),
244 float64(0.5),
245 float64(1.0),
246 float64(math.MaxFloat64),
247 string("0"),
248 string("A"),
249 string("Iñtërnâtiônàlizætiøn"),
250 []interface{}{nil, true, int64(1), float64(1.0), float64(1.5)},
251 map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
252 },
253 Out: `[` + strings.Join([]string{
254 `null`,
255 `true`,
256 `false`,
257 `0`,
258 `9223372036854775807`,
259 `0`,
260 `0.5`,
261 `1`,
262 strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
263 `"0"`,
264 `"A"`,
265 `"Iñtërnâtiônàlizætiøn"`,
266 `[null,true,1,1,1.5]`,
267 `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`,
268 }, ",") + `]`,
269 },
270
271
272 {
273 In: `{}`,
274 Data: map[string]interface{}{},
275 Out: `{}`,
276 },
277 {
278 In: `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
279 Data: map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
280 Out: `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`,
281 },
282 }
283
284 for i, tc := range testCases {
285 t.Run(fmt.Sprintf("%d_map", i), func(t *testing.T) {
286
287 inputJSON := fmt.Sprintf(`{"data":%s}`, tc.In)
288 expectedJSON := fmt.Sprintf(`{"data":%s}`, tc.Out)
289 m := map[string]interface{}{}
290 err := Unmarshal([]byte(inputJSON), &m)
291 if tc.Err && err != nil {
292
293 return
294 }
295 if err != nil {
296 t.Fatalf("%s: error decoding: %v", tc.In, err)
297 }
298 if tc.Err {
299 t.Fatalf("%s: expected error, got none", tc.In)
300 }
301 data, ok := m["data"]
302 if !ok {
303 t.Fatalf("%s: decoded object missing data key: %#v", tc.In, m)
304 }
305 if !reflect.DeepEqual(tc.Data, data) {
306 t.Fatalf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data))
307 }
308
309 outputJSON, err := Marshal(m)
310 if err != nil {
311 t.Fatalf("%s: error encoding: %v", tc.In, err)
312 }
313
314 if expectedJSON != string(outputJSON) {
315 t.Fatalf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON))
316 }
317 })
318
319 t.Run(fmt.Sprintf("%d_slice", i), func(t *testing.T) {
320
321 inputJSON := fmt.Sprintf(`[0,%s]`, tc.In)
322 expectedJSON := fmt.Sprintf(`[0,%s]`, tc.Out)
323 m := []interface{}{}
324 err := Unmarshal([]byte(inputJSON), &m)
325 if tc.Err && err != nil {
326
327 return
328 }
329 if err != nil {
330 t.Fatalf("%s: error decoding: %v", tc.In, err)
331 }
332 if tc.Err {
333 t.Fatalf("%s: expected error, got none", tc.In)
334 }
335 if len(m) != 2 {
336 t.Fatalf("%s: decoded object wasn't the right length: %#v", tc.In, m)
337 }
338 data := m[1]
339 if !reflect.DeepEqual(tc.Data, data) {
340 t.Fatalf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data))
341 }
342
343 outputJSON, err := Marshal(m)
344 if err != nil {
345 t.Fatalf("%s: error encoding: %v", tc.In, err)
346 }
347
348 if expectedJSON != string(outputJSON) {
349 t.Fatalf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON))
350 }
351 })
352
353 t.Run(fmt.Sprintf("%d_raw", i), func(t *testing.T) {
354
355 inputJSON := tc.In
356 expectedJSON := tc.Out
357 var m interface{}
358 err := Unmarshal([]byte(inputJSON), &m)
359 if tc.Err && err != nil {
360
361 return
362 }
363 if err != nil {
364 t.Fatalf("%s: error decoding: %v", tc.In, err)
365 }
366 if tc.Err {
367 t.Fatalf("%s: expected error, got none", tc.In)
368 }
369 data := m
370 if !reflect.DeepEqual(tc.Data, data) {
371 t.Fatalf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data))
372 }
373
374 outputJSON, err := Marshal(m)
375 if err != nil {
376 t.Fatalf("%s: error encoding: %v", tc.In, err)
377 }
378
379 if expectedJSON != string(outputJSON) {
380 t.Fatalf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON))
381 }
382 })
383 }
384 }
385
386 func TestUnmarshalNil(t *testing.T) {
387 {
388 var v *interface{}
389 err := Unmarshal([]byte(`0`), v)
390 goerr := gojson.Unmarshal([]byte(`0`), v)
391 if err == nil || goerr == nil || err.Error() != goerr.Error() {
392 t.Fatalf("expected error matching stdlib, got %v, %v", err, goerr)
393 } else {
394 t.Log(err)
395 }
396 }
397
398 {
399 var v *[]interface{}
400 err := Unmarshal([]byte(`[]`), v)
401 goerr := gojson.Unmarshal([]byte(`[]`), v)
402 if err == nil || goerr == nil || err.Error() != goerr.Error() {
403 t.Fatalf("expected error matching stdlib, got %v, %v", err, goerr)
404 } else {
405 t.Log(err)
406 }
407 }
408
409 {
410 var v *map[string]interface{}
411 err := Unmarshal([]byte(`{}`), v)
412 goerr := gojson.Unmarshal([]byte(`{}`), v)
413 if err == nil || goerr == nil || err.Error() != goerr.Error() {
414 t.Fatalf("expected error matching stdlib, got %v, %v", err, goerr)
415 } else {
416 t.Log(err)
417 }
418 }
419 }
420
View as plain text