Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

storage/engine: introduce a datadriven framework to run MVCC tests #42250

Merged
merged 1 commit into from
Dec 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
914 changes: 914 additions & 0 deletions pkg/storage/engine/mvcc_history_test.go

Large diffs are not rendered by default.

1,225 changes: 11 additions & 1,214 deletions pkg/storage/engine/mvcc_test.go

Large diffs are not rendered by default.

64 changes: 64 additions & 0 deletions pkg/storage/engine/testdata/mvcc_histories/clear_range
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

# Populate some values

run ok
with t=A v=abc resolve
txn_begin ts=44
put k=a
put k=a/123
put k=b
put k=b/123
put k=c
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000044,0 min=0.000000000,0 seq=0} rw=true stat=PENDING rts=0.000000044,0 wto=false max=0.000000000,0
data: "a"/0.000000044,0 -> /BYTES/abc
data: "a/123"/0.000000044,0 -> /BYTES/abc
data: "b"/0.000000044,0 -> /BYTES/abc
data: "b/123"/0.000000044,0 -> /BYTES/abc
data: "c"/0.000000044,0 -> /BYTES/abc


run ok
clear_range k=a end=+a
----
>> at end:
data: "a/123"/0.000000044,0 -> /BYTES/abc
data: "b"/0.000000044,0 -> /BYTES/abc
data: "b/123"/0.000000044,0 -> /BYTES/abc
data: "c"/0.000000044,0 -> /BYTES/abc

run ok
clear_range k=a end=-a
----
>> at end:
data: "b"/0.000000044,0 -> /BYTES/abc
data: "b/123"/0.000000044,0 -> /BYTES/abc
data: "c"/0.000000044,0 -> /BYTES/abc

run ok
clear_range k=a end==b
----
>> at end:
data: "b"/0.000000044,0 -> /BYTES/abc
data: "b/123"/0.000000044,0 -> /BYTES/abc
data: "c"/0.000000044,0 -> /BYTES/abc

run ok
clear_range k=a end=+b
----
>> at end:
data: "b/123"/0.000000044,0 -> /BYTES/abc
data: "c"/0.000000044,0 -> /BYTES/abc

run ok
clear_range k=a end=-b
----
>> at end:
data: "c"/0.000000044,0 -> /BYTES/abc

run ok
clear_range k=a end=-c
----
>> at end:
<no data>
113 changes: 113 additions & 0 deletions pkg/storage/engine/testdata/mvcc_histories/conditional_put
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
run error
cput k=k v=v cond=v2 ts=123
----
>> at end:
<no data>
error: (*roachpb.ConditionFailedError:) unexpected value: <nil>

# Verify the difference between missing value and empty value.

run error
cput k=k v=v cond= ts=123,1
----
>> at end:
<no data>
error: (*roachpb.ConditionFailedError:) unexpected value: <nil>

# Do a conditional put with expectation that the value is completely missing; will succeed.

run ok
cput k=k v=v ts=123,2
----
>> at end:
data: "k"/0.000000123,2 -> /BYTES/v

# Another conditional put expecting value missing will fail, now that value1 is written.

run error
cput k=k v=v ts=123,3
----
>> at end:
data: "k"/0.000000123,2 -> /BYTES/v
error: (*roachpb.ConditionFailedError:) unexpected value: raw_bytes:"\000\000\000\000\003v" timestamp:<wall_time:123 logical:2 >

# Conditional put expecting wrong value2, will fail.

run error
cput k=k v=v cond=v2 ts=123,4
----
>> at end:
data: "k"/0.000000123,2 -> /BYTES/v
error: (*roachpb.ConditionFailedError:) unexpected value: raw_bytes:"\000\000\000\000\003v" timestamp:<wall_time:123 logical:2 >

# Move to an empty value. Will succeed.

run ok
cput k=k v= cond=v ts=123,5
----
>> at end:
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v

# Move key2 (which does not exist) to from value1 to value2.
# Expect it to fail since it does not exist with value1.

run error
cput k=k2 v=v2 cond=v ts=123,6
----
>> at end:
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v
error: (*roachpb.ConditionFailedError:) unexpected value: <nil>

# Move key2 (which does not yet exist) to from value1 to value2, but
# allowing for it not existing.

run ok
cput k=k2 v=v2 cond=v ts=123,7 allow_missing
----
>> at end:
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v
data: "k2"/0.000000123,7 -> /BYTES/v2

# Try to move key2 (which has value2) from value1 to empty. Expect error.

run error
cput k=k2 v= cond=v allow_missing ts=123,8
----
>> at end:
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v
data: "k2"/0.000000123,7 -> /BYTES/v2
error: (*roachpb.ConditionFailedError:) unexpected value: raw_bytes:"\000\000\000\000\003v2" timestamp:<wall_time:123 logical:7 >

# Try to move key2 (which has value2) from value2 to empty. Expect success.

run ok
cput k=k2 v= cond=v2 allow_missing ts=123,9
----
>> at end:
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v
data: "k2"/0.000000123,9 -> /BYTES/
data: "k2"/0.000000123,7 -> /BYTES/v2

# Now move to value2 from expected empty value.

run ok
cput k=k v=v2 cond= ts=123,10
----
>> at end:
data: "k"/0.000000123,10 -> /BYTES/v2
data: "k"/0.000000123,5 -> /BYTES/
data: "k"/0.000000123,2 -> /BYTES/v
data: "k2"/0.000000123,9 -> /BYTES/
data: "k2"/0.000000123,7 -> /BYTES/v2

# Verify we get value2 as expected.

run ok
get k=k ts=123,11
----
get: "k" -> /BYTES/v2 @0.000000123,10
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
run ok
txn_begin t=A ts=123
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000123,0 min=0.000000000,0 seq=0} rw=true stat=PENDING rts=0.000000123,0 wto=false max=0.000000000,0

# Write value1.

run ok
with t=A
txn_step
cput k=k v=v
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000123,0 min=0.000000000,0 seq=1} rw=true stat=PENDING rts=0.000000123,0 wto=false max=0.000000000,0
meta: "k"/0.000000000,0 -> txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000123,0 min=0.000000000,0 seq=1} ts=0.000000123,0 del=false klen=12 vlen=6
data: "k"/0.000000123,0 -> /BYTES/v

# Now, overwrite value1 with value2 from same txn; should see value1
# as pre-existing value.

run ok
with t=A
txn_step
cput k=k v=v2 cond=v
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000123,0 min=0.000000000,0 seq=2} rw=true stat=PENDING rts=0.000000123,0 wto=false max=0.000000000,0
meta: "k"/0.000000000,0 -> txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000123,0 min=0.000000000,0 seq=2} ts=0.000000123,0 del=false klen=12 vlen=7 ih={{1 /BYTES/v}}
data: "k"/0.000000123,0 -> /BYTES/v2

# Writing value3 from a new epoch should see nil again.

run ok
with t=A
txn_restart
txn_step
cput k=k v=v3
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=1 ts=0.000000123,0 min=0.000000000,0 seq=1} rw=true stat=PENDING rts=0.000000123,0 wto=false max=0.000000000,0
meta: "k"/0.000000000,0 -> txn={id=00000000 key=/Min pri=0.00000000 epo=1 ts=0.000000123,0 min=0.000000000,0 seq=1} ts=0.000000123,0 del=false klen=12 vlen=7
data: "k"/0.000000123,0 -> /BYTES/v3

# Commit value3 at a later timestamp.

run ok
with t=A
txn_advance ts=124
resolve_intent k=k
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=1 ts=0.000000124,0 min=0.000000000,0 seq=1} rw=true stat=PENDING rts=0.000000123,0 wto=false max=0.000000000,0
data: "k"/0.000000124,0 -> /BYTES/v3

# Write value4 with an old timestamp without txn...should get a write
# too old error.

run error
cput k=k v=v4 cond=v3 ts=123
----
>> at end:
data: "k"/0.000000124,1 -> /BYTES/v4
data: "k"/0.000000124,0 -> /BYTES/v3
error: (*roachpb.WriteTooOldError:) WriteTooOldError: write at timestamp 0.000000123,0 too old; wrote at 0.000000124,1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This test verifies the differing behavior
# of conditional puts when writing with an older timestamp than the
# existing write. If there's no transaction, the conditional put
# should use the latest value. When there's a transaction, then it
# should use the value at the specified timestamp.

run ok
put ts=10 k=k v=v1
----
>> at end:
data: "k"/0.000000010,0 -> /BYTES/v1

# Try a non-transactional put @t=1 with expectation of nil; should fail.
run error
cput ts=1 k=k v=v2
----
>> at end:
data: "k"/0.000000010,0 -> /BYTES/v1
error: (*roachpb.ConditionFailedError:) unexpected value: raw_bytes:"\000\000\000\000\003v1" timestamp:<wall_time:10 >

# Now do a non-transactional put @t=1 with expectation of value1; will "succeed" @t=10,1 with WriteTooOld.
run error
cput ts=1 k=k v=v2 cond=v1
----
>> at end:
data: "k"/0.000000010,1 -> /BYTES/v2
data: "k"/0.000000010,0 -> /BYTES/v1
error: (*roachpb.WriteTooOldError:) WriteTooOldError: write at timestamp 0.000000001,0 too old; wrote at 0.000000010,1

# Try a transactional put @t=1 with expectation of value2; should fail.
run error
with t=a
txn_begin ts=1
cput k=k v=v2 cond=v1
----
>> at end:
txn: "a" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000001,0 min=0.000000000,0 seq=0} rw=true stat=PENDING rts=0.000000001,0 wto=false max=0.000000000,0
data: "k"/0.000000010,1 -> /BYTES/v2
data: "k"/0.000000010,0 -> /BYTES/v1
error: (*roachpb.ConditionFailedError:) unexpected value: <nil>

# Now do a transactional put @t=1 with expectation of nil; will "succeed" @t=10,2 with WriteTooOld.
run error
with t=a
cput k=k v=v3
----
>> at end:
meta: "k"/0.000000000,0 -> txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000001,0 min=0.000000000,0 seq=0} ts=0.000000010,2 del=false klen=12 vlen=7
data: "k"/0.000000010,2 -> /BYTES/v3
data: "k"/0.000000010,1 -> /BYTES/v2
data: "k"/0.000000010,0 -> /BYTES/v1
error: (*roachpb.WriteTooOldError:) WriteTooOldError: write at timestamp 0.000000001,0 too old; wrote at 0.000000010,2
33 changes: 33 additions & 0 deletions pkg/storage/engine/testdata/mvcc_histories/deletes
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## A simple txn that deletes.
## The delete tombstone is placed alongside the previous value, at the newer timestamp.

run ok
with t=A
txn_begin ts=44
del k=a resolve
txn_remove
----
>> at end:
data: "a"/0.000000044,0 -> /<empty>

# Show the value disappears from gets.

run ok
with t=A
txn_begin ts=45
get k=a
txn_remove
----
get: "a" -> <no data>
>> at end:

# Show the tombstone.

run ok
with t=A
txn_begin ts=45
get k=a tombstones
txn_remove
----
get: "a" -> /<empty> @0.000000044,0
>> at end:
32 changes: 32 additions & 0 deletions pkg/storage/engine/testdata/mvcc_histories/empty_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
run error
get ts=0,1 k=
----
error: (*errors.fundamental:) attempted access to empty key

run error
put ts=0,1 k= v=a
----
>> at end:
<no data>
error: (*errors.fundamental:) attempted access to empty key

run ok
scan ts=0,1 k= end=a
----
scan: /Min-"a" -> <no data>


run error
scan ts=0,1 k=a end=
----
scan: "a"-/Min -> <no data>
error: (*errors.fundamental:) attempted access to empty key

run error
txn_begin t=A
resolve_intent t=A k=
----
>> at end:
txn: "A" meta={id=00000000 key=/Min pri=0.00000000 epo=0 ts=0.000000000,0 min=0.000000000,0 seq=0} rw=true stat=PENDING rts=0.000000000,0 wto=false max=0.000000000,0
<no data>
error: (*errors.fundamental:) attempted access to empty key
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
run ok
put k=k v=v ts=1
----
>> at end:
data: "k"/0.000000001,0 -> /BYTES/v

run error
get k=k ts=-1
----
error: (*withstack.withStack:) cannot write to "k" at timestamp 0.-00000001,0


run error
put k=k v=v ts=-1
----
>> at end:
data: "k"/0.000000001,0 -> /BYTES/v
error: (*withstack.withStack:) cannot write to "k" at timestamp 0.-00000001,0
Loading