1
16
17 package encoder
18
19 import (
20 `encoding/hex`
21 `encoding/json`
22 `math`
23 `reflect`
24 `runtime`
25 `strings`
26 `testing`
27 `unsafe`
28
29 `github.com/bytedance/sonic/option`
30 `github.com/bytedance/sonic/internal/rt`
31 `github.com/davecgh/go-spew/spew`
32 `github.com/stretchr/testify/assert`
33 )
34
35 func TestEncoderMemoryCorruption(t *testing.T) {
36 println("TestEncoderMemoryCorruption")
37 runtime.GC()
38 var m = map[string]interface{}{
39 "1": map[string]interface{} {
40 `"`+strings.Repeat("a", int(option.DefaultEncoderBufferSize) - 38)+`"`: "b",
41 "1": map[string]int32{
42 "b": 1658219785,
43 },
44 },
45 }
46 out, err := Encode(m, SortMapKeys)
47 if err != nil {
48 t.Fatal(err)
49 }
50 println(len(out))
51 if err := json.Unmarshal(out, &m); err != nil {
52 t.Fatal(err)
53 }
54 }
55
56 func TestAssembler_CompileAndLoad(t *testing.T) {
57 p, err := newCompiler().compile(reflect.TypeOf((*bool)(nil)), true)
58 assert.Nil(t, err)
59 a := newAssembler(p)
60 f := a.Load()
61 s := newStack()
62 b := []byte(nil)
63
64
65 v := true
66 u := &v
67 e := f(&b, unsafe.Pointer(&u), s, 0)
68 assert.Nil(t, e)
69 println(cap(b))
70 println(hex.Dump(b))
71
72
73 v = false
74 u = &v
75 b = b[:0]
76 e = f(&b, unsafe.Pointer(&u), s, 0)
77 assert.Nil(t, e)
78 println(cap(b))
79 println(hex.Dump(b))
80
81
82 u = nil
83 b = b[:0]
84 e = f(&b, unsafe.Pointer(&u), s, 0)
85 assert.Nil(t, e)
86 println(cap(b))
87 println(hex.Dump(b))
88 }
89
90 type testOps struct {
91 key string
92 ins _Program
93 exp string
94 err error
95 val interface{}
96 }
97
98 func testOpCode(t *testing.T, v interface{}, ex string, err error, ins _Program) {
99 p := ins
100 m := []byte(nil)
101 s := new(_Stack)
102 a := newAssembler(p)
103 f := a.Load()
104 e := f(&m, rt.UnpackEface(v).Value, s, 0)
105 if err != nil {
106 assert.EqualError(t, e, err.Error())
107 } else {
108 assert.Nil(t, e)
109 assert.Equal(t, ex, string(m))
110 }
111 }
112
113 type IfaceValue int
114 func (IfaceValue) Error() string {
115 return "not really implemented"
116 }
117
118 type JsonMarshalerValue int
119 func (JsonMarshalerValue) MarshalJSON() ([]byte, error) {
120 return []byte("123456789"), nil
121 }
122
123 type RecursiveValue struct {
124 A int `json:"a"`
125 P *RecursiveValue `json:"p,omitempty"`
126 Q []RecursiveValue `json:"q"`
127 R map[string]RecursiveValue `json:"r"`
128 Z int `json:"z"`
129 }
130
131 func mustCompile(t interface{}) _Program {
132 p, err := newCompiler().compile(reflect.TypeOf(t), !rt.UnpackEface(t).Type.Indirect())
133 if err != nil {
134 panic(err)
135 }
136 return p
137 }
138
139 func TestAssembler_OpCode(t *testing.T) {
140 var iface error = IfaceValue(12345)
141 var eface interface{} = 12345
142 var jval = new(JsonMarshalerValue)
143 var jifv json.Marshaler = JsonMarshalerValue(0)
144 var jifp json.Marshaler = jval
145 var rec = &RecursiveValue {
146 A: 123,
147 Z: 456,
148 P: &RecursiveValue {
149 A: 789,
150 Z: 666,
151 P: &RecursiveValue {
152 A: 777,
153 Z: 888,
154 Q: []RecursiveValue {{
155 A: 999,
156 Z: 222,
157 R: map[string]RecursiveValue {
158 "xxx": {
159 A: 333,
160 },
161 },
162 }},
163 },
164 },
165 }
166 tests := []testOps {
167 {
168 key: "_OP_null",
169 ins: []_Instr{newInsOp(_OP_null)},
170 exp: "null",
171 val: nil,
172 }, {
173 key: "_OP_bool/true",
174 ins: []_Instr{newInsOp(_OP_bool)},
175 exp: "true",
176 val: true,
177 }, {
178 key: "_OP_bool/false",
179 ins: []_Instr{newInsOp(_OP_bool)},
180 exp: "false",
181 val: false,
182 }, {
183 key: "_OP_i8",
184 ins: []_Instr{newInsOp(_OP_i8)},
185 exp: "-128",
186 val: int8(-128),
187 }, {
188 key: "_OP_i16",
189 ins: []_Instr{newInsOp(_OP_i16)},
190 exp: "-32768",
191 val: int16(-32768),
192 }, {
193 key: "_OP_i32",
194 ins: []_Instr{newInsOp(_OP_i32)},
195 exp: "-2147483648",
196 val: int32(-2147483648),
197 }, {
198 key: "_OP_i64",
199 ins: []_Instr{newInsOp(_OP_i64)},
200 exp: "-9223372036854775808",
201 val: int64(math.MinInt64),
202 }, {
203 key: "_OP_u8",
204 ins: []_Instr{newInsOp(_OP_u8)},
205 exp: "255",
206 val: uint8(255),
207 }, {
208 key: "_OP_u16",
209 ins: []_Instr{newInsOp(_OP_u16)},
210 exp: "65535",
211 val: uint16(65535),
212 }, {
213 key: "_OP_u32",
214 ins: []_Instr{newInsOp(_OP_u32)},
215 exp: "4294967295",
216 val: uint32(4294967295),
217 }, {
218 key: "_OP_u64",
219 ins: []_Instr{newInsOp(_OP_u64)},
220 exp: "18446744073709551615",
221 val: uint64(18446744073709551615),
222 }, {
223 key: "_OP_f32",
224 ins: []_Instr{newInsOp(_OP_f32)},
225 exp: "-12.5",
226 val: float32(-12.5),
227 }, {
228 key: "_OP_f32/nan",
229 ins: []_Instr{newInsOp(_OP_f32)},
230 err: _ERR_nan_or_infinite,
231 val: float32(math.NaN()),
232 }, {
233 key: "_OP_f32/+inf",
234 ins: []_Instr{newInsOp(_OP_f32)},
235 err: _ERR_nan_or_infinite,
236 val: float32(math.Inf(1)),
237 }, {
238 key: "_OP_f32/-inf",
239 ins: []_Instr{newInsOp(_OP_f32)},
240 err: _ERR_nan_or_infinite,
241 val: float32(math.Inf(-1)),
242 }, {
243 key: "_OP_f64",
244 ins: []_Instr{newInsOp(_OP_f64)},
245 exp: "-2.2250738585072014e-308",
246 val: -2.2250738585072014e-308,
247 }, {
248 key: "_OP_f64/nan",
249 ins: []_Instr{newInsOp(_OP_f64)},
250 err: _ERR_nan_or_infinite,
251 val: math.NaN(),
252 }, {
253 key: "_OP_f64/+inf",
254 ins: []_Instr{newInsOp(_OP_f64)},
255 err: _ERR_nan_or_infinite,
256 val: math.Inf(1),
257 }, {
258 key: "_OP_f64/-inf",
259 ins: []_Instr{newInsOp(_OP_f64)},
260 err: _ERR_nan_or_infinite,
261 val: math.Inf(-1),
262 }, {
263 key: "_OP_str",
264 ins: []_Instr{newInsOp(_OP_str)},
265 exp: `"Cartoonist, Illustrator, and T-Shirt connoisseur"`,
266 val: "Cartoonist, Illustrator, and T-Shirt connoisseur",
267 }, {
268 key: "_OP_str/empty",
269 ins: []_Instr{newInsOp(_OP_str)},
270 exp: `""`,
271 val: "",
272 }, {
273 key: "_OP_bin",
274 ins: []_Instr{newInsOp(_OP_bin)},
275 exp: `"AQIDBAU="`,
276 val: []byte{1, 2, 3, 4, 5},
277 }, {
278 key: "_OP_bin/empty",
279 ins: []_Instr{newInsOp(_OP_bin)},
280 exp: `""`,
281 val: []byte{},
282 }, {
283 key: "_OP_quote",
284 ins: []_Instr{newInsOp(_OP_quote)},
285 exp: `"\"test\""`,
286 val: "test",
287 }, {
288 key: "_OP_quote/escape",
289 ins: []_Instr{newInsOp(_OP_quote)},
290 exp: `"\"hello\\n\\t\\rworld\""`,
291 val: "hello\n\t\rworld",
292 }, {
293 key: "_OP_number",
294 ins: []_Instr{newInsOp(_OP_number)},
295 exp: "1.2345",
296 val: "1.2345",
297 }, {
298 key: "_OP_number/invalid",
299 ins: []_Instr{newInsOp(_OP_number)},
300 err: error_number("not a number"),
301 val: "not a number",
302 }, {
303 key: "_OP_eface",
304 ins: []_Instr{newInsOp(_OP_eface)},
305 exp: `12345`,
306 val: &eface,
307 }, {
308 key: "_OP_iface",
309 ins: []_Instr{newInsOp(_OP_iface)},
310 exp: `12345`,
311 val: &iface,
312 }, {
313 key: "_OP_byte",
314 ins: []_Instr{newInsVi(_OP_byte, 'x')},
315 exp: "x",
316 val: nil,
317 }, {
318 key: "_OP_text",
319 ins: []_Instr{newInsVs(_OP_text, "hello, world !!")},
320 exp: "hello, world !!",
321 val: nil,
322 }, {
323 key: "_OP_map_[iter,next,value]",
324 ins: mustCompile(map[string]map[int64]int{}),
325 exp: `{"asdf":{"-9223372036854775808":1234}}`,
326 val: &map[string]map[int64]int{"asdf": {math.MinInt64: 1234}},
327 }, {
328 key: "_OP_slice_[len,next]",
329 ins: mustCompile([][]int{}),
330 exp: `[[1,2,3],[4,5,6]]`,
331 val: &[][]int{{1, 2, 3}, {4, 5, 6}},
332 }, {
333 key: "_OP_marshal[_text]",
334 ins: []_Instr{newInsVt(_OP_marshal, reflect.TypeOf(JsonMarshalerValue(0)))},
335 exp: "123456789",
336 val: new(JsonMarshalerValue),
337 }, {
338 key: "_OP_marshal[_text]/ptr",
339 ins: []_Instr{newInsVt(_OP_marshal, reflect.TypeOf(new(JsonMarshalerValue)))},
340 exp: "123456789",
341 val: &jval,
342 }, {
343 key: "_OP_marshal[_text]/iface_v",
344 ins: []_Instr{newInsVt(_OP_marshal, jsonMarshalerType)},
345 exp: "123456789",
346 val: &jifv,
347 }, {
348 key: "_OP_marshal[_text]/iface_p",
349 ins: []_Instr{newInsVt(_OP_marshal, jsonMarshalerType)},
350 exp: "123456789",
351 val: &jifp,
352 },
353 {
354 key: "_OP_recurse",
355 ins: mustCompile(rec),
356 exp: `{"a":123,"p":{"a":789,"p":{"a":777,"q":[{"a":999,"q":null,"r":{"` +
357 `xxx":{"a":333,"q":null,"r":null,"z":0}},"z":222}],"r":null,"z":8` +
358 `88},"q":null,"r":null,"z":666},"q":null,"r":null,"z":456}`,
359 val: &rec,
360 }}
361 for _, tv := range tests {
362 t.Run(tv.key, func(t *testing.T) {
363 testOpCode(t, tv.val, tv.exp, tv.err, tv.ins)
364 })
365 }
366 }
367
368 func TestAssembler_StringMoreSpace(t *testing.T) {
369 p := _Program{newInsOp(_OP_str)}
370 m := make([]byte, 0, 8)
371 s := new(_Stack)
372 a := newAssembler(p)
373 f := a.Load()
374 v := "\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u0010"
375 e := f(&m, unsafe.Pointer(&v), s, 0)
376 assert.Nil(t, e)
377 spew.Dump(m)
378 }
379
380 func TestAssembler_TwitterJSON_Generic(t *testing.T) {
381 p := mustCompile(&_GenericValue)
382 m := []byte(nil)
383 s := new(_Stack)
384 a := newAssembler(p)
385 f := a.Load()
386 v := &_GenericValue
387 e := f(&m, unsafe.Pointer(&v), s, 0)
388 assert.Nil(t, e)
389 println(string(m))
390 }
391
392 func TestAssembler_TwitterJSON_Structure(t *testing.T) {
393 p := mustCompile(_BindingValue)
394 m := []byte(nil)
395 s := new(_Stack)
396 a := newAssembler(p)
397 f := a.Load()
398 e := f(&m, unsafe.Pointer(&_BindingValue), s, 0)
399 assert.Nil(t, e)
400 println(string(m))
401 runtime.KeepAlive(s)
402 }
403
404 func TestScratchedString(t *testing.T) {
405 fatal := *(*string)(unsafe.Pointer(&rt.GoString{nil, 1}))
406 defer func(){
407 if v := recover(); v == nil {
408 t.Fatal()
409 } else if s, ok := v.(string); !ok {
410 t.Fatal(v)
411 }else{
412 if !strings.Contains(s, "has nil pointer while its length is not zero") {
413 t.Fatal(s)
414 }
415 }
416 }()
417 _, _ = Encode(fatal, 0)
418 t.Fatal()
419 }
420
421 func TestScratchedNumber(t *testing.T) {
422 fatal := *(*json.Number)(unsafe.Pointer(&rt.GoString{nil, 1}))
423 defer func(){
424 if v := recover(); v == nil {
425 t.Fatal()
426 } else if s, ok := v.(string); !ok {
427 t.Fatal(v)
428 }else{
429 if !strings.Contains(s, "has nil pointer while its length is not zero") {
430 t.Fatal(s)
431 }
432 }
433 }()
434 _, _ = Encode(fatal, 0)
435 t.Fatal()
436 }
View as plain text