github.com/iotexproject/iotex-core@v1.14.1-rc1/db/batch/batch_impl_test.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package batch 7 8 import ( 9 "bytes" 10 "math/rand" 11 "strconv" 12 "testing" 13 14 "github.com/iotexproject/go-pkgs/hash" 15 16 "github.com/pkg/errors" 17 "github.com/stretchr/testify/require" 18 ) 19 20 var ( 21 _bucket1 = "test_ns1" 22 _testK1 = [3][]byte{[]byte("key_1"), []byte("key_2"), []byte("key_3")} 23 _testV1 = [3][]byte{[]byte("value_1"), []byte("value_2"), []byte("value_3")} 24 _testK2 = [3][]byte{[]byte("key_4"), []byte("key_5"), []byte("key_6")} 25 _testV2 = [3][]byte{[]byte("value_4"), []byte("value_5"), []byte("value_6")} 26 ) 27 28 func TestBaseKVStoreBatch(t *testing.T) { 29 require := require.New(t) 30 31 b := NewBatch() 32 require.Equal(0, b.Size()) 33 b.Put("ns", []byte{}, []byte{}, "") 34 require.Equal(1, b.Size()) 35 _, err := b.Entry(1) 36 require.Error(err) 37 b.Delete("ns", []byte{}, "") 38 require.Equal(2, b.Size()) 39 wi, err := b.Entry(1) 40 require.NoError(err) 41 require.Equal(Delete, wi.WriteType()) 42 b.AddFillPercent("test", 0.5) 43 p, ok := b.CheckFillPercent("ns") 44 require.False(ok) 45 require.Equal(1.0*0, p) 46 p, ok = b.CheckFillPercent("test") 47 require.True(ok) 48 require.Equal(0.5, p) 49 50 // test serialize/translate 51 require.True(bytes.Equal([]byte{0, 110, 115, 1, 110, 115}, b.SerializeQueue(nil, nil))) 52 require.True(bytes.Equal([]byte{}, b.SerializeQueue(nil, func(wi *WriteInfo) bool { 53 return wi.Namespace() == "ns" 54 }))) 55 require.True(bytes.Equal([]byte{110, 115, 110, 115}, b.SerializeQueue(func(wi *WriteInfo) []byte { 56 return wi.SerializeWithoutWriteType() 57 }, nil))) 58 newb := b.Translate(func(wi *WriteInfo) *WriteInfo { 59 if wi.WriteType() == Delete { 60 return NewWriteInfo( 61 Put, 62 "to_delete_ns", 63 wi.Key(), 64 wi.Value(), 65 "", 66 ) 67 } 68 return wi 69 }) 70 newEntry1, err := newb.Entry(1) 71 require.NoError(err) 72 require.Equal("to_delete_ns", newEntry1.Namespace()) 73 require.Equal(Put, newEntry1.WriteType()) 74 b.Clear() 75 require.Equal(0, b.Size()) 76 } 77 78 func TestCachedBatch(t *testing.T) { 79 require := require.New(t) 80 81 cb := NewCachedBatch() 82 cb.Put(_bucket1, _testK1[0], _testV1[0], "") 83 v, err := cb.Get(_bucket1, _testK1[0]) 84 require.NoError(err) 85 require.Equal(_testV1[0], v) 86 v, err = cb.Get(_bucket1, _testK2[0]) 87 require.Equal(ErrNotExist, err) 88 require.Equal([]byte(nil), v) 89 si := cb.Snapshot() 90 require.Equal(0, si) 91 92 cb.Delete(_bucket1, _testK2[0], "") 93 cb.Delete(_bucket1, _testK1[0], "") 94 _, err = cb.Get(_bucket1, _testK1[0]) 95 require.Equal(ErrAlreadyDeleted, errors.Cause(err)) 96 97 w, err := cb.Entry(1) 98 require.NoError(err) 99 require.Equal(_bucket1, w.namespace) 100 require.Equal(_testK2[0], w.key) 101 require.Equal([]byte(nil), w.value) 102 require.Equal(Delete, w.writeType) 103 104 w, err = cb.Entry(2) 105 require.NoError(err) 106 require.Equal(_bucket1, w.namespace) 107 require.Equal(_testK1[0], w.key) 108 require.Equal([]byte(nil), w.value) 109 require.Equal(Delete, w.writeType) 110 require.True(bytes.Equal( 111 []byte{116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49, 118, 97, 108, 117, 101, 95, 49, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 52, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49}, 112 cb.SerializeQueue(func(wi *WriteInfo) []byte { 113 return wi.SerializeWithoutWriteType() 114 }, nil), 115 )) 116 require.True(bytes.Equal([]byte{116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49, 118, 97, 108, 117, 101, 95, 49}, cb.SerializeQueue(func(wi *WriteInfo) []byte { 117 return wi.SerializeWithoutWriteType() 118 }, func(wi *WriteInfo) bool { 119 return wi.WriteType() == Delete 120 }))) 121 require.True(bytes.Equal( 122 []byte{0, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49, 118, 97, 108, 117, 101, 95, 49, 1, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 52, 1, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49}, 123 cb.SerializeQueue(nil, nil), 124 )) 125 require.True(bytes.Equal([]byte{0, 116, 101, 115, 116, 95, 110, 115, 49, 107, 101, 121, 95, 49, 118, 97, 108, 117, 101, 95, 49}, cb.SerializeQueue(nil, func(wi *WriteInfo) bool { 126 return wi.WriteType() == Delete 127 }))) 128 require.Equal(3, cb.Size()) 129 require.Error(cb.RevertSnapshot(-1)) 130 require.Error(cb.RevertSnapshot(si + 1)) 131 require.NoError(cb.RevertSnapshot(si)) 132 require.Equal(1, cb.Size()) 133 require.True(bytes.Equal([]byte{}, cb.Translate(func(wi *WriteInfo) *WriteInfo { 134 if wi.WriteType() != Delete { 135 return nil 136 } 137 return wi 138 }).SerializeQueue(nil, nil))) 139 cb.Clear() 140 require.Equal(0, cb.Size()) 141 } 142 143 func TestSnapshot(t *testing.T) { 144 require := require.New(t) 145 146 cb := NewCachedBatch() 147 cb.Clear() 148 cb.Put(_bucket1, _testK1[0], _testV1[0], "") 149 cb.Put(_bucket1, _testK1[1], _testV1[1], "") 150 s0 := cb.Snapshot() 151 require.Equal(0, s0) 152 require.Equal(2, cb.Size()) 153 154 cb.Put(_bucket1, _testK2[0], _testV2[0], "") 155 cb.Put(_bucket1, _testK2[1], _testV2[1], "") 156 cb.Delete(_bucket1, _testK1[0], "") 157 v, err := cb.Get(_bucket1, _testK1[0]) 158 require.Equal(ErrAlreadyDeleted, err) 159 require.Nil(v) 160 s1 := cb.Snapshot() 161 require.Equal(1, s1) 162 require.Equal(5, cb.Size()) 163 164 cb.Put(_bucket1, _testK1[2], _testV1[2], "") 165 cb.Put(_bucket1, _testK2[2], _testV2[2], "") 166 cb.Delete(_bucket1, _testK2[0], "") 167 _, err = cb.Get(_bucket1, _testK2[0]) 168 require.Equal(ErrAlreadyDeleted, err) 169 s2 := cb.Snapshot() 170 require.Equal(2, s2) 171 require.Equal(8, cb.Size()) 172 173 // snapshot 2 174 require.Error(cb.RevertSnapshot(3)) 175 require.Error(cb.RevertSnapshot(-1)) 176 require.NoError(cb.RevertSnapshot(2)) 177 _, err = cb.Get(_bucket1, _testK2[0]) 178 require.Equal(ErrAlreadyDeleted, err) 179 v, err = cb.Get(_bucket1, _testK1[1]) 180 require.NoError(err) 181 require.Equal(_testV1[1], v) 182 v, err = cb.Get(_bucket1, _testK2[1]) 183 require.NoError(err) 184 require.Equal(_testV2[1], v) 185 v, err = cb.Get(_bucket1, _testK1[2]) 186 require.NoError(err) 187 require.Equal(_testV1[2], v) 188 v, err = cb.Get(_bucket1, _testK2[2]) 189 require.NoError(err) 190 require.Equal(_testV2[2], v) 191 cb.Put(_bucket1, _testK2[2], _testV2[1], "") 192 v, err = cb.Get(_bucket1, _testK2[2]) 193 require.NoError(err) 194 require.Equal(_testV2[1], v) 195 196 // snapshot 1 197 require.NoError(cb.RevertSnapshot(2)) 198 v, err = cb.Get(_bucket1, _testK2[2]) 199 require.NoError(err) 200 require.Equal(_testV2[2], v) 201 require.NoError(cb.RevertSnapshot(1)) 202 _, err = cb.Get(_bucket1, _testK1[0]) 203 require.Equal(ErrAlreadyDeleted, err) 204 v, err = cb.Get(_bucket1, _testK1[1]) 205 require.NoError(err) 206 require.Equal(_testV1[1], v) 207 v, err = cb.Get(_bucket1, _testK2[0]) 208 require.NoError(err) 209 require.Equal(_testV2[0], v) 210 v, err = cb.Get(_bucket1, _testK2[1]) 211 require.NoError(err) 212 require.Equal(_testV2[1], v) 213 _, err = cb.Get(_bucket1, _testK2[2]) 214 require.Equal(ErrNotExist, err) 215 216 // snapshot 0 217 require.Error(cb.RevertSnapshot(2)) 218 require.NoError(cb.RevertSnapshot(0)) 219 v, err = cb.Get(_bucket1, _testK1[0]) 220 require.NoError(err) 221 require.Equal(_testV1[0], v) 222 v, err = cb.Get(_bucket1, _testK1[1]) 223 require.NoError(err) 224 require.Equal(_testV1[1], v) 225 _, err = cb.Get(_bucket1, _testK2[0]) 226 require.Equal(ErrNotExist, err) 227 _, err = cb.Get(_bucket1, _testK1[2]) 228 require.Equal(ErrNotExist, err) 229 } 230 231 func BenchmarkCachedBatch_Digest(b *testing.B) { 232 cb := NewCachedBatch() 233 234 for i := 0; i < 10000; i++ { 235 k := hash.Hash256b([]byte(strconv.Itoa(i))) 236 var v [1024]byte 237 for i := range v { 238 v[i] = byte(rand.Intn(8)) 239 } 240 cb.Put(_bucket1, k[:], v[:], "") 241 } 242 require.Equal(b, 10000, cb.Size()) 243 244 b.ResetTimer() 245 for n := 0; n < b.N; n++ { 246 b.StartTimer() 247 h := cb.SerializeQueue(nil, nil) 248 b.StopTimer() 249 require.NotEqual(b, hash.ZeroHash256, h) 250 } 251 } 252 253 func BenchmarkCachedBatch_Snapshot(b *testing.B) { 254 cb := NewCachedBatch() 255 k := hash.Hash256b([]byte("test")) 256 var v [1024]byte 257 for i := range v { 258 v[i] = byte(rand.Intn(8)) 259 } 260 b.ResetTimer() 261 for i := 0; i < b.N; i++ { 262 cb.Put(_bucket1, k[:], v[:], "") 263 _, _ = cb.Get(_bucket1, k[:]) 264 sn := cb.Snapshot() 265 cb.Delete(_bucket1, k[:], "") 266 _, _ = cb.Get(_bucket1, k[:]) 267 cb.RevertSnapshot(sn) 268 _, _ = cb.Get(_bucket1, k[:]) 269 cb.Delete(_bucket1, k[:], "") 270 } 271 }