{-# LANGUAGE UndecidableInstances, DeriveDataTypeable #-}
module Test.Framework.Core where
import Test.Framework.Improving
import Test.Framework.Options
import Control.Arrow (first, second)
import Control.Concurrent.MVar ( withMVar, newMVar, MVar )
import Data.Typeable ( Typeable )
class (Show i, Show r) => TestResultlike i r | r -> i where
testSucceeded :: r -> Bool
class TestResultlike i r => Testlike i r t | t -> i r, r -> i where
runTest :: CompleteTestOptions -> t -> IO (i :~> r, IO ())
testTypeName :: t -> TestTypeName
type TestName = String
type TestTypeName = String
data Test = forall i r t.
(Testlike i r t, Typeable t) => Test TestName t
| TestGroup TestName [Test]
| PlusTestOptions TestOptions Test
| BuildTestBracketed (IO (Test, IO ()))
testGroup :: TestName -> [Test] -> Test
testGroup :: TestName -> [Test] -> Test
testGroup = TestName -> [Test] -> Test
TestGroup
plusTestOptions :: TestOptions -> Test -> Test
plusTestOptions :: TestOptions -> Test -> Test
plusTestOptions = TestOptions -> Test -> Test
PlusTestOptions
buildTest :: IO Test -> Test
buildTest :: IO Test -> Test
buildTest IO Test
mx = IO (Test, IO ()) -> Test
BuildTestBracketed ((Test -> (Test, IO ())) -> IO Test -> IO (Test, IO ())
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Test -> IO () -> (Test, IO ())) -> IO () -> Test -> (Test, IO ())
forall a b c. (a -> b -> c) -> b -> a -> c
flip (,) (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())) IO Test
mx)
buildTestBracketed :: IO (Test, IO ()) -> Test
buildTestBracketed :: IO (Test, IO ()) -> Test
buildTestBracketed = IO (Test, IO ()) -> Test
BuildTestBracketed
data MutuallyExcluded t = ME (MVar ()) t
deriving Typeable
instance Testlike i r t => Testlike i r (MutuallyExcluded t) where
runTest :: CompleteTestOptions -> MutuallyExcluded t -> IO (i :~> r, IO ())
runTest CompleteTestOptions
cto (ME MVar ()
mvar t
x) = ((i :~> r, IO ()) -> (i :~> r, IO ()))
-> IO (i :~> r, IO ()) -> IO (i :~> r, IO ())
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((IO () -> IO ()) -> (i :~> r, IO ()) -> (i :~> r, IO ())
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (\IO ()
act -> MVar () -> (() -> IO ()) -> IO ()
forall a b. MVar a -> (a -> IO b) -> IO b
withMVar MVar ()
mvar ((() -> IO ()) -> IO ()) -> (() -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \() -> IO ()
act)) (IO (i :~> r, IO ()) -> IO (i :~> r, IO ()))
-> IO (i :~> r, IO ()) -> IO (i :~> r, IO ())
forall a b. (a -> b) -> a -> b
$ CompleteTestOptions -> t -> IO (i :~> r, IO ())
forall i r t.
Testlike i r t =>
CompleteTestOptions -> t -> IO (i :~> r, IO ())
runTest CompleteTestOptions
cto t
x
testTypeName :: MutuallyExcluded t -> TestName
testTypeName ~(ME MVar ()
_ t
x) = t -> TestName
forall i r t. Testlike i r t => t -> TestName
testTypeName t
x
{-# NOINLINE mutuallyExclusive #-}
mutuallyExclusive :: Test -> Test
mutuallyExclusive :: Test -> Test
mutuallyExclusive Test
init_t = IO Test -> Test
buildTest (IO Test -> Test) -> IO Test -> Test
forall a b. (a -> b) -> a -> b
$ do
MVar ()
mvar <- () -> IO (MVar ())
forall a. a -> IO (MVar a)
newMVar ()
let go :: Test -> Test
go (Test TestName
tn t
t) = TestName -> MutuallyExcluded t -> Test
forall i r t. (Testlike i r t, Typeable t) => TestName -> t -> Test
Test TestName
tn (MVar () -> t -> MutuallyExcluded t
forall t. MVar () -> t -> MutuallyExcluded t
ME MVar ()
mvar t
t)
go (TestGroup TestName
tn [Test]
ts) = TestName -> [Test] -> Test
TestGroup TestName
tn ((Test -> Test) -> [Test] -> [Test]
forall a b. (a -> b) -> [a] -> [b]
map Test -> Test
go [Test]
ts)
go (PlusTestOptions TestOptions
to Test
t) = TestOptions -> Test -> Test
PlusTestOptions TestOptions
to (Test -> Test
go Test
t)
go (BuildTestBracketed IO (Test, IO ())
build) = IO (Test, IO ()) -> Test
BuildTestBracketed (((Test, IO ()) -> (Test, IO ()))
-> IO (Test, IO ()) -> IO (Test, IO ())
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Test -> Test) -> (Test, IO ()) -> (Test, IO ())
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first Test -> Test
go) IO (Test, IO ())
build)
Test -> IO Test
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Test -> Test
go Test
init_t)