dejafu/dejafu-tests/Common.hs

115 lines
3.6 KiB
Haskell
Raw Normal View History

{-# 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
import System.Random (mkStdGen)
import Test.DejaFu (Predicate, Failure, Result(..), alwaysTrue)
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)
import qualified Test.LeanCheck as LeanCheck
-------------------------------------------------------------------------------
-- 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 = hunitTest $ testDejafu c name p
2017-09-20 01:40:38 +03:00
djfuT :: Show a => String -> Predicate a -> (forall t. ConcST t a) -> [TF.Test]
djfuT name p c = toTestList $ T name c p
alwaysFailsWith :: (Failure -> Bool) -> Predicate a
alwaysFailsWith p = alwaysTrue (either p (const False))
leancheck :: LeanCheck.Testable a => String -> a -> TF.Test
leancheck name = hunitTest . TH.TestLabel name . lcheck . LeanCheck.counterExamples 2500 where
lcheck = TH.TestCase . TH.assertString . unlines . map showf
showf xs = "Failed for " ++ unwords xs
hunitTest :: TH.Test -> TF.Test
hunitTest = head . toTestList
-------------------------------------------------------------------------------
-- 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) }