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