mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 09:05:18 +00:00
396 lines
11 KiB
Plaintext
396 lines
11 KiB
Plaintext
|
# Test a scenario that should NOT result in defragmentation.
|
||
|
|
||
|
define
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
----
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
<nil>
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
|
||
|
# Test a scenario that SHOULD result in internal defragmentation ([a,c) and
|
||
|
# [c,d) should be merged.
|
||
|
|
||
|
define
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
----
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
|
||
|
# Test defragmenting in both directions at seek keys.
|
||
|
|
||
|
define
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-h:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
h-p:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
p-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
----
|
||
|
|
||
|
iter
|
||
|
seekge b
|
||
|
prev
|
||
|
seekge b
|
||
|
next
|
||
|
seeklt d
|
||
|
next
|
||
|
seeklt d
|
||
|
prev
|
||
|
----
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
|
||
|
iter
|
||
|
seeklt d
|
||
|
next
|
||
|
prev
|
||
|
----
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
|
||
|
# Test next-ing and prev-ing around seek keys.
|
||
|
|
||
|
define
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-h:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
h-p:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
p-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
----
|
||
|
|
||
|
iter
|
||
|
seekge r
|
||
|
prev
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
|
||
|
iter
|
||
|
seekge f
|
||
|
seekge h
|
||
|
seekge p
|
||
|
seekge t
|
||
|
seekge u
|
||
|
seekge v
|
||
|
seekge z
|
||
|
----
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
<nil>
|
||
|
|
||
|
iter
|
||
|
seeklt f
|
||
|
seeklt h
|
||
|
seeklt p
|
||
|
seeklt t
|
||
|
seeklt u
|
||
|
seeklt z
|
||
|
----
|
||
|
a-f:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
f-t:{(#3,RANGEKEYSET,@3,bananas)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
t-z:{(#4,RANGEKEYSET,@2,oranges)}
|
||
|
|
||
|
# Test iteration with a reducer that collects keys across all spans that
|
||
|
# constitute a defragmented span. Abutting spans are always combined.
|
||
|
|
||
|
define
|
||
|
a-b:{(#3,RANGEDEL) (#2,RANGEDEL)}
|
||
|
b-c:{(#4,RANGEDEL) (#1,RANGEDEL)}
|
||
|
c-d:{(#5,RANGEDEL)}
|
||
|
e-f:{(#1,RANGEDEL)}
|
||
|
f-g:{(#2,RANGEDEL)}
|
||
|
----
|
||
|
|
||
|
iter equal=always reducer=collect
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
a-d:{(#5,RANGEDEL) (#4,RANGEDEL) (#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)}
|
||
|
e-g:{(#2,RANGEDEL) (#1,RANGEDEL)}
|
||
|
<nil>
|
||
|
e-g:{(#2,RANGEDEL) (#1,RANGEDEL)}
|
||
|
a-d:{(#5,RANGEDEL) (#4,RANGEDEL) (#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)}
|
||
|
<nil>
|
||
|
|
||
|
# Test defragmentation of non-empty (i.e. more than one value) fragments, while
|
||
|
# empty fragments are left untouched.
|
||
|
|
||
|
define
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
g-h:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
----
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
g-h:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
g-h:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
e-f:{}
|
||
|
d-e:{}
|
||
|
a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
<nil>
|
||
|
|
||
|
iter
|
||
|
seekge d
|
||
|
next
|
||
|
prev
|
||
|
seekge e
|
||
|
next
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
g-h:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
e-f:{}
|
||
|
d-e:{}
|
||
|
a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
|
||
|
iter
|
||
|
seeklt e
|
||
|
next
|
||
|
prev
|
||
|
seeklt f
|
||
|
next
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
d-e:{}
|
||
|
e-f:{}
|
||
|
g-h:{(#1,RANGEKEYSET,@3,bananas)}
|
||
|
e-f:{}
|
||
|
d-e:{}
|
||
|
a-d:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
|
||
|
# Test that the defragmenting iterator does yield errors in cases that do not
|
||
|
# need to defragment.
|
||
|
|
||
|
define
|
||
|
a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
----
|
||
|
|
||
|
iter probes=(ErrInjected)
|
||
|
seek-ge b
|
||
|
seek-lt d
|
||
|
first
|
||
|
last
|
||
|
----
|
||
|
<nil> err=<injected error>
|
||
|
<nil> err=<injected error>
|
||
|
<nil> err=<injected error>
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
# Next and Prev may only be called on positioned iterators, so to test
|
||
|
# propagation of errors on Next or Prev, we must use a probe that injects errors
|
||
|
# on Next or Prev but leaves seeks untouched.
|
||
|
#
|
||
|
# The situation is complicated by the fact that a seek on the defragmenting
|
||
|
# iterator will result in Next/Prevs on the embedded iterator (in order to peek
|
||
|
# ahead to see if anything needs to be defragmented).
|
||
|
#
|
||
|
# First we test the seeks too result in injected errors when they Next/Prev
|
||
|
# ahead to determine if there's anything to defragment.
|
||
|
|
||
|
iter probes=((If (Or OpNext OpPrev) ErrInjected noop), (Log "# inner."))
|
||
|
seek-ge b
|
||
|
next
|
||
|
seek-lt cat
|
||
|
prev
|
||
|
----
|
||
|
# inner.SeekGE("b") = a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.SeekLT("cat") = c-d:{(#4,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
# Use a probe that injects errors whenever we otherwise would've returned the
|
||
|
# c-d span. First and Last calls should both return errors because during
|
||
|
# defragmenting they'll step the internal iterator on to the error position.
|
||
|
|
||
|
iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner."))
|
||
|
first
|
||
|
last
|
||
|
----
|
||
|
# inner.First() = a-c:{(#3,RANGEKEYUNSET,@5) (#2,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.Last() = d-e:{(#4,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
# In order to test that errors are injected when Next-ing the top-level
|
||
|
# iterator, define test data that includes 5 spans.
|
||
|
|
||
|
define
|
||
|
a-b:{(#3,RANGEKEYUNSET,@5)}
|
||
|
b-c:{(#4,RANGEKEYSET,@5,apples)}
|
||
|
c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
e-f:{(#4,RANGEKEYSET,@1,pineapple)}
|
||
|
----
|
||
|
|
||
|
# Use a probe that injects errors whenever we would've otherwise returned the
|
||
|
# c-d span. Our initial First/Last seeks should not step on to the error
|
||
|
# position and should not error. The subsequent Next/Prev however should.
|
||
|
|
||
|
iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner."))
|
||
|
first
|
||
|
next
|
||
|
last
|
||
|
prev
|
||
|
----
|
||
|
# inner.First() = a-b:{(#3,RANGEKEYUNSET,@5)}
|
||
|
# inner.Next() = b-c:{(#4,RANGEKEYSET,@5,apples)}
|
||
|
a-b:{(#3,RANGEKEYUNSET,@5)}
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.Last() = e-f:{(#4,RANGEKEYSET,@1,pineapple)}
|
||
|
# inner.Prev() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
e-f:{(#4,RANGEKEYSET,@1,pineapple)}
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
# When seeking, the defragmenting iterator needs to defragment in both
|
||
|
# directions. A forward seek first defragments in the reverse direction, and
|
||
|
# then in the forward direction. A backward seek does the inverse. If an error
|
||
|
# is encountered while performing the first defragment scan, it must be
|
||
|
# surfaced.
|
||
|
#
|
||
|
# To test this scenario we again inject errors instead of the c-d span.
|
||
|
# - The SeekGE('d') should land on d-e, try to defragment backward first and
|
||
|
# encounter the error.
|
||
|
# - The SeekLT('c') should land on b-c, try to defragment forward first and
|
||
|
# encounter the error.
|
||
|
iter probes=((If (Equal StartKey (Bytes "c")) ErrInjected noop), (Log "# inner."))
|
||
|
seek-ge d
|
||
|
seek-lt c
|
||
|
----
|
||
|
# inner.SeekGE("d") = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
# inner.SeekLT("c") = b-c:{(#4,RANGEKEYSET,@5,apples)}
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
# When changing directions in some circumstances we step an iterator and then
|
||
|
# defragment twice; once to skip over the current span and once to construct the
|
||
|
# next defragmented span in the new iteration direction. If the first step of
|
||
|
# the iterator surfaces an error, ensure that it's still propagated.
|
||
|
iter probes=((If (And OpPrev (Equal StartKey (Bytes "c"))) ErrInjected noop), (Log "# inner."))
|
||
|
seek-ge c
|
||
|
prev
|
||
|
----
|
||
|
# inner.SeekGE("c") = c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Prev() = b-c:{(#4,RANGEKEYSET,@5,apples)}
|
||
|
# inner.Next() = c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Next() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Prev() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|
||
|
|
||
|
iter probes=((If (And OpNext (Equal StartKey (Bytes "c"))) ErrInjected noop), (Log "# inner."))
|
||
|
seek-lt d
|
||
|
next
|
||
|
----
|
||
|
# inner.SeekLT("d") = c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Next() = d-e:{(#6,RANGEKEYSET,@3,bananas) (#4,RANGEKEYSET,@1,pineapple)}
|
||
|
# inner.Prev() = c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Prev() = b-c:{(#4,RANGEKEYSET,@5,apples)}
|
||
|
c-d:{(#5,RANGEKEYSET,@3,bananas)}
|
||
|
# inner.Next() = nil <err="injected error">
|
||
|
<nil> err=<injected error>
|