...
1 package tests
2
3 import (
4 "reflect"
5 "testing"
6 "unsafe"
7
8 "github.com/mailru/easyjson"
9 )
10
11
12 func strBelongsTo(s string, buf []byte) bool {
13 sPtr := (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
14 bufPtr := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data
15
16 if bufPtr <= sPtr && sPtr < bufPtr+uintptr(len(buf)) {
17 return true
18 }
19 return false
20 }
21
22 func TestNocopy(t *testing.T) {
23 data := []byte(`{"a": "valueA", "b": "valueB"}`)
24 exp := NocopyStruct{
25 A: "valueA",
26 B: "valueB",
27 }
28 res := NocopyStruct{}
29
30 err := easyjson.Unmarshal(data, &res)
31 if err != nil {
32 t.Error(err)
33 }
34 if !reflect.DeepEqual(exp, res) {
35 t.Errorf("TestNocopy(): got=%+v, exp=%+v", res, exp)
36 }
37
38 if strBelongsTo(res.A, data) {
39 t.Error("TestNocopy(): field A was not copied and refers to buffer")
40 }
41 if !strBelongsTo(res.B, data) {
42 t.Error("TestNocopy(): field B was copied rather than refer to bufferr")
43 }
44
45 data = []byte(`{"b": "valueNoCopy"}`)
46 res = NocopyStruct{}
47 allocsPerRun := testing.AllocsPerRun(1000, func() {
48 err := easyjson.Unmarshal(data, &res)
49 if err != nil {
50 t.Error(err)
51 }
52 if res.B != "valueNoCopy" {
53 t.Fatalf("wrong value: %q", res.B)
54 }
55 })
56 if allocsPerRun != 1 {
57 t.Fatalf("noCopy field unmarshal: expected 1 allocs, got %f", allocsPerRun)
58 }
59
60 data = []byte(`{"a": "valueNoCopy"}`)
61 allocsPerRun = testing.AllocsPerRun(1000, func() {
62 err := easyjson.Unmarshal(data, &res)
63 if err != nil {
64 t.Error(err)
65 }
66 if res.A != "valueNoCopy" {
67 t.Fatalf("wrong value: %q", res.A)
68 }
69 })
70 if allocsPerRun != 2 {
71 t.Fatalf("copy field unmarshal: expected 2 allocs, got %f", allocsPerRun)
72 }
73 }
74
View as plain text