@@ -208,17 +208,58 @@ propLockstep_ModelIOImpl =
208208 = Nothing
209209
210210instance Arbitrary R. TableConfig where
211- arbitrary :: Gen R. TableConfig
212- arbitrary = pure $ R. TableConfig {
211+ arbitrary = do
212+ confWriteBufferAlloc <- QC. arbitrary
213+ pure $ R. TableConfig {
213214 R. confMergePolicy = R. MergePolicyLazyLevelling
214215 , R. confSizeRatio = R. Four
215- , R. confWriteBufferAlloc = R. AllocNumEntries ( R. NumEntries 30 )
216+ , confWriteBufferAlloc
216217 , R. confBloomFilterAlloc = R. AllocFixed 10
217218 , R. confFencePointerIndex = R. CompactIndex
218219 , R. confDiskCachePolicy = R. DiskCacheNone
219220 , R. confMergeSchedule = R. OneShot
220221 }
221222
223+ shrink R. TableConfig {.. } =
224+ [ R. TableConfig {
225+ confWriteBufferAlloc = confWriteBufferAlloc'
226+ , ..
227+ }
228+ | confWriteBufferAlloc' <- QC. shrink confWriteBufferAlloc
229+ ]
230+
231+ -- TODO: the current generator is suboptimal, and should be improved. There are
232+ -- some aspects to consider, and since they are at tension with each other, we
233+ -- should try find a good balance.
234+ --
235+ -- Say the write buffer allocation is @n@.
236+ --
237+ -- * If @n@ is too large, then the tests degrade to only testing the write
238+ -- buffer, because there are no flushes/merges.
239+ --
240+ -- * If @n@ is too small, then the resulting runs are also small. They might
241+ -- consist of only a few disk pages, or they might consist of only 1 underfull
242+ -- disk page. This means there are some parts of the code that we would rarely
243+ -- cover in the state machine tests.
244+ --
245+ -- * If @n@ is too small, then we flush/merge very frequently, which may exhaust
246+ -- the number of open file handles when using the real file system. Specially
247+ -- if the test fails and the shrinker kicks in, then @n@ can currently become
248+ -- very small. This is good for finding a minimal counterexample, but it might
249+ -- also make the real filesystem run out of file descriptors. Arguably, you
250+ -- could overcome this specific issue by only generating or shrinking to small
251+ -- @n@ when we use the mocked file system. This would require some boilerplate
252+ -- to add type level tags to distinguish between the two cases.
253+ instance Arbitrary R. WriteBufferAlloc where
254+ arbitrary = QC. scale (max 30 ) $ do
255+ QC. Positive x <- QC. arbitrary
256+ pure (R. AllocNumEntries (R. NumEntries x))
257+
258+ shrink (R. AllocNumEntries (R. NumEntries x)) =
259+ [ R. AllocNumEntries (R. NumEntries x')
260+ | QC. Positive x' <- QC. shrink (QC. Positive x)
261+ ]
262+
222263propLockstep_RealImpl_RealFS_IO ::
223264 Tracer IO R. LSMTreeTrace
224265 -> Actions (Lockstep (ModelState R. TableHandle ))
0 commit comments