talent-plan-tinykv/kv/transaction/commands4b_test.go
Rich 15838152aa fix invalid order of expected and actual in kv/server/server_test.go (#141)
* fix invalid order of expected and actual in tests

Co-authored-by: Connor <zbk602423539@gmail.com>
2020-04-30 15:31:26 +08:00

597 lines
22 KiB
Go

package transaction
import (
"testing"
"github.com/pingcap-incubator/tinykv/kv/transaction/mvcc"
"github.com/pingcap-incubator/tinykv/kv/util/engine_util"
"github.com/pingcap-incubator/tinykv/proto/pkg/kvrpcpb"
"github.com/stretchr/testify/assert"
)
// TestGetValue4B getting a value works in the simple case.
func TestGetValue4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
})
var req kvrpcpb.GetRequest
req.Key = []byte{99}
req.Version = mvcc.TsMax
resp := builder.runOneRequest(&req).(*kvrpcpb.GetResponse)
assert.Nil(t, resp.RegionError)
assert.Nil(t, resp.Error)
assert.Equal(t, []byte{42}, resp.Value)
}
// TestGetValueTs4B getting a value works with different timestamps.
func TestGetValueTs4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
})
var req0 kvrpcpb.GetRequest
req0.Key = []byte{99}
req0.Version = 100
var req1 kvrpcpb.GetRequest
req1.Key = []byte{99}
req1.Version = 100
var req2 kvrpcpb.GetRequest
req2.Key = []byte{99}
req2.Version = 100
resps := builder.runRequests(&req0, &req1, &req2)
resp0 := resps[0].(*kvrpcpb.GetResponse)
resp1 := resps[1].(*kvrpcpb.GetResponse)
resp2 := resps[2].(*kvrpcpb.GetResponse)
assert.Nil(t, resp0.RegionError)
assert.Nil(t, resp0.Error)
assert.Equal(t, []byte{42}, resp0.Value)
assert.Nil(t, resp1.RegionError)
assert.Nil(t, resp1.Error)
assert.Equal(t, []byte{42}, resp1.Value)
assert.Nil(t, resp2.RegionError)
assert.Nil(t, resp2.Error)
assert.Equal(t, []byte{42}, resp2.Value)
}
// TestGetEmpty4B tests that get on an empty DB.
func TestGetEmpty4B(t *testing.T) {
builder := newBuilder(t)
var req kvrpcpb.GetRequest
req.Key = []byte{100}
req.Version = mvcc.TsMax
resp := builder.runOneRequest(&req).(*kvrpcpb.GetResponse)
assert.Nil(t, resp.RegionError)
assert.Nil(t, resp.Error)
assert.True(t, resp.NotFound)
}
// TestGetNone4B tests that getting a missing key works.
func TestGetNone4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
{cf: engine_util.CfDefault, key: []byte{101}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{101}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
})
var req kvrpcpb.GetRequest
req.Key = []byte{100}
req.Version = mvcc.TsMax
resp := builder.runOneRequest(&req).(*kvrpcpb.GetResponse)
assert.Nil(t, resp.RegionError)
assert.Nil(t, resp.Error)
assert.True(t, resp.NotFound)
}
// TestGetVersions4B tests we get the correct value when there are multiple versions.
func TestGetVersions4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
{cf: engine_util.CfDefault, key: []byte{99}, ts: 60, value: []byte{43}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 66, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 60}},
{cf: engine_util.CfDefault, key: []byte{99}, ts: 120, value: []byte{44}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 122, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 120}},
})
var req0 kvrpcpb.GetRequest
req0.Key = []byte{99}
req0.Version = 40
var req1 kvrpcpb.GetRequest
req1.Key = []byte{99}
req1.Version = 56
var req2 kvrpcpb.GetRequest
req2.Key = []byte{99}
req2.Version = 60
var req3 kvrpcpb.GetRequest
req3.Key = []byte{99}
req3.Version = 65
var req4 kvrpcpb.GetRequest
req4.Key = []byte{99}
req4.Version = 66
var req5 kvrpcpb.GetRequest
req5.Key = []byte{99}
req5.Version = 100
resps := builder.runRequests(&req0, &req1, &req2, &req3, &req4, &req5)
resp0 := resps[0].(*kvrpcpb.GetResponse)
resp1 := resps[1].(*kvrpcpb.GetResponse)
resp2 := resps[2].(*kvrpcpb.GetResponse)
resp3 := resps[3].(*kvrpcpb.GetResponse)
resp4 := resps[4].(*kvrpcpb.GetResponse)
resp5 := resps[5].(*kvrpcpb.GetResponse)
assert.Nil(t, resp0.RegionError)
assert.Nil(t, resp0.Error)
assert.True(t, resp0.NotFound)
assert.Nil(t, resp1.RegionError)
assert.Nil(t, resp1.Error)
assert.Equal(t, []byte{42}, resp1.Value)
assert.Nil(t, resp2.RegionError)
assert.Nil(t, resp2.Error)
assert.Equal(t, []byte{42}, resp2.Value)
assert.Nil(t, resp3.RegionError)
assert.Nil(t, resp3.Error)
assert.Equal(t, []byte{42}, resp3.Value)
assert.Nil(t, resp4.RegionError)
assert.Nil(t, resp4.Error)
assert.Equal(t, []byte{43}, resp4.Value)
assert.Nil(t, resp5.RegionError)
assert.Nil(t, resp5.Error)
assert.Equal(t, []byte{43}, resp5.Value)
}
// TestGetDeleted4B tests we get the correct value when there are multiple versions, including a deletion.
func TestGetDeleted4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
{cf: engine_util.CfDefault, key: []byte{99}, ts: 60, value: nil},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 66, value: []byte{2, 0, 0, 0, 0, 0, 0, 0, 60}},
{cf: engine_util.CfDefault, key: []byte{99}, ts: 120, value: []byte{44}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 122, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 120}},
})
var req0 kvrpcpb.GetRequest
req0.Key = []byte{99}
req0.Version = 54
var req1 kvrpcpb.GetRequest
req1.Key = []byte{99}
req1.Version = 60
var req2 kvrpcpb.GetRequest
req2.Key = []byte{99}
req2.Version = 65
var req3 kvrpcpb.GetRequest
req3.Key = []byte{99}
req3.Version = 66
var req4 kvrpcpb.GetRequest
req4.Key = []byte{99}
req4.Version = 67
var req5 kvrpcpb.GetRequest
req5.Key = []byte{99}
req5.Version = 122
resps := builder.runRequests(&req0, &req1, &req2, &req3, &req4, &req5)
resp0 := resps[0].(*kvrpcpb.GetResponse)
resp1 := resps[1].(*kvrpcpb.GetResponse)
resp2 := resps[2].(*kvrpcpb.GetResponse)
resp3 := resps[3].(*kvrpcpb.GetResponse)
resp4 := resps[4].(*kvrpcpb.GetResponse)
resp5 := resps[5].(*kvrpcpb.GetResponse)
assert.Nil(t, resp0.RegionError)
assert.Nil(t, resp0.Error)
assert.Equal(t, []byte{42}, resp0.Value)
assert.Nil(t, resp1.RegionError)
assert.Nil(t, resp1.Error)
assert.Equal(t, []byte{42}, resp1.Value)
assert.Nil(t, resp2.RegionError)
assert.Nil(t, resp2.Error)
assert.Equal(t, []byte{42}, resp2.Value)
assert.Nil(t, resp3.RegionError)
assert.Nil(t, resp3.Error)
assert.True(t, resp3.NotFound)
assert.Nil(t, resp4.RegionError)
assert.Nil(t, resp4.Error)
assert.True(t, resp4.NotFound)
assert.Nil(t, resp5.RegionError)
assert.Nil(t, resp5.Error)
assert.Equal(t, []byte{44}, resp5.Value)
}
// TestGetLocked4B tests getting a value when it is locked by another transaction.
func TestGetLocked4B(t *testing.T) {
builder := newBuilder(t)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{99}, ts: 50, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{99}, ts: 54, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 50}},
{cf: engine_util.CfLock, key: []byte{99}, value: []byte{99, 1, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0}},
})
var req0 kvrpcpb.GetRequest
req0.Key = []byte{99}
req0.Version = 55
var req1 kvrpcpb.GetRequest
req1.Key = []byte{99}
req1.Version = 300
resps := builder.runRequests(&req0, &req1)
resp0 := resps[0].(*kvrpcpb.GetResponse)
resp1 := resps[1].(*kvrpcpb.GetResponse)
assert.Nil(t, resp0.RegionError)
assert.Nil(t, resp0.Error)
assert.Equal(t, []byte{42}, resp0.Value)
assert.Nil(t, resp1.RegionError)
lockInfo := resp1.Error.Locked
assert.Equal(t, []byte{99}, lockInfo.Key)
assert.Equal(t, []byte{99}, lockInfo.PrimaryLock)
assert.Equal(t, uint64(200), lockInfo.LockVersion)
}
// TestEmptyPrewrite4B tests that a Prewrite with no mutations succeeds and changes nothing.
func TestEmptyPrewrite4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest()
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Empty(t, resp.Errors)
assert.Nil(t, resp.RegionError)
builder.assertLen(engine_util.CfDefault, 0)
}
// TestSinglePrewrite4B tests a prewrite with one write, it should succeed, we test all the expected values.
func TestSinglePrewrite4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put))
cmd.LockTtl = 1000
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Empty(t, resp.Errors)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 1, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 3, 232}},
})
}
// TestPrewriteLocked4B tests that two prewrites to the same key causes a lock error.
func TestPrewriteLocked4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put))
cmd2 := builder.prewriteRequest(mutation(3, []byte{53}, kvrpcpb.Op_Put))
resps := builder.runRequests(cmd, cmd2)
assert.Empty(t, resps[0].(*kvrpcpb.PrewriteResponse).Errors)
assert.Nil(t, resps[0].(*kvrpcpb.PrewriteResponse).RegionError)
assert.Equal(t, 1, len(resps[1].(*kvrpcpb.PrewriteResponse).Errors))
assert.Nil(t, resps[1].(*kvrpcpb.PrewriteResponse).RegionError)
builder.assertLens(1, 1, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
})
}
// TestPrewriteWritten4B tests an attempted prewrite with a write conflict.
func TestPrewriteWritten4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put))
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80, value: []byte{5}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 101, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Equal(t, 1, len(resp.Errors))
assert.NotNil(t, resp.Errors[0].Conflict)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80, value: []byte{5}},
})
}
// TestPrewriteWrittenNoConflict4B tests an attempted prewrite with a write already present, but no conflict.
func TestPrewriteWrittenNoConflict4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put))
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80, value: []byte{5}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 90, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Empty(t, resp.Errors)
assert.Nil(t, resp.RegionError)
assert.Nil(t, resp.RegionError)
builder.assertLens(2, 1, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{5}, ts: 80},
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
})
}
// TestMultiplePrewrites4B tests that multiple prewrites to different keys succeeds.
func TestMultiplePrewrites4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put))
cmd2 := builder.prewriteRequest(mutation(4, []byte{53}, kvrpcpb.Op_Put))
resps := builder.runRequests(cmd, cmd2)
assert.Empty(t, resps[0].(*kvrpcpb.PrewriteResponse).Errors)
assert.Nil(t, resps[0].(*kvrpcpb.PrewriteResponse).RegionError)
assert.Empty(t, resps[1].(*kvrpcpb.PrewriteResponse).Errors)
assert.Nil(t, resps[1].(*kvrpcpb.PrewriteResponse).RegionError)
builder.assertLens(2, 2, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{4}, ts: 101, value: []byte{53}},
{cf: engine_util.CfLock, key: []byte{4}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0}},
})
}
// TestPrewriteOverwrite4B tests that two writes in the same prewrite succeed and we see the second write.
func TestPrewriteOverwrite4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(mutation(3, []byte{42}, kvrpcpb.Op_Put), mutation(3, []byte{45}, kvrpcpb.Op_Put))
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Empty(t, resp.Errors)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 1, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{45}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
})
}
// TestPrewriteMultiple4B tests that a prewrite with multiple mutations succeeds.
func TestPrewriteMultiple4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.prewriteRequest(
mutation(3, []byte{42}, kvrpcpb.Op_Put),
mutation(4, []byte{43}, kvrpcpb.Op_Put),
mutation(5, []byte{44}, kvrpcpb.Op_Put),
mutation(4, nil, kvrpcpb.Op_Del),
mutation(4, []byte{1, 3, 5}, kvrpcpb.Op_Put),
mutation(255, []byte{45}, kvrpcpb.Op_Put),
)
resp := builder.runOneRequest(cmd).(*kvrpcpb.PrewriteResponse)
assert.Empty(t, resp.Errors)
assert.Nil(t, resp.RegionError)
builder.assertLens(4, 4, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{4}, value: []byte{1, 3, 5}},
})
}
// TestEmptyCommit4B tests a commit request with no keys to commit.
func TestEmptyCommit4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([][]byte{}...)
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(0, 0, 0)
}
// TestSimpleCommit4B tests committing a single key.
func TestSingleCommit4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfDefault, key: []byte{3}},
})
}
// TestCommitOverwrite4B tests committing where there is already a write.
func TestCommitOverwrite4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
// A previous, committed write.
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80, value: []byte{15}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 84, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
// The current, pre-written write.
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(2, 0, 2)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfDefault, key: []byte{3}},
})
}
// TestCommitMultipleKeys4B tests committing multiple keys in the same commit. Also puts some other data in the DB and test
// that it is unchanged.
func TestCommitMultipleKeys4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3}, []byte{12, 4, 0}, []byte{15})
builder.init([]kv{
// Current, pre-written.
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{12, 4, 0}, value: []byte{1, 1, 0, 0, 1, 5}},
{cf: engine_util.CfLock, key: []byte{12, 4, 0}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{15}, value: []byte{0}},
{cf: engine_util.CfLock, key: []byte{15}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
// Some committed data.
{cf: engine_util.CfDefault, key: []byte{4}, ts: 80, value: []byte{15}},
{cf: engine_util.CfWrite, key: []byte{4}, ts: 84, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{cf: engine_util.CfDefault, key: []byte{3, 0}, ts: 80, value: []byte{150}},
{cf: engine_util.CfWrite, key: []byte{3, 0}, ts: 84, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
// Another pre-written transaction.
{cf: engine_util.CfDefault, key: []byte{2}, ts: 99, value: []byte{0, 0, 0, 8}},
{cf: engine_util.CfLock, key: []byte{2}, value: []byte{1, 2, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{43, 6}, ts: 99, value: []byte{1, 1, 0, 0, 1, 5}},
{cf: engine_util.CfLock, key: []byte{43, 6}, value: []byte{1, 2, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(7, 2, 5)
builder.assert([]kv{
// The newly committed data.
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfWrite, key: []byte{12, 4, 0}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfWrite, key: []byte{15}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
// Committed data is untouched.
{cf: engine_util.CfDefault, key: []byte{4}, ts: 80},
{cf: engine_util.CfWrite, key: []byte{4}, ts: 84},
{cf: engine_util.CfDefault, key: []byte{3, 0}, ts: 80},
{cf: engine_util.CfWrite, key: []byte{3, 0}, ts: 84},
// Pre-written data is untouched.
{cf: engine_util.CfDefault, key: []byte{2}, ts: 99},
{cf: engine_util.CfLock, key: []byte{2}},
{cf: engine_util.CfDefault, key: []byte{43, 6}, ts: 99},
{cf: engine_util.CfLock, key: []byte{43, 6}},
})
}
// TestRecommitKey4B tests committing the same key multiple times in one commit.
func TestRecommitKey4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3}, []byte{3})
builder.init([]kv{
// The current, pre-written write.
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfDefault, key: []byte{3}},
})
}
// TestCommitConflictRollback4B tests committing a rolled back transaction.
func TestCommitConflictRollback4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(0, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110},
})
}
// TestCommitConflictRace4B tests committing where a key is pre-written by a different transaction.
func TestCommitConflictRace4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 90, value: []byte{110}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 3, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.NotNil(t, resp.Error.Retryable)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 1, 0)
builder.assert([]kv{
{cf: engine_util.CfLock, key: []byte{3}},
{cf: engine_util.CfDefault, key: []byte{3}, ts: 90},
})
}
// TestCommitConflictRepeat4B tests recommitting a transaction (i.e., the same commit request is received twice).
func TestCommitConflictRepeat4B(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110},
{cf: engine_util.CfDefault, key: []byte{3}},
})
}
// TestCommitMissingPrewrite4a tests committing a transaction which was not prewritten (i.e., a request was lost, but
// the commit request was not).
func TestCommitMissingPrewrite4a(t *testing.T) {
builder := newBuilder(t)
cmd := builder.commitRequest([]byte{3})
builder.init([]kv{
// Some committed data.
{cf: engine_util.CfDefault, key: []byte{4}, ts: 80, value: []byte{15}},
{cf: engine_util.CfWrite, key: []byte{4}, ts: 84, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{cf: engine_util.CfDefault, key: []byte{3, 0}, ts: 80, value: []byte{150}},
{cf: engine_util.CfWrite, key: []byte{3, 0}, ts: 84, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
// Note no prewrite.
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CommitResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(2, 0, 2)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{4}, ts: 80},
{cf: engine_util.CfWrite, key: []byte{4}, ts: 84},
{cf: engine_util.CfDefault, key: []byte{3, 0}, ts: 80},
{cf: engine_util.CfWrite, key: []byte{3, 0}, ts: 84},
})
}