packages feed

io-sim 1.10.0.0 → 1.10.1.0

raw patch · 7 files changed

+142/−15 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # Revision history of io-sim +## 1.10.1.0++### Non-breaking changes++* Added `IOSimPOR` `QuickCheck` combinators:+  * `monadicIOSimPOR_`+  * `monadicIOSimPOR`+  * `runIOSimPORGen`+* Support ghc-9.14+* Support QuickCheck-2.18.0.0+ ## 1.10.0.0  ### Breaking changes@@ -23,7 +34,9 @@   `EventLogEvaluationError`. * Added `Data.List.Trace.last` * Although `IOSim` and `IOSimPOR` are pure we use `evaluate` in a few places,-  non of them now catch asynchrounous exceptions.+  none of them now catch asynchronous exceptions.+* Added `IOSimPOR` QuickCheck monadic combinators:+  `monadicIOSimPOR`, `monadicIOSimPOR_` and `runIOSimPORGen`.  ## 1.9.1.0 
io-sim.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.4 name:                io-sim-version:             1.10.0.0+version:             1.10.1.0 synopsis:            A pure simulator for monadic concurrency with STM. description:   A pure simulator monad with support of concurrency (base & async style), stm,@@ -19,7 +19,7 @@ build-type:          Simple extra-doc-files:     CHANGELOG.md README.md bug-reports:         https://github.com/input-output-hk/io-sim/issues-tested-with:         GHC == { 9.6, 9.8, 9.10, 9.12 }+tested-with:         GHC == { 9.6, 9.8, 9.10, 9.12, 9.14 }  flag asserts   description: Enable assertions@@ -64,9 +64,9 @@   default-extensions:  LambdaCase   if impl(ghc < 9.4)     default-extensions: GADTs-  build-depends:       base              >=4.16 && <4.22,+  build-depends:       base              >=4.16 && <4.23,                        io-classes:{io-classes,strict-stm,si-timers}-                                        ^>=1.9 || ^>=1.10,+                                        ^>=1.10,                        exceptions        >=0.10,                        containers,                        deepseq,@@ -112,6 +112,8 @@                        -rtsopts   if impl(ghc >= 9.8)     ghc-options:       -Wno-x-partial+  if impl(ghc >= 9.14)+    ghc-options:       -Wno-incomplete-record-selectors  benchmark bench   import:              warnings
src/Control/Monad/IOSim.hs view
@@ -18,6 +18,9 @@   , monadicIOSim   , runIOSimGen     -- ** Explore races using /IOSimPOR/+  , monadicIOSimPOR_+  , monadicIOSimPOR+  , runIOSimPORGen     -- $iosimpor   , exploreSimTrace   , controlSimTrace@@ -801,3 +804,77 @@     Capture eval <- capture     let trace = runSimTrace (eval sim)     return (f trace)++-- | Like <runSTGen+-- https://hackage.haskell.org/package/QuickCheck-2.14.3/docs/Test-QuickCheck-Monadic.html#v:runSTGen>,+-- but evaluates generated simulations using 'exploreSimTrace'.+--+-- The callback receives the previously passing trace (if any) and the current+-- trace being checked.+--+-- @since 1.10.0.0+--+runIOSimPORGen :: Testable test+               => (ExplorationOptions -> ExplorationOptions)+               -> (Maybe (SimTrace a) -> SimTrace a -> test)+               -> (forall s. Gen (IOSim s a))+               -> Gen Property+runIOSimPORGen optsf k sim = do+  Capture eval <- capture+  pure $ exploreSimTrace optsf (eval sim) k++-- | A /IOSimPOR/ variant of 'monadicIOSim_', which:+--+-- * explores alternative schedules using 'exploreSimTrace';+-- * allows to run in monad stacks build on top of `IOSim`;+-- * gives more control how to attach debugging information to failed+--   tests.+--+-- Note, to use this combinator your monad needs to be defined as:+--+-- > newtype M s a = M { runM :: ReaderT State (IOSim s) a }+--+-- It's important that `M s` is a monad.  For such a monad you'll need to+-- provide a natural transformation:+-- @+--   -- the state could also be created as an `IOSim` computation.+--   nat :: forall s a. State -> M s a -> 'IOSim' s a+--   nat state m = runStateT (runM m) state+-- @+--+-- @since 1.10.0.0+--+monadicIOSimPOR :: (Testable a, forall s. Monad (m s))+                => (ExplorationOptions -> ExplorationOptions)+                -> (Maybe (SimTrace Property) -> SimTrace Property -> Property)+                -> (forall s a. m s a -> IOSim s a)+                -> (forall s. PropertyM (m s) a)+                -> Property+monadicIOSimPOR optsf f tr sim =+  property (runIOSimPORGen optsf f (tr <$> monadic' sim))++-- | Like <monadicST+-- https://hackage.haskell.org/package/QuickCheck-2.14.3/docs/Test-QuickCheck-Monadic.html#v:monadicST>,+-- but using /IOSimPOR/ schedule exploration.+--+-- Note: it calls `traceResult` in non-strict mode, e.g. leaked threads do not+-- cause failures.+--+-- > testProperty "example" $+-- >   monadicIOSimPOR_ $ do+-- >     x <- run (pure (1 :: Int))+-- >     assert (x == 1)+--+-- @since 1.10.0.0+--+monadicIOSimPOR_ :: Testable a+                 => (forall s. PropertyM (IOSim s) a)+                 -> Property+monadicIOSimPOR_ sim =+   monadicIOSimPOR+      id+      (\_ tr -> case traceResult False tr of+          Left e  -> counterexample (show e) False+          Right p -> p)+      id+      sim
src/Control/Monad/IOSim/Types.hs view
@@ -846,7 +846,6 @@   deriving Generic   deriving Show via Quiet SimEvent - -- | Pretty print a 'SimEvent'. -- ppSimEvent :: Int -- ^ width of the time
test/Test/Control/Monad/IOSim.hs view
@@ -56,9 +56,9 @@ tests =   testGroup "IOSim"   [ testProperty "read/write graph (IO)"    prop_stm_graph_io-  , testProperty "read/write graph (IOSim)" (withMaxSuccess 1000 prop_stm_graph_sim)+  , testProperty "read/write graph (IOSim)" (withNumTests 1000 prop_stm_graph_sim)   , testGroup "timeouts"-    [ testProperty "IOSim"                  (withMaxSuccess 1000 prop_timers_ST)+    [ testProperty "IOSim"                  (withNumTests 1000 prop_timers_ST)     -- fails since we just use `threadDelay` to schedule timers in `IO`.     , testProperty "IO"                     (expectFailure prop_timers_IO)     , testProperty "IOSim: no deadlock"     prop_timeout_no_deadlock_Sim@@ -83,8 +83,8 @@     [ testProperty "timeout: discardAfter"  unit_discardAfter     , testProperty "timeout: within"        unit_within     ]-  , testProperty "threadId order (IOSim)"   (withMaxSuccess 1000 prop_threadId_order_order_Sim)-  , testProperty "forkIO order (IOSim)"     (withMaxSuccess 1000 prop_fork_order_ST)+  , testProperty "threadId order (IOSim)"   (withNumTests 1000 prop_threadId_order_order_Sim)+  , testProperty "forkIO order (IOSim)"     (withNumTests 1000 prop_fork_order_ST)   , testProperty "order (IO)"               (expectFailure prop_fork_order_IO)   , testProperty "STM wakeup order"         prop_wakeup_order_ST   , testGroup "throw/catch unit tests"
test/Test/Control/Monad/IOSimPOR.hs view
@@ -45,6 +45,7 @@  import Data.List.Trace qualified as Trace import Test.QuickCheck+import Test.QuickCheck.Monadic (assert, run) import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck @@ -69,9 +70,9 @@     -- , testProperty "propPermutations" propPermutations     ]   , testGroup "IO simulator properties"-    [ testProperty "read/write graph (IOSim)" (withMaxSuccess 1000 prop_stm_graph_sim)+    [ testProperty "read/write graph (IOSim)" (withNumTests 1000 prop_stm_graph_sim)     , testGroup "timeouts"-      [ testProperty "IOSim"                  (withMaxSuccess 1000 prop_timers_ST)+      [ testProperty "IOSim"                  (withNumTests 1000 prop_timers_ST)       , testProperty "IOSim: no deadlock"     prop_timeout_no_deadlock_Sim       , testProperty "timeout"                prop_timeout       , testProperty "timeouts"               prop_timeouts@@ -85,8 +86,8 @@         ]       ]     , testProperty "infinite simulation"      prop_explore_endless_simulation-    , testProperty "threadId order (IOSim)"   (withMaxSuccess 1000 prop_threadId_order_order_Sim)-    , testProperty "forkIO order (IOSim)"     (withMaxSuccess 1000 prop_fork_order_ST)+    , testProperty "threadId order (IOSim)"   (withNumTests 1000 prop_threadId_order_order_Sim)+    , testProperty "forkIO order (IOSim)"     (withNumTests 1000 prop_fork_order_ST)     , testGroup "throw/catch unit tests"       [ testProperty "0" unit_catch_0       , testProperty "1" unit_catch_1@@ -123,6 +124,11 @@       , testProperty "catch: throwTo async blocking (IOSim)"       $ forall_masking_states unit_catch_throwTo_masking_state_async_mayblock_ST       ]+    , testGroup "PropertyM callbacks"+      [ testProperty "happy path"      unit_monadicIOSimPOR_0+      , testProperty "failing assert"  unit_monadicIOSimPOR_1+      , testProperty "exception"       unit_monadicIOSimPOR_2+      ]     , testProperty "evaluate unit test" unit_evaluate_0     , testGroup "forkIO unit tests"       [ testProperty "1" unit_fork_1@@ -756,6 +762,30 @@                       say "after"                    ) $ \_ trace ->     selectTraceSay trace === ["inner", "handler1", "handler2", "after"]++unit_monadicIOSimPOR_0, unit_monadicIOSimPOR_1, unit_monadicIOSimPOR_2+  :: Property++-- | Basic success case: a PropertyM test can be executed through IOSimPOR.+unit_monadicIOSimPOR_0 =+  monadicIOSimPOR_ $ do+    x <- run (pure (1 :: Int))+    assert (x == 1)++-- | Failing assertions inside PropertyM are reported as property failures.+unit_monadicIOSimPOR_1 =+  expectFailure $+    monadicIOSimPOR_ $ do+      x <- run (pure (1 :: Int))+      assert (x == 2)++-- | Exceptions thrown by the simulation are turned into failing properties via+-- `traceResult False`, matching the manual workaround from issue #229.+unit_monadicIOSimPOR_2 =+  expectFailure $+    monadicIOSimPOR_ $ do+      _ <- run $ evaluate (error "boom" :: ())+      assert True  -- evaluate should catch pure errors unit_evaluate_0 :: Property
test/Test/Control/Monad/Utils.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} module Test.Control.Monad.Utils where  import Data.Array@@ -18,6 +19,11 @@  import Test.QuickCheck +#if !MIN_VERSION_QuickCheck(2,18,0)+withNumTests :: Testable prop => Int -> prop -> Property+withNumTests = withMaxSuccess+#endif+ -- -- Read/Write graph --@@ -489,7 +495,7 @@                       -> Property forall_masking_states prop =     -- make sure that the property is executed once!-    withMaxSuccess 1 $+    withNumTests 1 $     foldr (\ms p -> counterexample (show ms) (prop ms) .&&. p)           (property True)           [Unmasked, MaskedInterruptible, MaskedUninterruptible]