Skip to content

Commit 0d7dcfe

Browse files
Initial stab at parallel actions (#94)
1 parent f2d9800 commit 0d7dcfe

File tree

14 files changed

+682
-152
lines changed

14 files changed

+682
-152
lines changed

.github/workflows/haskell-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040

4141
strategy:
4242
matrix:
43-
ghc-version: [latest, 9.12, "9.10", 9.8, 9.6, 9.4, 9.2, 9.0, "8.10"]
43+
ghc-version: [latest, 9.12, "9.10", 9.8, 9.6, 9.4, 9.2, 9.0]
4444
os: [ubuntu-latest]
4545
fail-fast: false
4646

cabal.project

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,16 @@ packages:
44
tests: true
55

66
test-show-details: direct
7+
8+
source-repository-package
9+
type: git
10+
location: https://github.com/input-output-hk/io-sim
11+
subdir: io-sim
12+
tag: 5683864d3c7300f9ee4a3430b4a590bb130cb88a
13+
14+
15+
source-repository-package
16+
type: git
17+
location: https://github.com/input-output-hk/io-sim
18+
subdir: io-classes
19+
tag: 5683864d3c7300f9ee4a3430b4a590bb130cb88a

quickcheck-dynamic/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
77
As a minor extension, we also keep a semantic version for the `UNRELEASED`
88
changes.
99

10+
## UNRELEASED
11+
12+
* **BREAKING**: Removed `m` parameter from `PostConditionM` as this is not generally safe.
13+
* **BREAKING**: Additional `Show` constraint on the result of actions
14+
* A new module `Test.QuickCheck.ParallelActions` that implements testing linearizability of a model
15+
when running in parallel.
16+
* Additional `Property` combinators `sometimes` and `always`
17+
1018
## 4.0.0 - 2025-03-12
1119

1220
* **BREAKING**: Removed `Realized`

quickcheck-dynamic/quickcheck-dynamic.cabal

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ license-files:
66
LICENSE
77
NOTICE
88

9+
Tested-with: GHC >= 9.0 && < 9.13
910
maintainer: [email protected]
1011
author: Ulf Norell
1112
category: Testing
@@ -27,6 +28,9 @@ source-repository head
2728
type: git
2829
location: https://github.com/input-output-hk/quickcheck-dynamic
2930

31+
flag dev
32+
default: False
33+
3034
common lang
3135
default-language: Haskell2010
3236
default-extensions:
@@ -62,6 +66,7 @@ common lang
6266
-Wall -Wnoncanonical-monad-instances -Wunused-packages
6367
-Wincomplete-uni-patterns -Wincomplete-record-updates
6468
-Wredundant-constraints -Widentities -Wno-unused-do-bind
69+
-Wno-name-shadowing -Wno-x-partial
6570

6671
library
6772
import: lang
@@ -76,6 +81,23 @@ library
7681
Test.QuickCheck.Extras
7782
Test.QuickCheck.StateModel
7883
Test.QuickCheck.StateModel.Variables
84+
Test.QuickCheck.ParallelActions
85+
86+
if flag(dev)
87+
hs-source-dirs: test
88+
exposed-modules:
89+
Spec.DynamicLogic.Counters
90+
Spec.DynamicLogic.Registry
91+
Spec.DynamicLogic.RegistryModel
92+
Test.QuickCheck.DynamicLogic.QuantifySpec
93+
Test.QuickCheck.StateModelSpec
94+
build-depends:
95+
, io-classes
96+
, io-sim
97+
, stm
98+
, tasty
99+
, tasty-hunit
100+
, tasty-quickcheck
79101

80102
build-depends:
81103
, base >=4.7 && <5
@@ -100,6 +122,8 @@ test-suite quickcheck-dynamic-test
100122
build-depends:
101123
, base
102124
, containers
125+
, io-classes
126+
, io-sim
103127
, mtl
104128
, QuickCheck
105129
, quickcheck-dynamic

quickcheck-dynamic/src/Test/QuickCheck/DynamicLogic.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ instance Monad (DL s) where
6060
instance MonadFail (DL s) where
6161
fail = errorDL
6262

63-
action :: (Typeable a, Eq (Action s a), Show (Action s a)) => Action s a -> DL s (Var a)
63+
action :: (Typeable a, Show a, Eq (Action s a), Show (Action s a)) => Action s a -> DL s (Var a)
6464
action cmd = DL $ \_ k -> DL.after cmd k
6565

66-
failingAction :: (Typeable a, Eq (Action s a), Show (Action s a)) => Action s a -> DL s ()
66+
failingAction :: (Typeable a, Show a, Eq (Action s a), Show (Action s a)) => Action s a -> DL s ()
6767
failingAction cmd = DL $ \_ k -> DL.afterNegative cmd (k ())
6868

6969
anyAction :: DL s ()
@@ -96,7 +96,7 @@ getModelStateDL = DL $ \s k -> k (underlyingState s) s
9696
getVarContextDL :: DL s VarContext
9797
getVarContextDL = DL $ \s k -> k (vars s) s
9898

99-
forAllVar :: forall a s. Typeable a => DL s (Var a)
99+
forAllVar :: forall a s. (Typeable a, Show a) => DL s (Var a)
100100
forAllVar = do
101101
xs <- ctxAtType <$> getVarContextDL
102102
forAllQ $ elementsQ xs

quickcheck-dynamic/src/Test/QuickCheck/DynamicLogic/Internal.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ data DynLogic s
3333
Stopping (DynLogic s)
3434
| -- | After a specific action the predicate should hold
3535
forall a.
36-
(Eq (Action s a), Show (Action s a), Typeable a) =>
36+
(Eq (Action s a), Show (Action s a), Typeable a, Show a) =>
3737
After (ActionWithPolarity s a) (Var a -> DynPred s)
3838
| Error String (DynPred s)
3939
| -- | Adjust the probability of picking a branch
@@ -66,7 +66,7 @@ afterAny :: (Annotated s -> DynFormula s) -> DynFormula s
6666
afterAny f = DynFormula $ \n -> AfterAny $ \s -> unDynFormula (f s) n
6767

6868
afterPolar
69-
:: (Typeable a, Eq (Action s a), Show (Action s a))
69+
:: (Typeable a, Show a, Eq (Action s a), Show (Action s a))
7070
=> ActionWithPolarity s a
7171
-> (Var a -> Annotated s -> DynFormula s)
7272
-> DynFormula s
@@ -75,7 +75,7 @@ afterPolar act f = DynFormula $ \n -> After act $ \x s -> unDynFormula (f x s) n
7575
-- | Given `f` must be `True` after /some/ action.
7676
-- `f` is passed the state resulting from executing the `Action`.
7777
after
78-
:: (Typeable a, Eq (Action s a), Show (Action s a))
78+
:: (Typeable a, Show a, Eq (Action s a), Show (Action s a))
7979
=> Action s a
8080
-> (Var a -> Annotated s -> DynFormula s)
8181
-> DynFormula s
@@ -85,7 +85,7 @@ after act f = afterPolar (ActionWithPolarity act PosPolarity) f
8585
-- `f` is passed the state resulting from executing the `Action`
8686
-- as a negative action.
8787
afterNegative
88-
:: (Typeable a, Eq (Action s a), Show (Action s a))
88+
:: (Typeable a, Show a, Eq (Action s a), Show (Action s a))
8989
=> Action s a
9090
-> (Annotated s -> DynFormula s)
9191
-> DynFormula s

quickcheck-dynamic/src/Test/QuickCheck/Extras.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module Test.QuickCheck.Extras where
22

33
import Control.Monad.Reader
44
import Control.Monad.State
5+
import Test.QuickCheck
56
import Test.QuickCheck.Monadic
67

78
runPropertyStateT :: Monad m => PropertyM (StateT s m) a -> s -> PropertyM m (a, s)
@@ -13,3 +14,9 @@ runPropertyReaderT :: Monad m => PropertyM (ReaderT e m) a -> e -> PropertyM m a
1314
runPropertyReaderT p e = MkPropertyM $ \k -> do
1415
m <- unPropertyM p $ fmap lift . k
1516
return $ runReaderT m e
17+
18+
sometimes :: Testable p => Int -> p -> Property
19+
sometimes i = disjoin . replicate i
20+
21+
always :: Testable p => Int -> p -> Property
22+
always i = conjoin . replicate i

0 commit comments

Comments
 (0)