@@ -343,51 +343,72 @@ instance Arbitrary P where
343
343
<> [PMergingRun m' | m' <- shrink m]
344
344
345
345
instance (Arbitrary t , IsMergeType t ) => Arbitrary (M t ) where
346
- arbitrary = QC. frequency
347
- [ (1 , do (mt, r) <- arbitrary
348
- let md = MergeDebt (runSize r)
349
- pure $ MCompleted mt md r)
350
- , (1 , do
351
- mt <- arbitrary
352
- n <- QC. chooseInt (2 , 8 )
353
- rs <- QC. vectorOf n (QC. scale (`div` n) arbitrary)
354
- let totalDebt = sum (map (length . getNonEmptyRun) rs)
355
- suppliedCredits <- QC. chooseInt (0 , totalDebt- 1 )
356
- unspentCredits <- QC. chooseInt (0 , min (mergeBatchSize- 1 ) suppliedCredits)
357
- let spentCredits = suppliedCredits - unspentCredits
358
- let md = MergeDebt {
359
- totalDebt
360
- }
361
- mc = MergeCredit {
362
- unspentCredits,
363
- spentCredits
364
- }
365
- assert (mergeDebtInvariant md mc) $
366
- return (MOngoing mt md mc rs))
346
+ arbitrary = QC. oneof
347
+ [ do (mt, r) <- arbitrary
348
+ let md = MergeDebt (runSize r)
349
+ pure (MCompleted mt md r)
350
+ , do mt <- arbitrary
351
+ n <- QC. chooseInt (2 , 8 )
352
+ rs <- QC. vectorOf n (QC. scale (`div` n) arbitrary)
353
+ (md, mc) <- genMergeCreditForRuns rs
354
+ pure (MOngoing mt md mc rs)
367
355
]
368
356
369
357
shrink (MCompleted mt md r) =
370
358
[ MCompleted mt md r' | r' <- shrink r ]
371
- shrink m@ (MOngoing mt md MergeCredit {spentCredits, unspentCredits} rs) =
359
+ shrink m@ (MOngoing mt md mc rs) =
372
360
[ MCompleted mt md (completeM m) ]
373
- <> [ assert (mergeDebtInvariant md' mc') $
374
- MOngoing mt md' mc' rs'
361
+ <> [ MOngoing mt md' mc' rs'
375
362
| rs' <- shrink rs
376
363
, length rs' > 1
377
- , let totalDebt' = sum (map (length . getNonEmptyRun) rs')
378
- , suppliedCredits' <- shrink (min (spentCredits+ unspentCredits)
379
- (totalDebt'- 1 ))
380
- , unspentCredits' <- shrink (min unspentCredits suppliedCredits')
381
- , let spentCredits' = suppliedCredits' - unspentCredits'
382
- , let md' = MergeDebt {
383
- totalDebt = totalDebt'
384
- }
385
- mc' = MergeCredit {
386
- spentCredits = spentCredits',
387
- unspentCredits = unspentCredits'
388
- }
364
+ , (md', mc') <- shrinkMergeCreditForRuns rs' mc
389
365
]
390
366
367
+ -- | The 'MergeDebt' and 'MergeCredit' must maintain a couple invariants:
368
+ --
369
+ -- * the total debt must be the same as the sum of the input run sizes;
370
+ -- * the supplied credit is less than the total merge debt.
371
+ --
372
+ genMergeCreditForRuns :: [NonEmptyRun ] -> QC. Gen (MergeDebt , MergeCredit )
373
+ genMergeCreditForRuns rs = do
374
+ let totalDebt = sum (map (length . getNonEmptyRun) rs)
375
+ suppliedCredits <- QC. chooseInt (0 , totalDebt- 1 )
376
+ unspentCredits <- QC. chooseInt (0 , min (mergeBatchSize- 1 ) suppliedCredits)
377
+ let spentCredits = suppliedCredits - unspentCredits
378
+ md = MergeDebt {
379
+ totalDebt
380
+ }
381
+ mc = MergeCredit {
382
+ unspentCredits,
383
+ spentCredits
384
+ }
385
+ assert (mergeDebtInvariant md mc) $
386
+ pure (md, mc)
387
+
388
+ -- | Shrink the 'MergeDebt' and 'MergeCredit' given the old 'MergeCredit' and
389
+ -- the already-shrunk runs.
390
+ --
391
+ -- Thus must maintain invariants, see 'genMergeCreditForDebt'.
392
+ --
393
+ shrinkMergeCreditForRuns :: [NonEmptyRun ]
394
+ -> MergeCredit -> [(MergeDebt , MergeCredit )]
395
+ shrinkMergeCreditForRuns rs' MergeCredit {spentCredits, unspentCredits} =
396
+ [ assert (mergeDebtInvariant md' mc')
397
+ (md', mc')
398
+ | let totalDebt' = sum (map (length . getNonEmptyRun) rs')
399
+ , suppliedCredits' <- shrink (min (spentCredits+ unspentCredits)
400
+ (totalDebt'- 1 ))
401
+ , unspentCredits' <- shrink (min unspentCredits suppliedCredits')
402
+ , let spentCredits' = suppliedCredits' - unspentCredits'
403
+ md' = MergeDebt {
404
+ totalDebt = totalDebt'
405
+ }
406
+ mc' = MergeCredit {
407
+ spentCredits = spentCredits',
408
+ unspentCredits = unspentCredits'
409
+ }
410
+ ]
411
+
391
412
instance Arbitrary NonEmptyRun where
392
413
arbitrary = do
393
414
s <- QC. getSize
0 commit comments