Skip to content

Commit 456f235

Browse files
committed
Improve the reliability of forgotten refs checking in the SM tests
Make sure the forgotten refs state is reset reliably after each run, so that during shrinking we do not get false errors from previous runs causing us to produce nonsense shrunk test cases.
1 parent 9607654 commit 456f235

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)