-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
storage/engine: introduce a datadriven framework to run MVCC tests
Previously MVCC tests were hand-coded in Go. This was making it hard(er) to introduce new tests or modify existing tests. This commit improves upon this situation by introducing a new datadriven test, `TestMVCCHistories`, which runs MVCC tests written using a DSL: ``` begin_txn t=<name> [ts=<int>[,<int>]] remove_txn t=<name> resolve_intent t=<name> k=<key> [status=<txnstatus>] restart_txn t=<name> update_txn t=<name> t2=<name> step_txn t=<name> [n=<int>] advance_txn t=<name> ts=<int>[,<int>] txn_status t=<name> status=<txnstatus> check_intent k=<key> [none] put [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> v=<string> [raw] cput [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> v=<string> [raw] [cond=<string>] increment [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> [inc=<val>] del [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> get [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> [inconsistent] [tombstones] scan [t=<name>] [ts=<int>[,<int>]] [resolve] k=<key> [end=<key>] [inconsistent] [tombstones] [reverse] merge [ts=<int>[,<int>]] k=<key> v=<string> [raw] clear_range k=<key> end=<key> ``` Where `<key>` can be a simple string, or a string prefixed by the following characters: - `=foo` means exactly key `foo` - `+foo` means `Key(foo).Next()` - `-foo` means `Key(foo).PrefixEnd()` Additionally, the pseudo-command `with` enables sharing a group of arguments between multiple commands, for example: ``` with t=A begin_txn with k=a put v=b resolve_intent ``` Release note: None
- Loading branch information
Showing
25 changed files
with
2,096 additions
and
1,214 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
begin_txn 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 orig=0.000000044,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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
113
pkg/storage/engine/testdata/mvcc_histories/conditional_put
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
65 changes: 65 additions & 0 deletions
65
pkg/storage/engine/testdata/mvcc_histories/conditional_put_with_txn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
run ok | ||
begin_txn 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 orig=0.000000123,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
|
||
# Write value1. | ||
|
||
run ok | ||
with t=A | ||
step_txn | ||
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 orig=0.000000123,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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 | ||
step_txn | ||
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 orig=0.000000123,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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 | ||
restart_txn | ||
step_txn | ||
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 orig=0.000000123,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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 | ||
advance_txn 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 orig=0.000000123,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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 |
52 changes: 52 additions & 0 deletions
52
pkg/storage/engine/testdata/mvcc_histories/conditional_put_write_too_old
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
begin_txn 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 orig=0.000000001,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
begin_txn ts=44 | ||
del k=a resolve | ||
remove_txn | ||
---- | ||
>> at end: | ||
data: "a"/0.000000044,0 -> /<empty> | ||
|
||
# Show the value disappears from gets. | ||
|
||
run ok | ||
with t=A | ||
begin_txn ts=45 | ||
get k=a | ||
remove_txn | ||
---- | ||
get: "a" -> <no data> | ||
>> at end: | ||
|
||
# Show the tombstone. | ||
|
||
run ok | ||
with t=A | ||
begin_txn ts=45 | ||
get k=a tombstones | ||
remove_txn | ||
---- | ||
get: "a" -> /<empty> | ||
>> at end: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
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= | ||
---- | ||
error: (*errors.fundamental:) attempted access to empty key | ||
|
||
run error | ||
begin_txn 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 orig=0.000000000,0 max=0.000000000,0 rts=0.000000000,0 wto=false | ||
<no data> | ||
error: (*errors.fundamental:) attempted access to empty key |
18 changes: 18 additions & 0 deletions
18
pkg/storage/engine/testdata/mvcc_histories/get_negative_timestamp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.