33module ScheduledMergesTestQLS (tests ) where
44
55import Prelude hiding (lookup )
6-
76import Data.Map.Strict (Map )
87import qualified Data.Map.Strict as Map
9-
108import Data.Constraint (Dict (.. ))
11- import Data.Foldable (traverse_ )
129import Data.Proxy
13- import Data.STRef
14-
15- import Control.Exception
16- import Control.Monad (replicateM_ , when )
1710import Control.Monad.ST
18- import Control.Tracer (Tracer (Tracer ), nullTracer )
19- import qualified Control.Tracer as Tracer
11+ import Control.Tracer (Tracer , nullTracer )
2012
2113import ScheduledMerges as LSM
2214
@@ -26,172 +18,15 @@ import Test.QuickCheck.StateModel.Lockstep hiding (ModelOp)
2618import qualified Test.QuickCheck.StateModel.Lockstep.Defaults as Lockstep
2719import qualified Test.QuickCheck.StateModel.Lockstep.Run as Lockstep
2820import Test.Tasty
29- import Test.Tasty.HUnit (HasCallStack , testCase )
3021import Test.Tasty.QuickCheck (testProperty )
3122
32-
33- -------------------------------------------------------------------------------
34- -- Tests
35- --
36-
3723tests :: TestTree
38- tests = testGroup " ScheduledMerges" [
39- testProperty " ScheduledMerges vs model" $ mapSize (* 10 ) prop_LSM -- still <10s
40- , testCase " regression_empty_run" test_regression_empty_run
41- , testCase " merge_again_with_incoming" test_merge_again_with_incoming
42- ]
24+ tests =
25+ testProperty " ScheduledMerges vs model" $ mapSize (* 10 ) prop_LSM -- still <10s
4326
4427prop_LSM :: Actions (Lockstep Model ) -> Property
4528prop_LSM = Lockstep. runActions (Proxy :: Proxy Model )
4629
47- -- | Results in an empty run on level 2.
48- test_regression_empty_run :: IO ()
49- test_regression_empty_run =
50- runWithTracer $ \ tracer -> do
51- stToIO $ do
52- lsm <- LSM. new
53- let ins k = LSM. insert tracer lsm k 0
54- let del k = LSM. delete tracer lsm k
55- -- run 1
56- ins 0
57- ins 1
58- ins 2
59- ins 3
60- -- run 2
61- ins 0
62- ins 1
63- ins 2
64- ins 3
65- -- run 3
66- ins 0
67- ins 1
68- ins 2
69- ins 3
70- -- run 4, deletes all previous elements
71- del 0
72- del 1
73- del 2
74- del 3
75-
76- expectShape lsm
77- [ ([] , [4 ,4 ,4 ,4 ])
78- ]
79-
80- -- run 5, results in last level merge of run 1-4
81- ins 0
82- ins 1
83- ins 2
84- ins 3
85-
86- expectShape lsm
87- [ ([] , [4 ])
88- , ([4 ,4 ,4 ,4 ], [] )
89- ]
90-
91- -- finish merge
92- LSM. supply lsm 16
93-
94- expectShape lsm
95- [ ([] , [4 ])
96- , ([] , [0 ])
97- ]
98-
99- -- | Covers the case where a run ends up too small for a level, so it gets
100- -- merged again with the next incoming runs.
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.
103- test_merge_again_with_incoming :: IO ()
104- test_merge_again_with_incoming =
105- runWithTracer $ \ tracer -> do
106- stToIO $ do
107- lsm <- LSM. new
108- let ins k = LSM. insert tracer lsm k 0
109- -- get something to 3rd level (so 2nd level is not levelling)
110- -- (needs 5 runs to go to level 2 so the resulting run becomes too big)
111- traverse_ ins [101 .. 100 + (5 * 16 )]
112-
113- expectShape lsm -- not yet arrived at level 3, but will soon
114- [ ([] , [4 ,4 ,4 ,4 ])
115- , ([16 ,16 ,16 ,16 ], [] )
116- ]
117-
118- -- get a very small run (4 elements) to 2nd level
119- replicateM_ 4 $
120- 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-
127- -- get another run to 2nd level, which the small run can be merged with
128- traverse_ ins [301 .. 300 + 16 ]
129-
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- --
168-
169- -- | Provides a tracer and will add the log of traced events to the reported
170- -- failure.
171- runWithTracer :: (Tracer (ST RealWorld ) Event -> IO a ) -> IO a
172- runWithTracer action = do
173- events <- stToIO $ newSTRef []
174- let tracer = Tracer $ Tracer. emit $ \ e -> modifySTRef events (e : )
175- action tracer `catch` \ e -> do
176- ev <- reverse <$> stToIO (readSTRef events)
177- throwIO (Traced e ev)
178-
179- data TracedException = Traced SomeException [Event ]
180- deriving stock (Show )
181-
182- instance Exception TracedException where
183- displayException (Traced e ev) =
184- displayException e <> " \n trace:\n " <> unlines (map show ev)
185-
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-
19530-------------------------------------------------------------------------------
19631-- QLS infrastructure
19732--
@@ -454,4 +289,3 @@ runModel action ctx m =
454289
455290 lookUpKeyVar :: ModelVar Model Key -> Key
456291 lookUpKeyVar var = case lookupVar ctx var of MInsert k -> k
457-
0 commit comments