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  }