mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 00:47:27 +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>
 |