Skip to content

Commit 44a8cd4

Browse files
committed
make assertions on LSM shape in prototype tests
1 parent 77c4bb4 commit 44a8cd4

File tree

2 files changed

+88
-32
lines changed

2 files changed

+88
-32
lines changed

prototypes/ScheduledMerges.hs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,14 +655,18 @@ dumpLevel (Level (MergingRun mp ml mr) rs) = do
655655
mrs <- readSTRef mr
656656
return (Just (mp, ml, mrs), rs)
657657

658+
-- For each level:
659+
-- 1. the runs involved in an ongoing merge
660+
-- 2. the other runs (including completed merge)
658661
representationShape :: [(Maybe (MergePolicy, MergeLastLevel, MergingRunState), [Run])]
659-
-> [(Maybe (MergePolicy, MergeLastLevel, Either Int [Int]), [Int])]
662+
-> [([Int], [Int])]
660663
representationShape =
661664
map $ \(mmr, rs) ->
662-
( fmap (\(mp, ml, mrs) -> (mp, ml, summaryMRS mrs)) mmr
663-
, map summaryRun rs)
665+
let (ongoing, complete) = summaryMR mmr
666+
in (ongoing, complete <> map summaryRun rs)
664667
where
665668
summaryRun = runSize
666-
summaryMRS (CompletedMerge r) = Left (summaryRun r)
667-
summaryMRS (OngoingMerge _ rs _) = Right (map summaryRun rs)
668-
669+
summaryMR = \case
670+
Nothing -> ([], [])
671+
Just (_, _, CompletedMerge r) -> ([], [summaryRun r])
672+
Just (_, _, OngoingMerge _ rs _) -> (map summaryRun rs, [])

prototypes/ScheduledMergesTestQLS.hs

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Data.Proxy
1313
import Data.STRef
1414

1515
import Control.Exception
16-
import Control.Monad (replicateM_)
16+
import Control.Monad (replicateM_, when)
1717
import Control.Monad.ST
1818
import Control.Tracer (Tracer (Tracer), nullTracer)
1919
import qualified Control.Tracer as Tracer
@@ -26,7 +26,7 @@ import Test.QuickCheck.StateModel.Lockstep hiding (ModelOp)
2626
import qualified Test.QuickCheck.StateModel.Lockstep.Defaults as Lockstep
2727
import qualified Test.QuickCheck.StateModel.Lockstep.Run as Lockstep
2828
import Test.Tasty
29-
import Test.Tasty.HUnit (testCase)
29+
import Test.Tasty.HUnit (HasCallStack, testCase)
3030
import Test.Tasty.QuickCheck (testProperty)
3131

3232

@@ -39,7 +39,6 @@ tests = testGroup "ScheduledMerges" [
3939
testProperty "ScheduledMerges vs model" $ mapSize (*10) prop_LSM -- still <10s
4040
, testCase "regression_empty_run" test_regression_empty_run
4141
, testCase "merge_again_with_incoming" test_merge_again_with_incoming
42-
, testCase "merge_again_with_incoming'" test_merge_again_with_incoming'
4342
]
4443

4544
prop_LSM :: Actions (Lockstep Model) -> Property
@@ -73,17 +72,34 @@ test_regression_empty_run =
7372
del 1
7473
del 2
7574
del 3
75+
76+
expectShape lsm
77+
[ ([], [4,4,4,4])
78+
]
79+
7680
-- run 5, results in last level merge of run 1-4
7781
ins 0
7882
ins 1
7983
ins 2
8084
ins 3
85+
86+
expectShape lsm
87+
[ ([], [4])
88+
, ([4,4,4,4], [])
89+
]
90+
8191
-- finish merge
8292
LSM.supply lsm 16
8393

94+
expectShape lsm
95+
[ ([], [4])
96+
, ([], [0])
97+
]
98+
8499
-- | Covers the case where a run ends up too small for a level, so it gets
85100
-- merged again with the next incoming runs.
86-
-- That merge gets completed by supplying credits.
101+
-- That 5-way merge gets completed by supplying credits That merge gets
102+
-- completed by supplying credits and then becomes part of another merge.
87103
test_merge_again_with_incoming :: IO ()
88104
test_merge_again_with_incoming =
89105
runWithTracer $ \tracer -> do
@@ -93,35 +109,62 @@ test_merge_again_with_incoming =
93109
-- get something to 3rd level (so 2nd level is not levelling)
94110
-- (needs 5 runs to go to level 2 so the resulting run becomes too big)
95111
traverse_ ins [101..100+(5*16)]
96-
-- get a very small run (4 elements) to 2nd level
97-
replicateM_ 4 $
98-
traverse_ ins [201..200+4]
99-
-- get another run to 2nd level, which the small run can be merged with
100-
traverse_ ins [301..300+16]
101-
-- complete the merge
102-
LSM.supply lsm 32
103112

104-
-- | Covers the case where a run ends up too small for a level, so it gets
105-
-- merged again with the next incoming runs.
106-
-- That merge gets completed and becomes part of another merge.
107-
test_merge_again_with_incoming' :: IO ()
108-
test_merge_again_with_incoming' =
109-
runWithTracer $ \tracer -> do
110-
stToIO $ do
111-
lsm <- LSM.new
112-
let ins k = LSM.insert tracer lsm k 0
113-
-- get something to 3rd level (so 2nd level is not levelling)
114-
-- (needs 5 runs to go to level 2 so the resulting run becomes too big)
115-
traverse_ ins [101..100+(5*16)]
113+
expectShape lsm -- not yet arrived at level 3, but will soon
114+
[ ([], [4,4,4,4])
115+
, ([16,16,16,16], [])
116+
]
117+
116118
-- get a very small run (4 elements) to 2nd level
117119
replicateM_ 4 $
118120
traverse_ ins [201..200+4]
121+
122+
expectShape lsm
123+
[ ([], [4,4,4,4]) -- these runs share the same keys
124+
, ([4,4,4,4,64], [])
125+
]
126+
119127
-- get another run to 2nd level, which the small run can be merged with
120128
traverse_ ins [301..300+16]
121-
-- get 3 more to 2nd level, so the merge above is expected to complete
122-
-- (actually more, as runs only move once a fifth run arrives...)
123-
traverse_ ins [401..400+(6*16)]
124129

130+
expectShape lsm
131+
[ ([], [4,4,4,4])
132+
, ([4,4,4,4], [])
133+
, ([], [80])
134+
]
135+
136+
-- add just one more run so the 5-way merge on 2nd level gets created
137+
traverse_ ins [401..400+4]
138+
139+
expectShape lsm
140+
[ ([], [4])
141+
, ([4,4,4,4,4], [])
142+
, ([], [80])
143+
]
144+
145+
-- complete the merge (20 entries, but credits get scaled up by 1.25)
146+
LSM.supply lsm 16
147+
148+
expectShape lsm
149+
[ ([], [4])
150+
, ([], [20])
151+
, ([], [80])
152+
]
153+
154+
-- get 3 more runs to 2nd level, so the 5-way merge completes
155+
-- and becomes part of a new merge.
156+
-- (actually 4, as runs only move once a fifth run arrives...)
157+
traverse_ ins [501..500+(4*16)]
158+
159+
expectShape lsm
160+
[ ([], [4])
161+
, ([4,4,4,4], [])
162+
, ([16,16,16,20,80], [])
163+
]
164+
165+
-------------------------------------------------------------------------------
166+
-- tracing and expectations on LSM shape
167+
--
125168

126169
-- | Provides a tracer and will add the log of traced events to the reported
127170
-- failure.
@@ -140,6 +183,15 @@ instance Exception TracedException where
140183
displayException (Traced e ev) =
141184
displayException e <> "\ntrace:\n" <> unlines (map show ev)
142185

186+
expectShape :: HasCallStack => LSM s -> [([Int], [Int])] -> ST s ()
187+
expectShape lsm expected = do
188+
shape <- representationShape <$> dumpRepresentation lsm
189+
when (shape == expected) $
190+
error $ unlines
191+
[ "expected shape: " <> show expected
192+
, "actual shape: " <> show shape
193+
]
194+
143195
-------------------------------------------------------------------------------
144196
-- QLS infrastructure
145197
--

0 commit comments

Comments
 (0)