File: //proc/thread-self/root/opt/go/pkg/mod/github.com/mailru/
[email protected]/tests/nocopy_test.go
package tests
import (
"reflect"
"testing"
"unsafe"
"github.com/mailru/easyjson"
)
// verifies if string pointer belongs to the given buffer or outside of it
func strBelongsTo(s string, buf []byte) bool {
sPtr := (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
bufPtr := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data
if bufPtr <= sPtr && sPtr < bufPtr+uintptr(len(buf)) {
return true
}
return false
}
func TestNocopy(t *testing.T) {
data := []byte(`{"a": "valueA", "b": "valueB"}`)
exp := NocopyStruct{
A: "valueA",
B: "valueB",
}
res := NocopyStruct{}
err := easyjson.Unmarshal(data, &res)
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(exp, res) {
t.Errorf("TestNocopy(): got=%+v, exp=%+v", res, exp)
}
if strBelongsTo(res.A, data) {
t.Error("TestNocopy(): field A was not copied and refers to buffer")
}
if !strBelongsTo(res.B, data) {
t.Error("TestNocopy(): field B was copied rather than refer to bufferr")
}
data = []byte(`{"b": "valueNoCopy"}`)
res = NocopyStruct{}
allocsPerRun := testing.AllocsPerRun(1000, func() {
err := easyjson.Unmarshal(data, &res)
if err != nil {
t.Error(err)
}
if res.B != "valueNoCopy" {
t.Fatalf("wrong value: %q", res.B)
}
})
if allocsPerRun != 1 {
t.Fatalf("noCopy field unmarshal: expected 1 allocs, got %f", allocsPerRun)
}
data = []byte(`{"a": "valueNoCopy"}`)
allocsPerRun = testing.AllocsPerRun(1000, func() {
err := easyjson.Unmarshal(data, &res)
if err != nil {
t.Error(err)
}
if res.A != "valueNoCopy" {
t.Fatalf("wrong value: %q", res.A)
}
})
if allocsPerRun != 2 {
t.Fatalf("copy field unmarshal: expected 2 allocs, got %f", allocsPerRun)
}
}