talent-plan-tinykv/kv/transaction/commands4c_test.go
Connor 5e089a2cd1 init course framework
Signed-off-by: Connor <zbk602423539@gmail.com>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: linning <linningde25@gmail.com>
Co-authored-by: YangKeao <keao.yang@yahoo.com>
Co-authored-by: andylokandy <andylokandy@hotmail.com>
Co-authored-by: Iosmanthus Teng <myosmanthustree@gmail.com>
2020-04-30 15:25:07 +08:00

485 lines
20 KiB
Go

package transaction
import (
"encoding/binary"
"testing"
"github.com/pingcap-incubator/tinykv/kv/util/engine_util"
"github.com/pingcap-incubator/tinykv/proto/pkg/kvrpcpb"
"github.com/stretchr/testify/assert"
)
// TestEmptyRollback4C tests a rollback with no keys.
func TestEmptyRollback4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([][]byte{}...)
resp := builder.runOneRequest(cmd).(*kvrpcpb.BatchRollbackResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(0, 0, 0)
}
// TestRollback4C tests a successful rollback.
func TestRollback4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]byte{3})
builder.init([]kv{
// See TestSinglePrewrite.
{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.BatchRollbackResponse)
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}, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
}
// TestRollbackDuplicateKeys4C tests a rollback which rolls back multiple keys, including one duplicated key.
func TestRollbackDuplicateKeys4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]byte{3}, []byte{15}, []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, 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}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.BatchRollbackResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(0, 0, 2)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfWrite, key: []byte{15}, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
}
// TestRollbackMissingPrewrite4C tests trying to roll back a missing prewrite.
func TestRollbackMissingPrewrite4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]byte{3})
resp := builder.runOneRequest(cmd).(*kvrpcpb.BatchRollbackResponse)
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}, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
}
// TestRollbackCommitted4C tests trying to roll back a transaction which is already committed.
func TestRollbackCommitted4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]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.BatchRollbackResponse)
assert.NotNil(t, resp.Error.Abort)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 110},
})
}
// TestRollbackDuplicate4C tests trying to roll back a transaction which has already been rolled back.
func TestRollbackDuplicate4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.BatchRollbackResponse)
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: 100},
})
}
// TestRollbackOtherTxn4C tests trying to roll back the wrong transaction.
func TestRollbackOtherTxn4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.rollbackRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 1, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.BatchRollbackResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 1, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 80},
{cf: engine_util.CfLock, key: []byte{3}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, builder.ts()}},
})
}
// TestCheckTxnStatusTtlExpired4C checks that if there is a lock and its ttl has expired, then it is rolled back.
func TestCheckTxnStatusTtlExpired4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.checkTxnStatusRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{3, 1, 0, 0, 5, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 8}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CheckTxnStatusResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, kvrpcpb.Action_TTLExpireRollback, resp.Action)
builder.assertLens(0, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs, value: []byte{3, 0, 0, 5, 0, 0, 0, 0, builder.ts()}},
})
}
// TestCheckTxnStatusTtlNotExpired4C checks that if there is a lock and its ttl has not expired, then nothing changes.
func TestCheckTxnStatusTtlNotExpired4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.checkTxnStatusRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{3, 1, 0, 0, 5, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 1, 0, 0, 0, 8}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CheckTxnStatusResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, kvrpcpb.Action_NoAction, resp.Action)
builder.assertLens(1, 1, 0)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs},
{cf: engine_util.CfLock, key: []byte{3}},
})
}
// TestCheckTxnStatusRolledBack4C tests checking a key which has already been rolled back..
func TestCheckTxnStatusRolledBack4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.checkTxnStatusRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs, value: []byte{3, 0, 0, 5, 0, 0, 0, 0, builder.ts()}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{3, 1, 0, 0, 8, 0, 0, 0, 0, builder.ts(), 0, 0, 0, 0, 0, 0, 0, 8}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CheckTxnStatusResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, kvrpcpb.Action_NoAction, resp.Action)
assert.Equal(t, uint64(0), resp.CommitVersion)
builder.assertLens(1, 1, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs},
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs},
{cf: engine_util.CfLock, key: []byte{3}},
})
}
// TestCheckTxnStatusCommitted4C tests checking a key which has already been committed.
func TestCheckTxnStatusCommitted4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.checkTxnStatusRequest([]byte{3})
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs, value: []byte{1, 0, 0, 5, 0, 0, 0, 0, builder.ts()}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CheckTxnStatusResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, kvrpcpb.Action_NoAction, resp.Action)
assert.Equal(t, binary.BigEndian.Uint64([]byte{0, 0, 5, 0, 0, 0, 0, builder.ts()}), resp.CommitVersion)
builder.assertLens(1, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: cmd.LockTs},
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs},
})
}
// TestCheckTxnStatusNoLockNoWrite4C checks if there is no data for the key, then we get the right response.
func TestCheckTxnStatusNoLockNoWrite4C(t *testing.T) {
builder := newBuilder(t)
cmd := builder.checkTxnStatusRequest([]byte{3})
resp := builder.runOneRequest(cmd).(*kvrpcpb.CheckTxnStatusResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, kvrpcpb.Action_LockNotExistRollback, resp.Action)
builder.assertLens(0, 0, 1)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: cmd.LockTs, value: []byte{3, 0, 0, 5, 0, 0, 0, 0, builder.ts()}},
})
}
// TestEmptyResolve4C tests a completely empty resolve request.
func TestEmptyResolve4C(t *testing.T) {
builder := newBuilder(t)
cmd := resolveRequest(0, 0)
resp := builder.runOneRequest(cmd).(*kvrpcpb.ResolveLockResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(0, 0, 0)
}
// TestResolveCommit4C should commit all keys in the specified transaction.
func TestResolveCommit4C(t *testing.T) {
builder := newBuilder(t)
cmd := resolveRequest(100, 120)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100, value: []byte{43}},
{cf: engine_util.CfLock, key: []byte{7}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110, value: []byte{44}},
{cf: engine_util.CfLock, key: []byte{200}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.ResolveLockResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(3, 1, 2)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{3}, ts: 120, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{7}, ts: 120, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110},
{cf: engine_util.CfLock, key: []byte{200}},
})
}
// TestResolveRollback4C should rollback all keys in the specified transaction.
func TestResolveRollback4C(t *testing.T) {
builder := newBuilder(t)
cmd := resolveRequest(100, 0)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfLock, key: []byte{3}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100, value: []byte{43}},
{cf: engine_util.CfLock, key: []byte{7}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110, value: []byte{44}},
{cf: engine_util.CfLock, key: []byte{200}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.ResolveLockResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(1, 1, 2)
builder.assert([]kv{
{cf: engine_util.CfWrite, key: []byte{3}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfWrite, key: []byte{7}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110},
{cf: engine_util.CfLock, key: []byte{200}},
})
}
// TestResolveCommitWritten4C tests a resolve where the matched keys are already committed or rolled back.
func TestResolveCommitWritten4C(t *testing.T) {
builder := newBuilder(t)
cmd := resolveRequest(100, 120)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 120, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100, value: []byte{43}},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110, value: []byte{44}},
{cf: engine_util.CfLock, key: []byte{200}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.ResolveLockResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(3, 1, 2)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 120},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 100},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110},
{cf: engine_util.CfLock, key: []byte{200}},
})
}
// TestResolveRollbackWritten4C tests a rollback resolve where data has already been committed or rolled back.
func TestResolveRollbackWritten4C(t *testing.T) {
builder := newBuilder(t)
cmd := resolveRequest(100, 0)
builder.init([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100, value: []byte{42}},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 120, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100, value: []byte{43}},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 100, value: []byte{3, 0, 0, 0, 0, 0, 0, 0, 100}},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110, value: []byte{44}},
{cf: engine_util.CfLock, key: []byte{200}, value: []byte{1, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0}},
})
resp := builder.runOneRequest(cmd).(*kvrpcpb.ResolveLockResponse)
assert.Nil(t, resp.Error)
assert.Nil(t, resp.RegionError)
builder.assertLens(3, 1, 2)
builder.assert([]kv{
{cf: engine_util.CfDefault, key: []byte{3}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 120},
{cf: engine_util.CfDefault, key: []byte{7}, ts: 100},
{cf: engine_util.CfWrite, key: []byte{201}, ts: 100},
{cf: engine_util.CfDefault, key: []byte{200}, ts: 110},
{cf: engine_util.CfLock, key: []byte{200}},
})
}
// TestScanEmpty4C tests a scan after the end of the DB.
func TestScanEmpty4C(t *testing.T) {
builder := builderForScan(t)
cmd := builder.scanRequest([]byte{200}, 10000)
resp := builder.runOneRequest(cmd).(*kvrpcpb.ScanResponse)
assert.Nil(t, resp.RegionError)
assert.Empty(t, resp.Pairs)
}
// TestScanLimitZero4C tests we get nothing if limit is 0.
func TestScanLimitZero4C(t *testing.T) {
builder := builderForScan(t)
cmd := builder.scanRequest([]byte{3}, 0)
resp := builder.runOneRequest(cmd).(*kvrpcpb.ScanResponse)
assert.Nil(t, resp.RegionError)
assert.Empty(t, resp.Pairs)
}
// TestScanAll4C start at the beginning of the DB and read all pairs, respecting the timestamp.
func TestScanAll4C(t *testing.T) {
builder := builderForScan(t)
cmd := builder.scanRequest([]byte{0}, 10000)
resp := builder.runOneRequest(cmd).(*kvrpcpb.ScanResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, 11, len(resp.Pairs))
assert.Equal(t, []byte{1}, resp.Pairs[0].Key)
assert.Equal(t, []byte{50}, resp.Pairs[0].Value)
assert.Equal(t, []byte{199}, resp.Pairs[10].Key)
assert.Equal(t, []byte{54}, resp.Pairs[10].Value)
}
// TestScanLimit4C tests that scan takes the limit into account.
func TestScanLimit4C(t *testing.T) {
builder := builderForScan(t)
cmd := builder.scanRequest([]byte{2}, 6)
resp := builder.runOneRequest(cmd).(*kvrpcpb.ScanResponse)
assert.Nil(t, resp.RegionError)
assert.Equal(t, 6, len(resp.Pairs))
assert.Equal(t, []byte{3}, resp.Pairs[0].Key)
assert.Equal(t, []byte{51}, resp.Pairs[0].Value)
assert.Equal(t, []byte{4}, resp.Pairs[5].Key)
assert.Equal(t, []byte{52}, resp.Pairs[5].Value)
}
// TestScanDeleted4C scan over a value which is deleted then replaced.
func TestScanDeleted4C(t *testing.T) {
builder := builderForScan(t)
req1 := builder.scanRequest([]byte{100}, 10000)
req1.Version = 100
req2 := builder.scanRequest([]byte{100}, 10000)
req2.Version = 105
req3 := builder.scanRequest([]byte{100}, 10000)
req3.Version = 120
resps := builder.runRequests(req1, req2, req3)
resp1 := resps[0].(*kvrpcpb.ScanResponse)
assert.Nil(t, resp1.RegionError)
assert.Equal(t, 3, len(resp1.Pairs))
assert.Equal(t, []byte{150}, resp1.Pairs[1].Key)
assert.Equal(t, []byte{42}, resp1.Pairs[1].Value)
resp2 := resps[1].(*kvrpcpb.ScanResponse)
assert.Nil(t, resp2.RegionError)
assert.Equal(t, 2, len(resp2.Pairs))
assert.Equal(t, []byte{120}, resp2.Pairs[0].Key)
assert.Equal(t, []byte{199}, resp2.Pairs[1].Key)
resp3 := resps[2].(*kvrpcpb.ScanResponse)
assert.Nil(t, resp3.RegionError)
assert.Equal(t, 3, len(resp3.Pairs))
assert.Equal(t, []byte{150}, resp3.Pairs[1].Key)
assert.Equal(t, []byte{64}, resp3.Pairs[1].Value)
}
func builderForScan(t *testing.T) *testBuilder {
values := []kv{
// Committed before 100.
{engine_util.CfDefault, []byte{1}, 80, []byte{50}},
{engine_util.CfWrite, []byte{1}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{1, 23}, 80, []byte{55}},
{engine_util.CfWrite, []byte{1, 23}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{3}, 80, []byte{51}},
{engine_util.CfWrite, []byte{3}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{3, 45}, 80, []byte{56}},
{engine_util.CfWrite, []byte{3, 45}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{3, 46}, 80, []byte{57}},
{engine_util.CfWrite, []byte{3, 46}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{3, 47}, 80, []byte{58}},
{engine_util.CfWrite, []byte{3, 47}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{3, 48}, 80, []byte{59}},
{engine_util.CfWrite, []byte{3, 48}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{4}, 80, []byte{52}},
{engine_util.CfWrite, []byte{4}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{120}, 80, []byte{53}},
{engine_util.CfWrite, []byte{120}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfDefault, []byte{199}, 80, []byte{54}},
{engine_util.CfWrite, []byte{199}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
// Committed after 100.
{engine_util.CfDefault, []byte{4, 45}, 110, []byte{58}},
{engine_util.CfWrite, []byte{4, 45}, 116, []byte{1, 0, 0, 0, 0, 0, 0, 0, 110}},
{engine_util.CfDefault, []byte{4, 46}, 110, []byte{57}},
{engine_util.CfWrite, []byte{4, 46}, 116, []byte{1, 0, 0, 0, 0, 0, 0, 0, 110}},
{engine_util.CfDefault, []byte{4, 47}, 110, []byte{58}},
{engine_util.CfWrite, []byte{4, 47}, 116, []byte{1, 0, 0, 0, 0, 0, 0, 0, 110}},
{engine_util.CfDefault, []byte{4, 48}, 110, []byte{59}},
{engine_util.CfWrite, []byte{4, 48}, 116, []byte{1, 0, 0, 0, 0, 0, 0, 0, 110}},
// Committed after 100, but started before.
{engine_util.CfDefault, []byte{5, 45}, 97, []byte{60}},
{engine_util.CfWrite, []byte{5, 45}, 101, []byte{1, 0, 0, 0, 0, 0, 0, 0, 97}},
{engine_util.CfDefault, []byte{5, 46}, 97, []byte{61}},
{engine_util.CfWrite, []byte{5, 46}, 101, []byte{1, 0, 0, 0, 0, 0, 0, 0, 97}},
{engine_util.CfDefault, []byte{5, 47}, 97, []byte{62}},
{engine_util.CfWrite, []byte{5, 47}, 101, []byte{1, 0, 0, 0, 0, 0, 0, 0, 97}},
{engine_util.CfDefault, []byte{5, 48}, 97, []byte{63}},
{engine_util.CfWrite, []byte{5, 48}, 101, []byte{1, 0, 0, 0, 0, 0, 0, 0, 97}},
// A deleted value and replaced value.
{engine_util.CfDefault, []byte{150}, 80, []byte{42}},
{engine_util.CfWrite, []byte{150}, 99, []byte{1, 0, 0, 0, 0, 0, 0, 0, 80}},
{engine_util.CfWrite, []byte{150}, 101, []byte{2, 0, 0, 0, 0, 0, 0, 0, 97}},
{engine_util.CfDefault, []byte{150}, 110, []byte{64}},
{engine_util.CfWrite, []byte{150}, 116, []byte{1, 0, 0, 0, 0, 0, 0, 0, 110}},
}
builder := newBuilder(t)
builder.init(values)
return &builder
}