forked from cosmos/iavl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnode_test.go
127 lines (117 loc) · 4.1 KB
/
node_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package iavl
import (
"bytes"
"math/rand"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNode_aminoSize(t *testing.T) {
node := &Node{
key: randBytes(10),
value: randBytes(10),
version: 1,
height: 0,
size: 100,
hash: randBytes(20),
leftHash: randBytes(20),
leftNode: nil,
rightHash: randBytes(20),
rightNode: nil,
persisted: false,
}
// leaf node
require.Equal(t, 26, node.aminoSize())
// non-leaf node
node.height = 1
require.Equal(t, 57, node.aminoSize())
}
func TestNode_validate(t *testing.T) {
k := []byte("key")
v := []byte("value")
h := []byte{1, 2, 3}
c := &Node{key: []byte("child"), value: []byte("x"), version: 1, size: 1}
testcases := map[string]struct {
node *Node
valid bool
}{
"nil node": {nil, false},
"leaf": {&Node{key: k, value: v, version: 1, size: 1}, true},
"leaf with nil key": {&Node{key: nil, value: v, version: 1, size: 1}, false},
"leaf with empty key": {&Node{key: []byte{}, value: v, version: 1, size: 1}, true},
"leaf with nil value": {&Node{key: k, value: nil, version: 1, size: 1}, false},
"leaf with empty value": {&Node{key: k, value: []byte{}, version: 1, size: 1}, true},
"leaf with version 0": {&Node{key: k, value: v, version: 0, size: 1}, false},
"leaf with version -1": {&Node{key: k, value: v, version: -1, size: 1}, false},
"leaf with size 0": {&Node{key: k, value: v, version: 1, size: 0}, false},
"leaf with size 2": {&Node{key: k, value: v, version: 1, size: 2}, false},
"leaf with size -1": {&Node{key: k, value: v, version: 1, size: -1}, false},
"leaf with left hash": {&Node{key: k, value: v, version: 1, size: 1, leftHash: h}, false},
"leaf with left child": {&Node{key: k, value: v, version: 1, size: 1, leftNode: c}, false},
"leaf with right hash": {&Node{key: k, value: v, version: 1, size: 1, rightNode: c}, false},
"leaf with right child": {&Node{key: k, value: v, version: 1, size: 1, rightNode: c}, false},
"inner": {&Node{key: k, version: 1, size: 1, height: 1, leftHash: h, rightHash: h}, true},
"inner with nil key": {&Node{key: nil, value: v, version: 1, size: 1, height: 1, leftHash: h, rightHash: h}, false},
"inner with value": {&Node{key: k, value: v, version: 1, size: 1, height: 1, leftHash: h, rightHash: h}, false},
"inner with empty value": {&Node{key: k, value: []byte{}, version: 1, size: 1, height: 1, leftHash: h, rightHash: h}, false},
"inner with left child": {&Node{key: k, version: 1, size: 1, height: 1, leftHash: h}, true},
"inner with right child": {&Node{key: k, version: 1, size: 1, height: 1, rightHash: h}, true},
"inner with no child": {&Node{key: k, version: 1, size: 1, height: 1}, false},
"inner with height 0": {&Node{key: k, version: 1, size: 1, height: 0, leftHash: h, rightHash: h}, false},
}
for desc, tc := range testcases {
tc := tc // appease scopelint
t.Run(desc, func(t *testing.T) {
err := tc.node.validate()
if tc.valid {
assert.NoError(t, err)
} else {
assert.Error(t, err)
}
})
}
}
func BenchmarkNode_aminoSize(b *testing.B) {
node := &Node{
key: randBytes(25),
value: randBytes(100),
version: rand.Int63n(10000000),
height: 1,
size: rand.Int63n(10000000),
leftHash: randBytes(20),
rightHash: randBytes(20),
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
node.aminoSize()
}
}
func BenchmarkNode_WriteBytes(b *testing.B) {
node := &Node{
key: randBytes(25),
value: randBytes(100),
version: rand.Int63n(10000000),
height: 1,
size: rand.Int63n(10000000),
leftHash: randBytes(20),
rightHash: randBytes(20),
}
b.ResetTimer()
b.Run("NoPreAllocate", func(sub *testing.B) {
sub.ReportAllocs()
for i := 0; i < sub.N; i++ {
var buf bytes.Buffer
buf.Reset()
_ = node.writeBytes(&buf)
}
})
b.Run("PreAllocate", func(sub *testing.B) {
sub.ReportAllocs()
for i := 0; i < sub.N; i++ {
var buf bytes.Buffer
buf.Grow(node.aminoSize())
_ = node.writeBytes(&buf)
}
})
}