github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/mockstore/mocktikv/mock_tikv_test.go (about) 1 // Copyright 2021 TiKV Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/mockstore/mocktikv/mock_tikv_test.go 19 // 20 21 // Copyright 2016 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package mocktikv 36 37 import ( 38 "math" 39 "testing" 40 41 "github.com/pingcap/errors" 42 "github.com/pingcap/kvproto/pkg/kvrpcpb" 43 "github.com/stretchr/testify/assert" 44 "github.com/stretchr/testify/require" 45 ) 46 47 func lock(key, primary string, ts uint64) *kvrpcpb.LockInfo { 48 return &kvrpcpb.LockInfo{ 49 Key: []byte(key), 50 PrimaryLock: []byte(primary), 51 LockVersion: ts, 52 } 53 } 54 55 func mustGetNone(t *testing.T, store MVCCStore, key string, ts uint64) { 56 val, err := store.Get([]byte(key), ts, kvrpcpb.IsolationLevel_SI, nil) 57 assert.Nil(t, err) 58 assert.Nil(t, val) 59 } 60 61 func mustGetErr(t *testing.T, store MVCCStore, key string, ts uint64) { 62 val, err := store.Get([]byte(key), ts, kvrpcpb.IsolationLevel_SI, nil) 63 assert.Error(t, err) 64 assert.Nil(t, val) 65 } 66 67 func mustGetOK(t *testing.T, store MVCCStore, key string, ts uint64, expect string) { 68 val, err := store.Get([]byte(key), ts, kvrpcpb.IsolationLevel_SI, nil) 69 assert.Nil(t, err) 70 assert.Equal(t, string(val), expect) 71 } 72 73 func mustGetRC(t *testing.T, store MVCCStore, key string, ts uint64, expect string) { 74 val, err := store.Get([]byte(key), ts, kvrpcpb.IsolationLevel_RC, nil) 75 assert.Nil(t, err) 76 assert.Equal(t, string(val), expect) 77 } 78 79 func mustPutOK(t *testing.T, store MVCCStore, key, value string, startTS, commitTS uint64) { 80 req := &kvrpcpb.PrewriteRequest{ 81 Mutations: putMutations(key, value), 82 PrimaryLock: []byte(key), 83 StartVersion: startTS, 84 } 85 errs := store.Prewrite(req) 86 for _, err := range errs { 87 assert.Nil(t, err) 88 } 89 err := store.Commit([][]byte{[]byte(key)}, startTS, commitTS) 90 assert.Nil(t, err) 91 } 92 93 func mustDeleteOK(t *testing.T, store MVCCStore, key string, startTS, commitTS uint64) { 94 mutations := []*kvrpcpb.Mutation{ 95 { 96 Op: kvrpcpb.Op_Del, 97 Key: []byte(key), 98 }, 99 } 100 req := &kvrpcpb.PrewriteRequest{ 101 Mutations: mutations, 102 PrimaryLock: []byte(key), 103 StartVersion: startTS, 104 } 105 errs := store.Prewrite(req) 106 for _, err := range errs { 107 assert.Nil(t, err) 108 } 109 err := store.Commit([][]byte{[]byte(key)}, startTS, commitTS) 110 assert.Nil(t, err) 111 } 112 113 func mustScanOK(t *testing.T, store MVCCStore, start string, limit int, ts uint64, expect ...string) { 114 mustRangeScanOK(t, store, start, "", limit, ts, expect...) 115 } 116 117 func mustRangeScanOK(t *testing.T, store MVCCStore, start, end string, limit int, ts uint64, expect ...string) { 118 assert := assert.New(t) 119 pairs := store.Scan([]byte(start), []byte(end), limit, ts, kvrpcpb.IsolationLevel_SI, nil) 120 assert.Equal(len(pairs)*2, len(expect)) 121 for i := 0; i < len(pairs); i++ { 122 assert.Nil(pairs[i].Err) 123 assert.Equal(pairs[i].Key, []byte(expect[i*2])) 124 assert.Equal(string(pairs[i].Value), expect[i*2+1]) 125 } 126 } 127 128 func mustReverseScanOK(t *testing.T, store MVCCStore, end string, limit int, ts uint64, expect ...string) { 129 mustRangeReverseScanOK(t, store, "", end, limit, ts, expect...) 130 } 131 132 func mustRangeReverseScanOK(t *testing.T, store MVCCStore, start, end string, limit int, ts uint64, expect ...string) { 133 assert := assert.New(t) 134 pairs := store.ReverseScan([]byte(start), []byte(end), limit, ts, kvrpcpb.IsolationLevel_SI, nil) 135 assert.Equal(len(pairs)*2, len(expect)) 136 for i := 0; i < len(pairs); i++ { 137 assert.Nil(pairs[i].Err) 138 assert.Equal(pairs[i].Key, []byte(expect[i*2])) 139 assert.Equal(string(pairs[i].Value), expect[i*2+1]) 140 } 141 } 142 143 func mustPrewriteOK(t *testing.T, store MVCCStore, mutations []*kvrpcpb.Mutation, primary string, startTS uint64) { 144 mustPrewriteWithTTLOK(t, store, mutations, primary, startTS, 0) 145 } 146 147 func mustPrewriteWithTTLOK(t *testing.T, store MVCCStore, mutations []*kvrpcpb.Mutation, primary string, startTS uint64, ttl uint64) { 148 assert.True(t, mustPrewriteWithTTL(store, mutations, primary, startTS, ttl)) 149 } 150 151 func mustCommitOK(t *testing.T, store MVCCStore, keys [][]byte, startTS, commitTS uint64) { 152 err := store.Commit(keys, startTS, commitTS) 153 assert.Nil(t, err) 154 } 155 156 func mustCommitErr(t *testing.T, store MVCCStore, keys [][]byte, startTS, commitTS uint64) { 157 err := store.Commit(keys, startTS, commitTS) 158 assert.NotNil(t, err) 159 } 160 161 func mustRollbackOK(t *testing.T, store MVCCStore, keys [][]byte, startTS uint64) { 162 err := store.Rollback(keys, startTS) 163 assert.Nil(t, err) 164 } 165 166 func mustRollbackErr(t *testing.T, store MVCCStore, keys [][]byte, startTS uint64) { 167 err := store.Rollback(keys, startTS) 168 assert.NotNil(t, err) 169 } 170 171 func mustScanLock(t *testing.T, store MVCCStore, maxTs uint64, expect []*kvrpcpb.LockInfo) { 172 locks, err := store.ScanLock(nil, nil, maxTs) 173 assert.Nil(t, err) 174 assert.Equal(t, locks, expect) 175 } 176 177 func mustResolveLock(t *testing.T, store MVCCStore, startTS, commitTS uint64) { 178 assert.Nil(t, store.ResolveLock(nil, nil, startTS, commitTS)) 179 } 180 181 func mustBatchResolveLock(t *testing.T, store MVCCStore, txnInfos map[uint64]uint64) { 182 assert.Nil(t, store.BatchResolveLock(nil, nil, txnInfos)) 183 } 184 185 func mustGC(t *testing.T, store MVCCStore, safePoint uint64) { 186 assert.Nil(t, store.GC(nil, nil, safePoint)) 187 } 188 189 func mustDeleteRange(t *testing.T, store MVCCStore, startKey, endKey string) { 190 assert.Nil(t, store.DeleteRange([]byte(startKey), []byte(endKey))) 191 } 192 193 func TestGet(t *testing.T) { 194 store, err := NewMVCCLevelDB("") 195 require.Nil(t, err) 196 defer store.Close() 197 mustGetNone(t, store, "x", 10) 198 mustPutOK(t, store, "x", "x", 5, 10) 199 mustGetNone(t, store, "x", 9) 200 mustGetOK(t, store, "x", 10, "x") 201 mustGetOK(t, store, "x", 11, "x") 202 } 203 204 func TestGetWithLock(t *testing.T) { 205 store, err := NewMVCCLevelDB("") 206 require.Nil(t, err) 207 defer store.Close() 208 209 key := "key" 210 value := "value" 211 mustPutOK(t, store, key, value, 5, 10) 212 mutations := []*kvrpcpb.Mutation{{ 213 Op: kvrpcpb.Op_Lock, 214 Key: []byte(key), 215 }} 216 // test with lock's type is lock 217 mustPrewriteOK(t, store, mutations, key, 20) 218 mustGetOK(t, store, key, 25, value) 219 mustCommitOK(t, store, [][]byte{[]byte(key)}, 20, 30) 220 221 // test get with lock's max ts and primary key 222 mustPrewriteOK(t, store, putMutations(key, "value2", "key2", "v5"), key, 40) 223 mustGetErr(t, store, key, 41) 224 mustGetErr(t, store, "key2", math.MaxUint64) 225 mustGetOK(t, store, key, math.MaxUint64, "value") 226 } 227 228 func TestDelete(t *testing.T) { 229 store, err := NewMVCCLevelDB("") 230 require.Nil(t, err) 231 defer store.Close() 232 233 mustPutOK(t, store, "x", "x5-10", 5, 10) 234 mustDeleteOK(t, store, "x", 15, 20) 235 mustGetNone(t, store, "x", 5) 236 mustGetNone(t, store, "x", 9) 237 mustGetOK(t, store, "x", 10, "x5-10") 238 mustGetOK(t, store, "x", 19, "x5-10") 239 mustGetNone(t, store, "x", 20) 240 mustGetNone(t, store, "x", 21) 241 } 242 243 func TestCleanupRollback(t *testing.T) { 244 store, err := NewMVCCLevelDB("") 245 require.Nil(t, err) 246 defer store.Close() 247 248 mustPutOK(t, store, "secondary", "s-0", 1, 2) 249 mustPrewriteOK(t, store, putMutations("primary", "p-5", "secondary", "s-5"), "primary", 5) 250 mustGetErr(t, store, "secondary", 8) 251 mustGetErr(t, store, "secondary", 12) 252 mustCommitOK(t, store, [][]byte{[]byte("primary")}, 5, 10) 253 mustRollbackErr(t, store, [][]byte{[]byte("primary")}, 5) 254 } 255 256 func TestReverseScan(t *testing.T) { 257 store, err := NewMVCCLevelDB("") 258 require.Nil(t, err) 259 defer store.Close() 260 261 // ver10: A(10) - B(_) - C(10) - D(_) - E(10) 262 mustPutOK(t, store, "A", "A10", 5, 10) 263 mustPutOK(t, store, "C", "C10", 5, 10) 264 mustPutOK(t, store, "E", "E10", 5, 10) 265 266 checkV10 := func() { 267 mustReverseScanOK(t, store, "Z", 0, 10) 268 mustReverseScanOK(t, store, "Z", 1, 10, "E", "E10") 269 mustReverseScanOK(t, store, "Z", 2, 10, "E", "E10", "C", "C10") 270 mustReverseScanOK(t, store, "Z", 3, 10, "E", "E10", "C", "C10", "A", "A10") 271 mustReverseScanOK(t, store, "Z", 4, 10, "E", "E10", "C", "C10", "A", "A10") 272 mustReverseScanOK(t, store, "E\x00", 3, 10, "E", "E10", "C", "C10", "A", "A10") 273 mustReverseScanOK(t, store, "C\x00", 3, 10, "C", "C10", "A", "A10") 274 mustReverseScanOK(t, store, "C\x00", 4, 10, "C", "C10", "A", "A10") 275 mustReverseScanOK(t, store, "B", 1, 10, "A", "A10") 276 mustRangeReverseScanOK(t, store, "", "E", 5, 10, "C", "C10", "A", "A10") 277 mustRangeReverseScanOK(t, store, "", "C\x00", 5, 10, "C", "C10", "A", "A10") 278 mustRangeReverseScanOK(t, store, "A\x00", "C", 5, 10) 279 } 280 checkV10() 281 282 // ver20: A(10) - B(20) - C(10) - D(20) - E(10) 283 mustPutOK(t, store, "B", "B20", 15, 20) 284 mustPutOK(t, store, "D", "D20", 15, 20) 285 286 checkV20 := func() { 287 mustReverseScanOK(t, store, "Z", 5, 20, "E", "E10", "D", "D20", "C", "C10", "B", "B20", "A", "A10") 288 mustReverseScanOK(t, store, "C\x00", 5, 20, "C", "C10", "B", "B20", "A", "A10") 289 mustReverseScanOK(t, store, "A\x00", 1, 20, "A", "A10") 290 mustRangeReverseScanOK(t, store, "B", "D", 5, 20, "C", "C10", "B", "B20") 291 mustRangeReverseScanOK(t, store, "B", "D\x00", 5, 20, "D", "D20", "C", "C10", "B", "B20") 292 mustRangeReverseScanOK(t, store, "B\x00", "D\x00", 5, 20, "D", "D20", "C", "C10") 293 } 294 checkV10() 295 checkV20() 296 297 // ver30: A(_) - B(20) - C(10) - D(_) - E(10) 298 mustDeleteOK(t, store, "A", 25, 30) 299 mustDeleteOK(t, store, "D", 25, 30) 300 301 checkV30 := func() { 302 mustReverseScanOK(t, store, "Z", 5, 30, "E", "E10", "C", "C10", "B", "B20") 303 mustReverseScanOK(t, store, "C", 1, 30, "B", "B20") 304 mustReverseScanOK(t, store, "C\x00", 5, 30, "C", "C10", "B", "B20") 305 } 306 checkV10() 307 checkV20() 308 checkV30() 309 310 // ver40: A(_) - B(_) - C(40) - D(40) - E(10) 311 mustDeleteOK(t, store, "B", 35, 40) 312 mustPutOK(t, store, "C", "C40", 35, 40) 313 mustPutOK(t, store, "D", "D40", 35, 40) 314 315 checkV40 := func() { 316 mustReverseScanOK(t, store, "Z", 5, 40, "E", "E10", "D", "D40", "C", "C40") 317 mustReverseScanOK(t, store, "Z", 5, 100, "E", "E10", "D", "D40", "C", "C40") 318 } 319 checkV10() 320 checkV20() 321 checkV30() 322 checkV40() 323 } 324 325 func TestScan(t *testing.T) { 326 store, err := NewMVCCLevelDB("") 327 require.Nil(t, err) 328 defer store.Close() 329 330 // ver10: A(10) - B(_) - C(10) - D(_) - E(10) 331 mustPutOK(t, store, "A", "A10", 5, 10) 332 mustPutOK(t, store, "C", "C10", 5, 10) 333 mustPutOK(t, store, "E", "E10", 5, 10) 334 335 checkV10 := func() { 336 mustScanOK(t, store, "", 0, 10) 337 mustScanOK(t, store, "", 1, 10, "A", "A10") 338 mustScanOK(t, store, "", 2, 10, "A", "A10", "C", "C10") 339 mustScanOK(t, store, "", 3, 10, "A", "A10", "C", "C10", "E", "E10") 340 mustScanOK(t, store, "", 4, 10, "A", "A10", "C", "C10", "E", "E10") 341 mustScanOK(t, store, "A", 3, 10, "A", "A10", "C", "C10", "E", "E10") 342 mustScanOK(t, store, "A\x00", 3, 10, "C", "C10", "E", "E10") 343 mustScanOK(t, store, "C", 4, 10, "C", "C10", "E", "E10") 344 mustScanOK(t, store, "F", 1, 10) 345 mustRangeScanOK(t, store, "", "E", 5, 10, "A", "A10", "C", "C10") 346 mustRangeScanOK(t, store, "", "C\x00", 5, 10, "A", "A10", "C", "C10") 347 mustRangeScanOK(t, store, "A\x00", "C", 5, 10) 348 } 349 checkV10() 350 351 // ver20: A(10) - B(20) - C(10) - D(20) - E(10) 352 mustPutOK(t, store, "B", "B20", 15, 20) 353 mustPutOK(t, store, "D", "D20", 15, 20) 354 355 checkV20 := func() { 356 mustScanOK(t, store, "", 5, 20, "A", "A10", "B", "B20", "C", "C10", "D", "D20", "E", "E10") 357 mustScanOK(t, store, "C", 5, 20, "C", "C10", "D", "D20", "E", "E10") 358 mustScanOK(t, store, "D\x00", 1, 20, "E", "E10") 359 mustRangeScanOK(t, store, "B", "D", 5, 20, "B", "B20", "C", "C10") 360 mustRangeScanOK(t, store, "B", "D\x00", 5, 20, "B", "B20", "C", "C10", "D", "D20") 361 mustRangeScanOK(t, store, "B\x00", "D\x00", 5, 20, "C", "C10", "D", "D20") 362 } 363 checkV10() 364 checkV20() 365 366 // ver30: A(_) - B(20) - C(10) - D(_) - E(10) 367 mustDeleteOK(t, store, "A", 25, 30) 368 mustDeleteOK(t, store, "D", 25, 30) 369 370 checkV30 := func() { 371 mustScanOK(t, store, "", 5, 30, "B", "B20", "C", "C10", "E", "E10") 372 mustScanOK(t, store, "A", 1, 30, "B", "B20") 373 mustScanOK(t, store, "C\x00", 5, 30, "E", "E10") 374 } 375 checkV10() 376 checkV20() 377 checkV30() 378 379 // ver40: A(_) - B(_) - C(40) - D(40) - E(10) 380 mustDeleteOK(t, store, "B", 35, 40) 381 mustPutOK(t, store, "C", "C40", 35, 40) 382 mustPutOK(t, store, "D", "D40", 35, 40) 383 384 checkV40 := func() { 385 mustScanOK(t, store, "", 5, 40, "C", "C40", "D", "D40", "E", "E10") 386 mustScanOK(t, store, "", 5, 100, "C", "C40", "D", "D40", "E", "E10") 387 } 388 checkV10() 389 checkV20() 390 checkV30() 391 checkV40() 392 } 393 394 func TestBatchGet(t *testing.T) { 395 assert := assert.New(t) 396 store, err := NewMVCCLevelDB("") 397 require.Nil(t, err) 398 defer store.Close() 399 400 mustPutOK(t, store, "k1", "v1", 1, 2) 401 mustPutOK(t, store, "k2", "v2", 1, 2) 402 mustPutOK(t, store, "k2", "v2", 3, 4) 403 mustPutOK(t, store, "k3", "v3", 1, 2) 404 batchKeys := [][]byte{[]byte("k1"), []byte("k2"), []byte("k3")} 405 pairs := store.BatchGet(batchKeys, 5, kvrpcpb.IsolationLevel_SI, nil) 406 for _, pair := range pairs { 407 assert.Nil(pair.Err) 408 } 409 assert.Equal(string(pairs[0].Value), "v1") 410 assert.Equal(string(pairs[1].Value), "v2") 411 assert.Equal(string(pairs[2].Value), "v3") 412 } 413 414 func TestScanLock(t *testing.T) { 415 assert := assert.New(t) 416 store, err := NewMVCCLevelDB("") 417 require.Nil(t, err) 418 defer store.Close() 419 420 mustPutOK(t, store, "k1", "v1", 1, 2) 421 mustPrewriteOK(t, store, putMutations("p1", "v5", "s1", "v5"), "p1", 5) 422 mustPrewriteOK(t, store, putMutations("p2", "v10", "s2", "v10"), "p2", 10) 423 mustPrewriteOK(t, store, putMutations("p3", "v20", "s3", "v20"), "p3", 20) 424 425 locks, err := store.ScanLock([]byte("a"), []byte("r"), 12) 426 assert.Nil(err) 427 assert.Equal(locks, []*kvrpcpb.LockInfo{ 428 lock("p1", "p1", 5), 429 lock("p2", "p2", 10), 430 }) 431 432 mustScanLock(t, store, 10, []*kvrpcpb.LockInfo{ 433 lock("p1", "p1", 5), 434 lock("p2", "p2", 10), 435 lock("s1", "p1", 5), 436 lock("s2", "p2", 10), 437 }) 438 } 439 440 func TestScanWithResolvedLock(t *testing.T) { 441 assert := assert.New(t) 442 store, err := NewMVCCLevelDB("") 443 require.Nil(t, err) 444 defer store.Close() 445 446 mustPrewriteOK(t, store, putMutations("p1", "v5", "s1", "v5"), "p1", 5) 447 mustPrewriteOK(t, store, putMutations("p2", "v10", "s2", "v10"), "p1", 5) 448 449 pairs := store.Scan([]byte("p1"), nil, 3, 10, kvrpcpb.IsolationLevel_SI, nil) 450 lock, ok := errors.Cause(pairs[0].Err).(*ErrLocked) 451 assert.True(ok) 452 _, ok = errors.Cause(pairs[1].Err).(*ErrLocked) 453 assert.True(ok) 454 455 // Mock the request after resolving lock. 456 pairs = store.Scan([]byte("p1"), nil, 3, 10, kvrpcpb.IsolationLevel_SI, []uint64{lock.StartTS}) 457 for _, pair := range pairs { 458 assert.Nil(pair.Err) 459 } 460 } 461 462 func TestCommitConflict(t *testing.T) { 463 assert := assert.New(t) 464 store, err := NewMVCCLevelDB("") 465 require.Nil(t, err) 466 defer store.Close() 467 468 // txn A want set x to A 469 // txn B want set x to B 470 // A prewrite. 471 mustPrewriteOK(t, store, putMutations("x", "A"), "x", 5) 472 // B prewrite and find A's lock. 473 req := &kvrpcpb.PrewriteRequest{ 474 Mutations: putMutations("x", "B"), 475 PrimaryLock: []byte("x"), 476 StartVersion: 10, 477 } 478 errs := store.Prewrite(req) 479 assert.NotNil(errs[0]) 480 // B find rollback A because A exist too long. 481 mustRollbackOK(t, store, [][]byte{[]byte("x")}, 5) 482 // if A commit here, it would find its lock removed, report error txn not found. 483 mustCommitErr(t, store, [][]byte{[]byte("x")}, 5, 10) 484 // B prewrite itself after it rollback A. 485 mustPrewriteOK(t, store, putMutations("x", "B"), "x", 10) 486 // if A commit here, it would find its lock replaced by others and commit fail. 487 mustCommitErr(t, store, [][]byte{[]byte("x")}, 5, 20) 488 // B commit success. 489 mustCommitOK(t, store, [][]byte{[]byte("x")}, 10, 20) 490 // if B commit again, it will success because the key already committed. 491 mustCommitOK(t, store, [][]byte{[]byte("x")}, 10, 20) 492 } 493 494 func TestResolveLock(t *testing.T) { 495 store, err := NewMVCCLevelDB("") 496 require.Nil(t, err) 497 defer store.Close() 498 499 mustPrewriteOK(t, store, putMutations("p1", "v5", "s1", "v5"), "p1", 5) 500 mustPrewriteOK(t, store, putMutations("p2", "v10", "s2", "v10"), "p2", 10) 501 mustResolveLock(t, store, 5, 0) 502 mustResolveLock(t, store, 10, 20) 503 mustGetNone(t, store, "p1", 20) 504 mustGetNone(t, store, "s1", 30) 505 mustGetOK(t, store, "p2", 20, "v10") 506 mustGetOK(t, store, "s2", 30, "v10") 507 mustScanLock(t, store, 30, nil) 508 } 509 510 func TestBatchResolveLock(t *testing.T) { 511 store, err := NewMVCCLevelDB("") 512 require.Nil(t, err) 513 defer store.Close() 514 515 mustPrewriteOK(t, store, putMutations("p1", "v11", "s1", "v11"), "p1", 11) 516 mustPrewriteOK(t, store, putMutations("p2", "v12", "s2", "v12"), "p2", 12) 517 mustPrewriteOK(t, store, putMutations("p3", "v13"), "p3", 13) 518 mustPrewriteOK(t, store, putMutations("p4", "v14", "s3", "v14", "s4", "v14"), "p4", 14) 519 mustPrewriteOK(t, store, putMutations("p5", "v15", "s5", "v15"), "p5", 15) 520 txnInfos := map[uint64]uint64{ 521 11: 0, 522 12: 22, 523 13: 0, 524 14: 24, 525 } 526 mustBatchResolveLock(t, store, txnInfos) 527 mustGetNone(t, store, "p1", 20) 528 mustGetNone(t, store, "p3", 30) 529 mustGetOK(t, store, "p2", 30, "v12") 530 mustGetOK(t, store, "s4", 30, "v14") 531 mustScanLock(t, store, 30, []*kvrpcpb.LockInfo{ 532 lock("p5", "p5", 15), 533 lock("s5", "p5", 15), 534 }) 535 txnInfos = map[uint64]uint64{ 536 15: 0, 537 } 538 mustBatchResolveLock(t, store, txnInfos) 539 mustScanLock(t, store, 30, nil) 540 } 541 542 func TestGC(t *testing.T) { 543 store, err := NewMVCCLevelDB("") 544 require.Nil(t, err) 545 defer store.Close() 546 var safePoint uint64 = 100 547 548 // Prepare data 549 mustPutOK(t, store, "k1", "v1", 1, 2) 550 mustPutOK(t, store, "k1", "v2", 11, 12) 551 552 mustPutOK(t, store, "k2", "v1", 1, 2) 553 mustPutOK(t, store, "k2", "v2", 11, 12) 554 mustPutOK(t, store, "k2", "v3", 101, 102) 555 556 mustPutOK(t, store, "k3", "v1", 1, 2) 557 mustPutOK(t, store, "k3", "v2", 11, 12) 558 mustDeleteOK(t, store, "k3", 101, 102) 559 560 mustPutOK(t, store, "k4", "v1", 1, 2) 561 mustDeleteOK(t, store, "k4", 11, 12) 562 563 // Check prepared data 564 mustGetOK(t, store, "k1", 5, "v1") 565 mustGetOK(t, store, "k1", 15, "v2") 566 mustGetOK(t, store, "k2", 5, "v1") 567 mustGetOK(t, store, "k2", 15, "v2") 568 mustGetOK(t, store, "k2", 105, "v3") 569 mustGetOK(t, store, "k3", 5, "v1") 570 mustGetOK(t, store, "k3", 15, "v2") 571 mustGetNone(t, store, "k3", 105) 572 mustGetOK(t, store, "k4", 5, "v1") 573 mustGetNone(t, store, "k4", 105) 574 575 mustGC(t, store, safePoint) 576 577 mustGetNone(t, store, "k1", 5) 578 mustGetOK(t, store, "k1", 15, "v2") 579 mustGetNone(t, store, "k2", 5) 580 mustGetOK(t, store, "k2", 15, "v2") 581 mustGetOK(t, store, "k2", 105, "v3") 582 mustGetNone(t, store, "k3", 5) 583 mustGetOK(t, store, "k3", 15, "v2") 584 mustGetNone(t, store, "k3", 105) 585 mustGetNone(t, store, "k4", 5) 586 mustGetNone(t, store, "k4", 105) 587 } 588 589 func TestRollbackAndWriteConflict(t *testing.T) { 590 store, err := NewMVCCLevelDB("") 591 require.Nil(t, err) 592 defer store.Close() 593 594 mustPutOK(t, store, "test", "test", 1, 3) 595 req := &kvrpcpb.PrewriteRequest{ 596 Mutations: putMutations("lock", "lock", "test", "test1"), 597 PrimaryLock: []byte("test"), 598 StartVersion: 2, 599 LockTtl: 2, 600 } 601 errs := store.Prewrite(req) 602 mustWriteWriteConflict(t, errs, 1) 603 604 mustPutOK(t, store, "test", "test2", 5, 8) 605 606 // simulate `getTxnStatus` for txn 2. 607 assert.Nil(t, store.Cleanup([]byte("test"), 2, math.MaxUint64)) 608 req = &kvrpcpb.PrewriteRequest{ 609 Mutations: putMutations("test", "test3"), 610 PrimaryLock: []byte("test"), 611 StartVersion: 6, 612 LockTtl: 1, 613 } 614 errs = store.Prewrite(req) 615 mustWriteWriteConflict(t, errs, 0) 616 } 617 618 func TestDeleteRange(t *testing.T) { 619 store, err := NewMVCCLevelDB("") 620 require.Nil(t, err) 621 defer store.Close() 622 623 for i := 1; i <= 5; i++ { 624 key := string(byte(i) + byte('0')) 625 value := "v" + key 626 mustPutOK(t, store, key, value, uint64(1+2*i), uint64(2+2*i)) 627 } 628 629 mustScanOK(t, store, "0", 10, 20, "1", "v1", "2", "v2", "3", "v3", "4", "v4", "5", "v5") 630 631 mustDeleteRange(t, store, "2", "4") 632 mustScanOK(t, store, "0", 10, 30, "1", "v1", "4", "v4", "5", "v5") 633 634 mustDeleteRange(t, store, "5", "5") 635 mustScanOK(t, store, "0", 10, 40, "1", "v1", "4", "v4", "5", "v5") 636 637 mustDeleteRange(t, store, "41", "42") 638 mustScanOK(t, store, "0", 10, 50, "1", "v1", "4", "v4", "5", "v5") 639 640 mustDeleteRange(t, store, "4\x00", "5\x00") 641 mustScanOK(t, store, "0", 10, 60, "1", "v1", "4", "v4") 642 643 mustDeleteRange(t, store, "0", "9") 644 mustScanOK(t, store, "0", 10, 70) 645 } 646 647 func mustWriteWriteConflict(t *testing.T, errs []error, i int) { 648 assert.NotNil(t, errs[i]) 649 _, ok := errs[i].(*ErrConflict) 650 assert.True(t, ok) 651 } 652 653 func TestRC(t *testing.T) { 654 store, err := NewMVCCLevelDB("") 655 require.Nil(t, err) 656 defer store.Close() 657 658 mustPutOK(t, store, "key", "v1", 5, 10) 659 mustPrewriteOK(t, store, putMutations("key", "v2"), "key", 15) 660 mustGetErr(t, store, "key", 20) 661 mustGetRC(t, store, "key", 12, "v1") 662 mustGetRC(t, store, "key", 20, "v1") 663 } 664 665 func TestCheckTxnStatus(t *testing.T) { 666 store, err := NewMVCCLevelDB("") 667 require.Nil(t, err) 668 defer store.Close() 669 assert := assert.New(t) 670 671 startTS := uint64(5 << 18) 672 mustPrewriteWithTTLOK(t, store, putMutations("pk", "val"), "pk", startTS, 666) 673 674 ttl, commitTS, action, err := store.CheckTxnStatus([]byte("pk"), startTS, startTS+100, 666, false, false) 675 assert.Nil(err) 676 assert.Equal(ttl, uint64(666)) 677 assert.Equal(commitTS, uint64(0)) 678 assert.Equal(action, kvrpcpb.Action_MinCommitTSPushed) 679 680 // MaxUint64 as callerStartTS shouldn't update minCommitTS but return Action_MinCommitTSPushed. 681 ttl, commitTS, action, err = store.CheckTxnStatus([]byte("pk"), startTS, math.MaxUint64, 666, false, false) 682 assert.Nil(err) 683 assert.Equal(ttl, uint64(666)) 684 assert.Equal(commitTS, uint64(0)) 685 assert.Equal(action, kvrpcpb.Action_MinCommitTSPushed) 686 mustCommitOK(t, store, [][]byte{[]byte("pk")}, startTS, startTS+101) 687 688 ttl, commitTS, _, err = store.CheckTxnStatus([]byte("pk"), startTS, 0, 666, false, false) 689 assert.Nil(err) 690 assert.Equal(ttl, uint64(0)) 691 assert.Equal(commitTS, startTS+101) 692 693 mustPrewriteWithTTLOK(t, store, putMutations("pk1", "val"), "pk1", startTS, 666) 694 mustRollbackOK(t, store, [][]byte{[]byte("pk1")}, startTS) 695 696 ttl, commitTS, action, err = store.CheckTxnStatus([]byte("pk1"), startTS, 0, 666, false, false) 697 assert.Nil(err) 698 assert.Equal(ttl, uint64(0)) 699 assert.Equal(commitTS, uint64(0)) 700 assert.Equal(action, kvrpcpb.Action_NoAction) 701 702 mustPrewriteWithTTLOK(t, store, putMutations("pk2", "val"), "pk2", startTS, 666) 703 currentTS := uint64(777 << 18) 704 ttl, commitTS, action, err = store.CheckTxnStatus([]byte("pk2"), startTS, 0, currentTS, false, false) 705 assert.Nil(err) 706 assert.Equal(ttl, uint64(0)) 707 assert.Equal(commitTS, uint64(0)) 708 assert.Equal(action, kvrpcpb.Action_TTLExpireRollback) 709 710 // Cover the TxnNotFound case. 711 _, _, _, err = store.CheckTxnStatus([]byte("txnNotFound"), 5, 0, 666, false, false) 712 assert.NotNil(err) 713 notFound, ok := errors.Cause(err).(*ErrTxnNotFound) 714 assert.True(ok) 715 assert.Equal(notFound.StartTs, uint64(5)) 716 assert.Equal(string(notFound.PrimaryKey), "txnNotFound") 717 718 ttl, commitTS, action, err = store.CheckTxnStatus([]byte("txnNotFound"), 5, 0, 666, true, false) 719 assert.Nil(err) 720 assert.Equal(ttl, uint64(0)) 721 assert.Equal(commitTS, uint64(0)) 722 assert.Equal(action, kvrpcpb.Action_LockNotExistRollback) 723 724 // Check the rollback tombstone blocks this prewrite which comes with a smaller startTS. 725 req := &kvrpcpb.PrewriteRequest{ 726 Mutations: putMutations("txnNotFound", "val"), 727 PrimaryLock: []byte("txnNotFound"), 728 StartVersion: 4, 729 MinCommitTs: 6, 730 } 731 errs := store.Prewrite(req) 732 assert.NotNil(errs) 733 } 734 735 func TestRejectCommitTS(t *testing.T) { 736 store, err := NewMVCCLevelDB("") 737 require.Nil(t, err) 738 defer store.Close() 739 mustPrewriteOK(t, store, putMutations("x", "A"), "x", 5) 740 // Push the minCommitTS 741 _, _, _, err = store.CheckTxnStatus([]byte("x"), 5, 100, 100, false, false) 742 assert.Nil(t, err) 743 err = store.Commit([][]byte{[]byte("x")}, 5, 10) 744 e, ok := errors.Cause(err).(*ErrCommitTSExpired) 745 assert.True(t, ok) 746 assert.Equal(t, e.MinCommitTs, uint64(101)) 747 } 748 749 func TestMvccGetByKey(t *testing.T) { 750 store, err := NewMVCCLevelDB("") 751 require.Nil(t, err) 752 defer store.Close() 753 754 mustPrewriteOK(t, store, putMutations("q1", "v5"), "p1", 5) 755 var istore interface{} = store 756 debugger, ok := istore.(MVCCDebugger) 757 assert.True(t, ok) 758 mvccInfo := debugger.MvccGetByKey([]byte("q1")) 759 except := &kvrpcpb.MvccInfo{ 760 Lock: &kvrpcpb.MvccLock{ 761 Type: kvrpcpb.Op_Put, 762 StartTs: 5, 763 Primary: []byte("p1"), 764 ShortValue: []byte("v5"), 765 }, 766 } 767 assert.Equal(t, mvccInfo, except) 768 } 769 770 func TestTxnHeartBeat(t *testing.T) { 771 store, err := NewMVCCLevelDB("") 772 require.Nil(t, err) 773 defer store.Close() 774 assert := assert.New(t) 775 776 mustPrewriteWithTTLOK(t, store, putMutations("pk", "val"), "pk", 5, 666) 777 778 // Update the ttl 779 ttl, err := store.TxnHeartBeat([]byte("pk"), 5, 888) 780 assert.Nil(err) 781 assert.Greater(ttl, uint64(666)) 782 783 // Advise ttl is small 784 ttl, err = store.TxnHeartBeat([]byte("pk"), 5, 300) 785 assert.Nil(err) 786 assert.Greater(ttl, uint64(300)) 787 788 // The lock has already been clean up 789 assert.Nil(store.Cleanup([]byte("pk"), 5, math.MaxUint64)) 790 _, err = store.TxnHeartBeat([]byte("pk"), 5, 1000) 791 assert.NotNil(err) 792 }