1
16
17 package decoder
18
19 import (
20 `encoding/json`
21 `runtime`
22 `runtime/debug`
23 `strings`
24 `sync`
25 `testing`
26 `time`
27 `reflect`
28
29 `github.com/bytedance/sonic/internal/rt`
30 `github.com/davecgh/go-spew/spew`
31 `github.com/stretchr/testify/assert`
32 `github.com/stretchr/testify/require`
33 )
34
35 func TestMain(m *testing.M) {
36 go func () {
37 if !debugAsyncGC {
38 return
39 }
40 println("Begin GC looping...")
41 for {
42 runtime.GC()
43 debug.FreeOSMemory()
44 }
45 println("stop GC looping!")
46 }()
47 time.Sleep(time.Millisecond)
48 m.Run()
49 }
50
51 func TestGC(t *testing.T) {
52 if debugSyncGC {
53 return
54 }
55 var w interface{}
56 out, err := decode(TwitterJson, &w, true)
57 if err != nil {
58 t.Fatal(err)
59 }
60 if out != len(TwitterJson) {
61 t.Fatal(out)
62 }
63 wg := &sync.WaitGroup{}
64 N := 10000
65 for i:=0; i<N; i++ {
66 wg.Add(1)
67 go func (wg *sync.WaitGroup) {
68 defer wg.Done()
69 var w interface{}
70 out, err := decode(TwitterJson, &w, true)
71 if err != nil {
72 t.Fatal(err)
73 }
74 if out != len(TwitterJson) {
75 t.Fatal(out)
76 }
77 runtime.GC()
78 }(wg)
79 }
80 wg.Wait()
81 }
82
83 var _BindingValue TwitterStruct
84
85 func init() {
86 _ = json.Unmarshal([]byte(TwitterJson), &_BindingValue)
87 }
88
89
90 func TestSkipMismatchTypeError(t *testing.T) {
91 t.Run("struct", func(t *testing.T) {
92 println("TestSkipError")
93 type skiptype struct {
94 A int `json:"a"`
95 B string `json:"b"`
96
97 Pass *int `json:"pass"`
98
99 C struct{
100
101 Pass4 interface{} `json:"pass4"`
102
103 D struct{
104 E float32 `json:"e"`
105 } `json:"d"`
106
107 Pass2 int `json:"pass2"`
108
109 } `json:"c"`
110
111 E bool `json:"e"`
112 F []int `json:"f"`
113 G map[string]int `json:"g"`
114 H bool `json:"h,string"`
115
116 Pass3 int `json:"pass2"`
117
118 I json.Number `json:"i"`
119 }
120 var obj, obj2 = &skiptype{Pass:new(int)}, &skiptype{Pass:new(int)}
121 var data = `{"a":"","b":1,"c":{"d":true,"pass2":1,"pass4":true},"e":{},"f":"","g":[],"pass":null,"h":"1.0","i":true,"pass3":1}`
122 d := NewDecoder(data)
123 err := d.Decode(obj)
124 err2 := json.Unmarshal([]byte(data), obj2)
125 println(err2.Error())
126 assert.Equal(t, err2 == nil, err == nil)
127
128 assert.Equal(t, obj2, obj)
129 if te, ok := err.(*MismatchTypeError); ok {
130 assert.Equal(t, reflect.TypeOf(obj.I), te.Type)
131 assert.Equal(t, strings.Index(data, `"i":t`)+4, te.Pos)
132 println(err.Error())
133 } else {
134 t.Fatal("invalid error")
135 }
136 })
137 t.Run("short array", func(t *testing.T) {
138 var obj, obj2 = &[]int{}, &[]int{}
139 var data = `[""]`
140 d := NewDecoder(data)
141 err := d.Decode(obj)
142 err2 := json.Unmarshal([]byte(data), obj2)
143
144 assert.Equal(t, err2 == nil, err == nil)
145
146 assert.Equal(t, obj2, obj)
147 })
148
149 t.Run("int ", func(t *testing.T) {
150 var obj int = 123
151 var obj2 int = 123
152 var data = `[""]`
153 d := NewDecoder(data)
154 err := d.Decode(&obj)
155 err2 := json.Unmarshal([]byte(data), &obj2)
156 println(err.Error(), obj, obj2)
157 assert.Equal(t, err2 == nil, err == nil)
158
159 assert.Equal(t, obj2, obj)
160 })
161
162 t.Run("array", func(t *testing.T) {
163 var obj, obj2 = &[]int{}, &[]int{}
164 var data = `["",true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true]`
165 d := NewDecoder(data)
166 err := d.Decode(obj)
167 err2 := json.Unmarshal([]byte(data), obj2)
168
169 assert.Equal(t, err2 == nil, err == nil)
170
171 assert.Equal(t, obj2, obj)
172 })
173
174 t.Run("map", func(t *testing.T) {
175 var obj, obj2 = &map[int]int{}, &map[int]int{}
176 var data = `{"true" : { },"1":1,"2" : true,"3":3}`
177 d := NewDecoder(data)
178 err := d.Decode(obj)
179 err2 := json.Unmarshal([]byte(data), obj2)
180 assert.Equal(t, err2 == nil, err == nil)
181
182 assert.Equal(t, obj2, obj)
183 })
184 t.Run("map error", func(t *testing.T) {
185 var obj, obj2 = &map[int]int{}, &map[int]int{}
186 var data = `{"true" : { ],"1":1,"2" : true,"3":3}`
187 d := NewDecoder(data)
188 err := d.Decode(obj)
189 err2 := json.Unmarshal([]byte(data), obj2)
190 println(err.Error())
191 println(err2.Error())
192 assert.Equal(t, err2 == nil, err == nil)
193
194
195 })
196 }
197
198 func TestDecodeCorrupt(t *testing.T) {
199 var ds = []string{
200 `{,}`,
201 `{,"a"}`,
202 `{"a":}`,
203 `{"a":1,}`,
204 `{"a":1,"b"}`,
205 `{"a":1,"b":}`,
206 `{,"a":1 "b":2}`,
207 `{"a",:1 "b":2}`,
208 `{"a":,1 "b":2}`,
209 `{"a":1 "b",:2}`,
210 `{"a":1 "b":,2}`,
211 `{"a":1 "b":2,}`,
212 `{"a":1 "b":2}`,
213 `[,]`,
214 `[,1]`,
215 `[1,]`,
216 `[,1,2]`,
217 `[1,2,]`,
218 }
219 for _, d := range ds {
220 var o interface{}
221 _, err := decode(d, &o, false)
222 if err == nil {
223 t.Fatalf("%#v", d)
224 }
225 if !strings.Contains(err.Error(), "invalid char"){
226 t.Fatal(err.Error())
227 }
228 }
229 }
230
231 func decode(s string, v interface{}, copy bool) (int, error) {
232 d := NewDecoder(s)
233 if copy {
234 d.CopyString()
235 }
236 err := d.Decode(v)
237 if err != nil {
238 return 0, err
239 }
240 return d.i, err
241 }
242
243 func TestCopyString(t *testing.T) {
244 var data []byte
245 var dc *Decoder
246 var err error
247 data = []byte(`{"A":"0","B":"1"}`)
248 dc = NewDecoder(rt.Mem2Str(data))
249 dc.UseNumber()
250 dc.CopyString()
251 var obj struct{
252 A string
253 B string
254 }
255 err = dc.Decode(&obj)
256 if err != nil {
257 t.Fatal(err)
258 }
259 data[6] = '1'
260 if obj.A != "0" {
261 t.Fatal(obj)
262 }
263 data[14] = '0'
264 if obj.B != "1" {
265 t.Fatal(obj)
266 }
267
268 data = []byte(`{"A":"0","B":"1"}`)
269 dc = NewDecoder(rt.Mem2Str(data))
270 dc.UseNumber()
271 err = dc.Decode(&obj)
272 if err != nil {
273 t.Fatal(err)
274 }
275 data[6] = '1'
276 if obj.A != "1" {
277 t.Fatal(obj)
278 }
279 data[14] = '0'
280 if obj.B != "0" {
281 t.Fatal(obj)
282 }
283
284 data = []byte(`{"A":"0","B":"1"}`)
285 dc = NewDecoder(rt.Mem2Str(data))
286 dc.UseNumber()
287 dc.CopyString()
288 m := map[string]interface{}{}
289 err = dc.Decode(&m)
290 if err != nil {
291 t.Fatal(err)
292 }
293 data[2] = 'C'
294 data[6] = '1'
295 if m["A"] != "0" {
296 t.Fatal(m)
297 }
298 data[10] = 'D'
299 data[14] = '0'
300 if m["B"] != "1" {
301 t.Fatal(m)
302 }
303
304 data = []byte(`{"A":"0","B":"1"}`)
305 dc = NewDecoder(rt.Mem2Str(data))
306 dc.UseNumber()
307 m = map[string]interface{}{}
308 err = dc.Decode(&m)
309 if err != nil {
310 t.Fatal(err)
311 }
312 data[6] = '1'
313 if m["A"] != "1" {
314 t.Fatal(m)
315 }
316 data[14] = '0'
317 if m["B"] != "0" {
318 t.Fatal(m)
319 }
320
321 data = []byte(`{"A":"0","B":"1"}`)
322 dc = NewDecoder(rt.Mem2Str(data))
323 dc.UseNumber()
324 dc.CopyString()
325 var x interface{}
326 err = dc.Decode(&x)
327 if err != nil {
328 t.Fatal(err)
329 }
330 data[2] = 'C'
331 data[6] = '1'
332 m = x.(map[string]interface{})
333 if m["A"] != "0" {
334 t.Fatal(m)
335 }
336 data[10] = 'D'
337 data[14] = '0'
338 if m["B"] != "1" {
339 t.Fatal(m)
340 }
341
342 data = []byte(`{"A":"0","B":"1"}`)
343 dc = NewDecoder(rt.Mem2Str(data))
344 dc.UseNumber()
345 var y interface{}
346 err = dc.Decode(&y)
347 if err != nil {
348 t.Fatal(err)
349 }
350 m = y.(map[string]interface{})
351 data[6] = '1'
352 if m["A"] != "1" {
353 t.Fatal(m)
354 }
355 data[14] = '0'
356 if m["B"] != "0" {
357 t.Fatal(m)
358 }
359 }
360
361 func TestDecoder_Basic(t *testing.T) {
362 var v int
363 pos, err := decode("12345", &v, false)
364 assert.NoError(t, err)
365 assert.Equal(t, 5, pos)
366 assert.Equal(t, 12345, v)
367 }
368
369 func TestDecoder_Generic(t *testing.T) {
370 var v interface{}
371 pos, err := decode(TwitterJson, &v, false)
372 assert.NoError(t, err)
373 assert.Equal(t, len(TwitterJson), pos)
374 }
375
376 func TestDecoder_Binding(t *testing.T) {
377 var v TwitterStruct
378 pos, err := decode(TwitterJson, &v, false)
379 assert.NoError(t, err)
380 assert.Equal(t, len(TwitterJson), pos)
381 assert.Equal(t, _BindingValue, v, 0)
382 spew.Dump(v)
383 }
384
385 func TestDecoder_SetOption(t *testing.T) {
386 var v interface{}
387 d := NewDecoder("123")
388 d.SetOptions(OptionUseInt64)
389 err := d.Decode(&v)
390 assert.NoError(t, err)
391 assert.Equal(t, v, int64(123))
392 }
393
394 func TestDecoder_MapWithIndirectElement(t *testing.T) {
395 var v map[string]struct { A [129]byte }
396 _, err := decode(`{"":{"A":[1,2,3,4,5]}}`, &v, false)
397 if x, ok := err.(SyntaxError); ok {
398 println(x.Description())
399 }
400 require.NoError(t, err)
401 assert.Equal(t, [129]byte{1, 2, 3, 4, 5}, v[""].A)
402 }
403
404 func BenchmarkDecoder_Generic_Sonic(b *testing.B) {
405 var w interface{}
406 _, _ = decode(TwitterJson, &w, true)
407 b.SetBytes(int64(len(TwitterJson)))
408 b.ResetTimer()
409 for i := 0; i < b.N; i++ {
410 var v interface{}
411 _, _ = decode(TwitterJson, &v, true)
412 }
413 }
414
415 func BenchmarkDecoder_Generic_Sonic_Fast(b *testing.B) {
416 var w interface{}
417 _, _ = decode(TwitterJson, &w, false)
418 b.SetBytes(int64(len(TwitterJson)))
419 b.ResetTimer()
420 for i := 0; i < b.N; i++ {
421 var v interface{}
422 _, _ = decode(TwitterJson, &v, false)
423 }
424 }
425
426 func BenchmarkDecoder_Generic_StdLib(b *testing.B) {
427 var w interface{}
428 m := []byte(TwitterJson)
429 _ = json.Unmarshal(m, &w)
430 b.SetBytes(int64(len(TwitterJson)))
431 b.ResetTimer()
432 for i := 0; i < b.N; i++ {
433 var v interface{}
434 _ = json.Unmarshal(m, &v)
435 }
436 }
437
438 func BenchmarkDecoder_Binding_Sonic(b *testing.B) {
439 var w TwitterStruct
440 _, _ = decode(TwitterJson, &w, true)
441 b.SetBytes(int64(len(TwitterJson)))
442 b.ResetTimer()
443 for i := 0; i < b.N; i++ {
444 var v TwitterStruct
445 _, _ = decode(TwitterJson, &v, true)
446 }
447 }
448
449 func BenchmarkDecoder_Binding_Sonic_Fast(b *testing.B) {
450 var w TwitterStruct
451 _, _ = decode(TwitterJson, &w, false)
452 b.SetBytes(int64(len(TwitterJson)))
453 b.ResetTimer()
454 for i := 0; i < b.N; i++ {
455 var v TwitterStruct
456 _, _ = decode(TwitterJson, &v, false)
457 }
458 }
459
460 func BenchmarkDecoder_Binding_StdLib(b *testing.B) {
461 var w TwitterStruct
462 m := []byte(TwitterJson)
463 _ = json.Unmarshal(m, &w)
464 b.SetBytes(int64(len(TwitterJson)))
465 b.ResetTimer()
466 for i := 0; i < b.N; i++ {
467 var v TwitterStruct
468 _ = json.Unmarshal(m, &v)
469 }
470 }
471
472 func BenchmarkDecoder_Parallel_Generic_Sonic(b *testing.B) {
473 var w interface{}
474 _, _ = decode(TwitterJson, &w, true)
475 b.SetBytes(int64(len(TwitterJson)))
476 b.ResetTimer()
477 b.RunParallel(func(pb *testing.PB) {
478 for pb.Next() {
479 var v interface{}
480 _, _ = decode(TwitterJson, &v, true)
481 }
482 })
483 }
484
485 func BenchmarkDecoder_Parallel_Generic_Sonic_Fast(b *testing.B) {
486 var w interface{}
487 _, _ = decode(TwitterJson, &w, false)
488 b.SetBytes(int64(len(TwitterJson)))
489 b.ResetTimer()
490 b.RunParallel(func(pb *testing.PB) {
491 for pb.Next() {
492 var v interface{}
493 _, _ = decode(TwitterJson, &v, false)
494 }
495 })
496 }
497
498 func BenchmarkDecoder_Parallel_Generic_StdLib(b *testing.B) {
499 var w interface{}
500 m := []byte(TwitterJson)
501 _ = json.Unmarshal(m, &w)
502 b.SetBytes(int64(len(TwitterJson)))
503 b.ResetTimer()
504 b.RunParallel(func(pb *testing.PB) {
505 for pb.Next() {
506 var v interface{}
507 _ = json.Unmarshal(m, &v)
508 }
509 })
510 }
511
512 func BenchmarkDecoder_Parallel_Binding_Sonic(b *testing.B) {
513 var w TwitterStruct
514 _, _ = decode(TwitterJson, &w, true)
515 b.SetBytes(int64(len(TwitterJson)))
516 b.ResetTimer()
517 b.RunParallel(func(pb *testing.PB) {
518 for pb.Next() {
519 var v TwitterStruct
520 _, _ = decode(TwitterJson, &v, true)
521 }
522 })
523 }
524
525 func BenchmarkDecoder_Parallel_Binding_Sonic_Fast(b *testing.B) {
526 var w TwitterStruct
527 _, _ = decode(TwitterJson, &w, false)
528 b.SetBytes(int64(len(TwitterJson)))
529 b.ResetTimer()
530 b.RunParallel(func(pb *testing.PB) {
531 for pb.Next() {
532 var v TwitterStruct
533 _, _ = decode(TwitterJson, &v, false)
534 }
535 })
536 }
537
538 func BenchmarkDecoder_Parallel_Binding_StdLib(b *testing.B) {
539 var w TwitterStruct
540 m := []byte(TwitterJson)
541 _ = json.Unmarshal(m, &w)
542 b.SetBytes(int64(len(TwitterJson)))
543 b.ResetTimer()
544 b.RunParallel(func(pb *testing.PB) {
545 for pb.Next() {
546 var v TwitterStruct
547 _ = json.Unmarshal(m, &v)
548 }
549 })
550 }
551
552 func BenchmarkSkip_Sonic(b *testing.B) {
553 var data = rt.Str2Mem(TwitterJson)
554 if ret, _ := Skip(data); ret < 0 {
555 b.Fatal()
556 }
557 b.SetBytes(int64(len(TwitterJson)))
558 b.ResetTimer()
559 for i:=0; i<b.N; i++ {
560 _, _ = Skip(data)
561 }
562 }
View as plain text