2017-09-20 01:17:02 +03:00
|
|
|
{-# LANGUAGE GADTs #-}
|
|
|
|
{-# LANGUAGE RankNTypes #-}
|
|
|
|
|
|
|
|
module Common
|
|
|
|
( module Common
|
|
|
|
, TF.Test
|
|
|
|
) where
|
|
|
|
|
|
|
|
import Control.Exception (ArithException, ArrayException, SomeException)
|
|
|
|
import Control.Monad (void)
|
|
|
|
import qualified Control.Monad.Catch as C
|
2017-09-20 01:40:38 +03:00
|
|
|
import Control.Monad.Conc.Class
|
|
|
|
import Control.Monad.STM.Class
|
2017-09-20 01:17:02 +03:00
|
|
|
import System.Random (mkStdGen)
|
2017-09-25 17:59:10 +03:00
|
|
|
import Test.DejaFu (Predicate, Result(..))
|
2017-09-20 01:17:02 +03:00
|
|
|
import Test.DejaFu.Conc (ConcST)
|
|
|
|
import qualified Test.Framework as TF
|
|
|
|
import Test.Framework.Providers.HUnit (hUnitTestToTests)
|
|
|
|
import qualified Test.HUnit as TH
|
2017-09-20 01:40:38 +03:00
|
|
|
import Test.HUnit.DejaFu (Bounds, defaultBounds, defaultMemType, uniformly, randomly, swarmy, systematically, testDejafu, testDejafuWay)
|
2017-09-20 01:17:02 +03:00
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- Tests
|
|
|
|
|
|
|
|
class IsTest t where
|
|
|
|
toTestList :: t -> [TF.Test]
|
|
|
|
|
|
|
|
instance IsTest TF.Test where
|
|
|
|
toTestList t = [t]
|
|
|
|
|
|
|
|
instance IsTest TH.Test where
|
|
|
|
toTestList = hUnitTestToTests
|
|
|
|
|
|
|
|
instance IsTest T where
|
|
|
|
toTestList (T n c p) = toTestList (BT n c p defaultBounds)
|
|
|
|
toTestList (BT n c p b) = toTestList . testGroup n $
|
|
|
|
let mk way name = testDejafuWay way defaultMemType c name p
|
|
|
|
g = mkStdGen 0
|
|
|
|
in [ mk (systematically b) "systematically"
|
|
|
|
, mk (uniformly g 100) "uniformly"
|
|
|
|
, mk (randomly g 100) "randomly"
|
|
|
|
, mk (swarmy g 100 10) "swarmy"
|
|
|
|
]
|
|
|
|
|
|
|
|
instance IsTest t => IsTest [t] where
|
|
|
|
toTestList = concatMap toTestList
|
|
|
|
|
|
|
|
data T where
|
|
|
|
T :: Show a => String -> (forall t. ConcST t a) -> Predicate a -> T
|
|
|
|
BT :: Show a => String -> (forall t. ConcST t a) -> Predicate a -> Bounds -> T
|
|
|
|
|
|
|
|
testGroup :: IsTest t => String -> t -> TF.Test
|
|
|
|
testGroup name = TF.testGroup name . toTestList
|
|
|
|
|
2017-09-20 01:40:38 +03:00
|
|
|
djfu :: Show a => String -> Predicate a -> (forall t. ConcST t a) -> TF.Test
|
|
|
|
djfu name p c = head . toTestList $ testDejafu c name p
|
|
|
|
|
|
|
|
djfuT :: Show a => String -> Predicate a -> (forall t. ConcST t a) -> [TF.Test]
|
|
|
|
djfuT name p c = toTestList $ T name c p
|
|
|
|
|
2017-09-20 01:17:02 +03:00
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- Exceptions
|
|
|
|
|
|
|
|
catchArithException :: C.MonadCatch m => m a -> (ArithException -> m a) -> m a
|
|
|
|
catchArithException = C.catch
|
|
|
|
|
|
|
|
catchArrayException :: C.MonadCatch m => m a -> (ArrayException -> m a) -> m a
|
|
|
|
catchArrayException = C.catch
|
|
|
|
|
|
|
|
catchSomeException :: C.MonadCatch m => m a -> (SomeException -> m a) -> m a
|
|
|
|
catchSomeException = C.catch
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- Utilities
|
|
|
|
|
|
|
|
(|||) :: MonadConc m => m a -> m b -> m ()
|
|
|
|
a ||| b = do
|
|
|
|
j <- spawn a
|
|
|
|
void b
|
|
|
|
void (readMVar j)
|
2017-09-20 01:40:38 +03:00
|
|
|
|
|
|
|
-- | Create an empty monomorphic @MVar@.
|
|
|
|
newEmptyMVarInt :: MonadConc m => m (MVar m Int)
|
|
|
|
newEmptyMVarInt = newEmptyMVar
|
|
|
|
|
|
|
|
-- | Create a full monomorphic @MVar@.
|
|
|
|
newMVarInt :: MonadConc m => Int -> m (MVar m Int)
|
|
|
|
newMVarInt = newMVar
|
|
|
|
|
|
|
|
-- | Create a monomorphic @CRef@.
|
|
|
|
newCRefInt :: MonadConc m => Int -> m (CRef m Int)
|
|
|
|
newCRefInt = newCRef
|
|
|
|
|
|
|
|
-- | Create a monomorphic @TVar@.
|
|
|
|
newTVarInt :: MonadSTM stm => Int -> stm (TVar stm Int)
|
|
|
|
newTVarInt = newTVar
|
2017-09-25 17:59:10 +03:00
|
|
|
|
|
|
|
-- | A test which should fail.
|
|
|
|
failing :: Predicate a -> Predicate a
|
|
|
|
failing p as =
|
|
|
|
let result = p as
|
|
|
|
in result { _pass = not (_pass result) }
|