Skip to content

Commit f56fc79

Browse files
authored
Merge pull request #594 from IntersectMBO/dcoutts/forgotten-ref-checking-reliability
Improve the reliability of forgotten refs checking in the state machine tests
2 parents 39a6fd8 + 456f235 commit f56fc79

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

src-control/Control/RefCount.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,11 @@ checkForgottenRefs = do
547547
where
548548
#endif
549549

550-
-- | Run 'checkForgottenRefs', but ignore the resulting exception, if any.
550+
-- | Ignore and reset the state of forgotten reference tracking. This ensures
551+
-- that any stale fogotten references are not reported later.
552+
--
553+
-- This is especillay important in QC tests with shrinking which otherwise
554+
-- leads to confusion.
551555
ignoreForgottenRefs :: IO ()
552556
ignoreForgottenRefs = void $ try @_ @SomeException $ checkForgottenRefs
553557

test/Test/Database/LSMTree/StateMachine.hs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ import Control.Monad.Class.MonadThrow (Exception (..), Handler (..),
7979
import Control.Monad.IOSim
8080
import Control.Monad.Primitive
8181
import Control.Monad.Reader (ReaderT (..))
82-
import Control.RefCount (RefException, checkForgottenRefs)
82+
import Control.RefCount (RefException, checkForgottenRefs,
83+
ignoreForgottenRefs)
8384
import Control.Tracer (Tracer, nullTracer)
8485
import Data.Bifunctor (Bifunctor (..))
8586
import Data.Constraint (Dict (..))
@@ -2251,15 +2252,19 @@ runActionsBracket p init cleanup runner tagger actions =
22512252
$ QLS.runActionsBracket p init cleanup' runner actions
22522253
where
22532254
cleanup' st = do
2254-
x <- cleanup st
2255-
pure (x QC..&&. propCheckForgottenRefs)
2256-
2257-
propCheckForgottenRefs :: Property
2258-
propCheckForgottenRefs = QC.ioProperty $ do
2259-
eith <- Control.Exception.try checkForgottenRefs
2260-
pure $ case eith of
2261-
Left (e :: RefException) -> QC.counterexample (show e) False
2262-
Right () -> QC.property True
2255+
x <- cleanup st `onException` ignoreForgottenRefs
2256+
-- We want to do checkForgottenRefs after cleanup, since cleanup itself
2257+
-- may lead to forgotten refs. And checkForgottenRefs has the crucial
2258+
-- side effect of reseting the forgotten refs state. If we don't do this
2259+
-- then the next test run (e.g. during shrinking) will encounter a
2260+
-- false/stale forgotten refs exception. But we also have to make sure
2261+
-- that if cleanup itself fails, that we reset the forgotten refs state!
2262+
e <- Control.Exception.try checkForgottenRefs
2263+
pure (x QC..&&. propCheckForgottenRefs e)
2264+
2265+
propCheckForgottenRefs :: Either RefException () -> Property
2266+
propCheckForgottenRefs (Left e) = QC.counterexample (show e) False
2267+
propCheckForgottenRefs (Right ()) = QC.property True
22632268

22642269
tagFinalState ::
22652270
forall state. StateModel (Lockstep state)

0 commit comments

Comments
 (0)