packages feed

quickcheck-dynamic 3.0.3 → 3.1.0

raw patch · 3 files changed

+31/−5 lines, 3 files

Files

CHANGELOG.md view
@@ -9,6 +9,13 @@  ## UNRELEASED +## 3.1.0 - 2023-04-10++* **BREAKING**: Change the type of `postcondition` to allow you to+  express property monitoring (e.g. stats or counterexamples) in the+  postcondition itself - rather than duplicating code for counterexamples+  in the `monitoring` function.+ ## 3.0.3 - 2023-04-18  * Added `hasNoVariablesQ` and `forAllNonVariableDL` functions to help make
quickcheck-dynamic.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.2 name:            quickcheck-dynamic-version:         3.0.3+version:         3.1.0 license:         Apache-2.0 license-files:   LICENSE@@ -54,6 +54,7 @@     TypeOperators     DerivingVia     DeriveGeneric+    GeneralizedNewtypeDeriving    ghc-options:     -Wall -Wnoncanonical-monad-instances -Wunused-packages
src/Test/QuickCheck/StateModel.hs view
@@ -11,6 +11,7 @@   module Test.QuickCheck.StateModel.Variables,   StateModel (..),   RunModel (..),+  PostconditionM (..),   WithUsedVars (..),   Annotated (..),   Step (..),@@ -22,6 +23,8 @@   Env,   Realized,   Generic,+  monitorPost,+  counterexamplePost,   stateAfter,   runActions,   lookUpVar,@@ -37,7 +40,7 @@ import Control.Monad.Identity import Control.Monad.Reader import Control.Monad.State-import Control.Monad.Writer (WriterT)+import Control.Monad.Writer (Endo (..), WriterT, runWriterT, tell) import Data.Data import Data.Kind import Data.List@@ -137,6 +140,19 @@ type instance Realized (WriterT w m) a = Realized m a type instance Realized Identity a = a +newtype PostconditionM m a = PostconditionM {runPost :: WriterT (Endo Property, Endo Property) m a}+  deriving (Functor, Applicative, Monad, MonadTrans)++-- | Apply the property transformation to the property after evaluating+-- the postcondition. Useful for collecting statistics while avoiding+-- duplication between `monitoring` and `postcondition`.+monitorPost :: Monad m => (Property -> Property) -> PostconditionM m ()+monitorPost m = PostconditionM $ tell (Endo m, mempty)++-- | Acts as `Test.QuickCheck.counterexample` if the postcondition fails.+counterexamplePost :: Monad m => String -> PostconditionM m ()+counterexamplePost c = PostconditionM $ tell (mempty, Endo $ counterexample c)+ class Monad m => RunModel state m where   -- | Perform an `Action` in some `state` in the `Monad` `m`.  This   -- is the function that's used to exercise the actual stateful@@ -153,10 +169,10 @@   -- | Postcondition on the `a` value produced at some step.   -- The result is `assert`ed and will make the property fail should it be `False`. This is useful   -- to check the implementation produces expected values.-  postcondition :: forall a. (state, state) -> Action state a -> LookUp m -> Realized m a -> m Bool+  postcondition :: forall a. (state, state) -> Action state a -> LookUp m -> Realized m a -> PostconditionM m Bool   postcondition _ _ _ _ = pure True -  -- | Allows the user to attach information to the `Property` at each step of the process.+  -- | Allows the user to attach additional information to the `Property` at each step of the process.   -- This function is given the full transition that's been executed, including the start and ending   -- `state`, the `Action`, the current environment to `Lookup` and the value produced by `perform`   -- while executing this step.@@ -381,6 +397,8 @@           s' = computeNextState s act var           env' = (var :== ret) : env       monitor (monitoring @state @m (underlyingState s, underlyingState s') act (lookUpVar env') ret)-      b <- run $ postcondition @state @m (underlyingState s, underlyingState s') act (lookUpVar env) ret+      (b, (Endo mon, Endo onFail)) <- run . runWriterT . runPost $ postcondition @state @m (underlyingState s, underlyingState s') act (lookUpVar env) ret+      monitor mon+      unless b $ monitor onFail       assert b       loop s' env' as