{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

module Test.Syd.Def.TestDefM where

import Control.Monad
import Control.Monad.RWS.Strict
import Control.Monad.Random
import Data.DList (DList)
import qualified Data.DList as DList
import Data.Kind
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import System.Random.Shuffle
import Test.QuickCheck.IO ()
import Test.Syd.OptParse
import Test.Syd.Run
import Test.Syd.SpecDef

-- | A synonym for easy migration from hspec
type Spec = SpecWith ()

-- | A synonym for easy migration from hspec
type SpecWith inner = SpecM inner ()

-- | A synonym for easy migration from hspec
type SpecM inner result = TestDefM '[] inner result

-- | A synonym for a test suite definition
type TestDef outers inner = TestDefM outers inner ()

-- | The test definition monad
--
-- This type has three parameters:
--
-- * @outers@: A type-level list of the outer resources. These are resources that are prived once, around a group of tests. (This is the type of the results of `aroundAll`.)
-- * @inner@: The inner resource. This is a resource that is set up around every test, and even every example of a property test. (This is the type of the result of `around`.)
-- * @result@: The result ('TestDefM' is a monad.)
--
-- In practice, all of these three parameters should be '()' at the top level.
newtype TestDefM (outers :: [Type]) inner result = TestDefM
  { TestDefM outers inner result
-> RWST TestRunSettings (TestForest outers inner) () IO result
unTestDefM :: RWST TestRunSettings (TestForest outers inner) () IO result
  }
  deriving (a -> TestDefM outers inner b -> TestDefM outers inner a
(a -> b) -> TestDefM outers inner a -> TestDefM outers inner b
(forall a b.
 (a -> b) -> TestDefM outers inner a -> TestDefM outers inner b)
-> (forall a b.
    a -> TestDefM outers inner b -> TestDefM outers inner a)
-> Functor (TestDefM outers inner)
forall (outers :: [*]) inner a b.
a -> TestDefM outers inner b -> TestDefM outers inner a
forall (outers :: [*]) inner a b.
(a -> b) -> TestDefM outers inner a -> TestDefM outers inner b
forall a b. a -> TestDefM outers inner b -> TestDefM outers inner a
forall a b.
(a -> b) -> TestDefM outers inner a -> TestDefM outers inner b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> TestDefM outers inner b -> TestDefM outers inner a
$c<$ :: forall (outers :: [*]) inner a b.
a -> TestDefM outers inner b -> TestDefM outers inner a
fmap :: (a -> b) -> TestDefM outers inner a -> TestDefM outers inner b
$cfmap :: forall (outers :: [*]) inner a b.
(a -> b) -> TestDefM outers inner a -> TestDefM outers inner b
Functor, Functor (TestDefM outers inner)
a -> TestDefM outers inner a
Functor (TestDefM outers inner)
-> (forall a. a -> TestDefM outers inner a)
-> (forall a b.
    TestDefM outers inner (a -> b)
    -> TestDefM outers inner a -> TestDefM outers inner b)
-> (forall a b c.
    (a -> b -> c)
    -> TestDefM outers inner a
    -> TestDefM outers inner b
    -> TestDefM outers inner c)
-> (forall a b.
    TestDefM outers inner a
    -> TestDefM outers inner b -> TestDefM outers inner b)
-> (forall a b.
    TestDefM outers inner a
    -> TestDefM outers inner b -> TestDefM outers inner a)
-> Applicative (TestDefM outers inner)
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner a
TestDefM outers inner (a -> b)
-> TestDefM outers inner a -> TestDefM outers inner b
(a -> b -> c)
-> TestDefM outers inner a
-> TestDefM outers inner b
-> TestDefM outers inner c
forall (outers :: [*]) inner. Functor (TestDefM outers inner)
forall (outers :: [*]) inner a. a -> TestDefM outers inner a
forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner a
forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
forall (outers :: [*]) inner a b.
TestDefM outers inner (a -> b)
-> TestDefM outers inner a -> TestDefM outers inner b
forall (outers :: [*]) inner a b c.
(a -> b -> c)
-> TestDefM outers inner a
-> TestDefM outers inner b
-> TestDefM outers inner c
forall a. a -> TestDefM outers inner a
forall a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner a
forall a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
forall a b.
TestDefM outers inner (a -> b)
-> TestDefM outers inner a -> TestDefM outers inner b
forall a b c.
(a -> b -> c)
-> TestDefM outers inner a
-> TestDefM outers inner b
-> TestDefM outers inner c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner a
$c<* :: forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner a
*> :: TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
$c*> :: forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
liftA2 :: (a -> b -> c)
-> TestDefM outers inner a
-> TestDefM outers inner b
-> TestDefM outers inner c
$cliftA2 :: forall (outers :: [*]) inner a b c.
(a -> b -> c)
-> TestDefM outers inner a
-> TestDefM outers inner b
-> TestDefM outers inner c
<*> :: TestDefM outers inner (a -> b)
-> TestDefM outers inner a -> TestDefM outers inner b
$c<*> :: forall (outers :: [*]) inner a b.
TestDefM outers inner (a -> b)
-> TestDefM outers inner a -> TestDefM outers inner b
pure :: a -> TestDefM outers inner a
$cpure :: forall (outers :: [*]) inner a. a -> TestDefM outers inner a
$cp1Applicative :: forall (outers :: [*]) inner. Functor (TestDefM outers inner)
Applicative, Applicative (TestDefM outers inner)
a -> TestDefM outers inner a
Applicative (TestDefM outers inner)
-> (forall a b.
    TestDefM outers inner a
    -> (a -> TestDefM outers inner b) -> TestDefM outers inner b)
-> (forall a b.
    TestDefM outers inner a
    -> TestDefM outers inner b -> TestDefM outers inner b)
-> (forall a. a -> TestDefM outers inner a)
-> Monad (TestDefM outers inner)
TestDefM outers inner a
-> (a -> TestDefM outers inner b) -> TestDefM outers inner b
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
forall (outers :: [*]) inner. Applicative (TestDefM outers inner)
forall (outers :: [*]) inner a. a -> TestDefM outers inner a
forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> (a -> TestDefM outers inner b) -> TestDefM outers inner b
forall a. a -> TestDefM outers inner a
forall a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
forall a b.
TestDefM outers inner a
-> (a -> TestDefM outers inner b) -> TestDefM outers inner b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> TestDefM outers inner a
$creturn :: forall (outers :: [*]) inner a. a -> TestDefM outers inner a
>> :: TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
$c>> :: forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> TestDefM outers inner b -> TestDefM outers inner b
>>= :: TestDefM outers inner a
-> (a -> TestDefM outers inner b) -> TestDefM outers inner b
$c>>= :: forall (outers :: [*]) inner a b.
TestDefM outers inner a
-> (a -> TestDefM outers inner b) -> TestDefM outers inner b
$cp1Monad :: forall (outers :: [*]) inner. Applicative (TestDefM outers inner)
Monad, Monad (TestDefM outers inner)
Monad (TestDefM outers inner)
-> (forall a. IO a -> TestDefM outers inner a)
-> MonadIO (TestDefM outers inner)
IO a -> TestDefM outers inner a
forall (outers :: [*]) inner. Monad (TestDefM outers inner)
forall (outers :: [*]) inner a. IO a -> TestDefM outers inner a
forall a. IO a -> TestDefM outers inner a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> TestDefM outers inner a
$cliftIO :: forall (outers :: [*]) inner a. IO a -> TestDefM outers inner a
$cp1MonadIO :: forall (outers :: [*]) inner. Monad (TestDefM outers inner)
MonadIO, MonadReader TestRunSettings, MonadWriter (TestForest outers inner), MonadState ())

execTestDefM :: Settings -> TestDefM outers inner result -> IO (TestForest outers inner)
execTestDefM :: Settings
-> TestDefM outers inner result -> IO (TestForest outers inner)
execTestDefM Settings
sets = ((result, TestForest outers inner) -> TestForest outers inner)
-> IO (result, TestForest outers inner)
-> IO (TestForest outers inner)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (result, TestForest outers inner) -> TestForest outers inner
forall a b. (a, b) -> b
snd (IO (result, TestForest outers inner)
 -> IO (TestForest outers inner))
-> (TestDefM outers inner result
    -> IO (result, TestForest outers inner))
-> TestDefM outers inner result
-> IO (TestForest outers inner)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Settings
-> TestDefM outers inner result
-> IO (result, TestForest outers inner)
forall (outers :: [*]) inner result.
Settings
-> TestDefM outers inner result
-> IO (result, TestForest outers inner)
runTestDefM Settings
sets

runTestDefM :: Settings -> TestDefM outers inner result -> IO (result, TestForest outers inner)
runTestDefM :: Settings
-> TestDefM outers inner result
-> IO (result, TestForest outers inner)
runTestDefM Settings
sets TestDefM outers inner result
defFunc = do
  let func :: RWST TestRunSettings (TestForest outers inner) () IO result
func = TestDefM outers inner result
-> RWST TestRunSettings (TestForest outers inner) () IO result
forall (outers :: [*]) inner result.
TestDefM outers inner result
-> RWST TestRunSettings (TestForest outers inner) () IO result
unTestDefM TestDefM outers inner result
defFunc
  (result
a, ()
_, TestForest outers inner
testForest) <- RWST TestRunSettings (TestForest outers inner) () IO result
-> TestRunSettings
-> ()
-> IO (result, (), TestForest outers inner)
forall r w s (m :: * -> *) a.
RWST r w s m a -> r -> s -> m (a, s, w)
runRWST RWST TestRunSettings (TestForest outers inner) () IO result
func (Settings -> TestRunSettings
toTestRunSettings Settings
sets) ()
  let testForest' :: TestForest outers inner
testForest' = Maybe Text -> TestForest outers inner -> TestForest outers inner
forall (outers :: [*]) inner result.
Maybe Text
-> SpecDefForest outers inner result
-> SpecDefForest outers inner result
filterTestForest (Settings -> Maybe Text
settingFilter Settings
sets) TestForest outers inner
testForest
  let testForest'' :: TestForest outers inner
testForest'' =
        if Settings -> Bool
settingRandomiseExecutionOrder Settings
sets
          then Rand StdGen (TestForest outers inner)
-> StdGen -> TestForest outers inner
forall g a. Rand g a -> g -> a
evalRand (TestForest outers inner -> Rand StdGen (TestForest outers inner)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
randomiseTestForest TestForest outers inner
testForest') (Int -> StdGen
mkStdGen (Settings -> Int
settingSeed Settings
sets))
          else TestForest outers inner
testForest'
  (result, TestForest outers inner)
-> IO (result, TestForest outers inner)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (result
a, TestForest outers inner
testForest'')

toTestRunSettings :: Settings -> TestRunSettings
toTestRunSettings :: Settings -> TestRunSettings
toTestRunSettings Settings {Bool
Int
Maybe Bool
Maybe Text
Iterations
Threads
settingDebug :: Settings -> Bool
settingIterations :: Settings -> Iterations
settingFailFast :: Settings -> Bool
settingColour :: Settings -> Maybe Bool
settingGoldenReset :: Settings -> Bool
settingGoldenStart :: Settings -> Bool
settingMaxShrinks :: Settings -> Int
settingMaxDiscard :: Settings -> Int
settingMaxSize :: Settings -> Int
settingMaxSuccess :: Settings -> Int
settingThreads :: Settings -> Threads
settingDebug :: Bool
settingIterations :: Iterations
settingFailFast :: Bool
settingFilter :: Maybe Text
settingColour :: Maybe Bool
settingGoldenReset :: Bool
settingGoldenStart :: Bool
settingMaxShrinks :: Int
settingMaxDiscard :: Int
settingMaxSize :: Int
settingMaxSuccess :: Int
settingThreads :: Threads
settingRandomiseExecutionOrder :: Bool
settingSeed :: Int
settingSeed :: Settings -> Int
settingRandomiseExecutionOrder :: Settings -> Bool
settingFilter :: Settings -> Maybe Text
..} =
  TestRunSettings :: Int -> Int -> Int -> Int -> Int -> Bool -> Bool -> TestRunSettings
TestRunSettings
    { testRunSettingSeed :: Int
testRunSettingSeed = Int
settingSeed,
      testRunSettingMaxSuccess :: Int
testRunSettingMaxSuccess = Int
settingMaxSuccess,
      testRunSettingMaxSize :: Int
testRunSettingMaxSize = Int
settingMaxSize,
      testRunSettingMaxDiscardRatio :: Int
testRunSettingMaxDiscardRatio = Int
settingMaxDiscard,
      testRunSettingMaxShrinks :: Int
testRunSettingMaxShrinks = Int
settingMaxShrinks,
      testRunSettingGoldenStart :: Bool
testRunSettingGoldenStart = Bool
settingGoldenStart,
      testRunSettingGoldenReset :: Bool
testRunSettingGoldenReset = Bool
settingGoldenReset
    }

filterTestForest :: Maybe Text -> SpecDefForest outers inner result -> SpecDefForest outers inner result
filterTestForest :: Maybe Text
-> SpecDefForest outers inner result
-> SpecDefForest outers inner result
filterTestForest Maybe Text
mf = SpecDefForest outers inner result
-> Maybe (SpecDefForest outers inner result)
-> SpecDefForest outers inner result
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe (SpecDefForest outers inner result)
 -> SpecDefForest outers inner result)
-> (SpecDefForest outers inner result
    -> Maybe (SpecDefForest outers inner result))
-> SpecDefForest outers inner result
-> SpecDefForest outers inner result
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList Text
-> SpecDefForest outers inner result
-> Maybe (SpecDefForest outers inner result)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
forall a. DList a
DList.empty
  where
    goForest :: DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
    goForest :: DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
ts SpecDefForest a b c
sdf = do
      let sdf' :: SpecDefForest a b c
sdf' = (SpecDefTree a b c -> Maybe (SpecDefTree a b c))
-> SpecDefForest a b c -> SpecDefForest a b c
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (DList Text -> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
goTree DList Text
ts) SpecDefForest a b c
sdf
      Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ SpecDefForest a b c -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null SpecDefForest a b c
sdf'
      SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure SpecDefForest a b c
sdf'

    filterGuard :: DList Text -> Bool
    filterGuard :: DList Text -> Bool
filterGuard DList Text
dl = case Maybe Text
mf of
      Just Text
f -> Text
f Text -> Text -> Bool
`T.isInfixOf` Text -> [Text] -> Text
T.intercalate Text
"." (DList Text -> [Text]
forall a. DList a -> [a]
DList.toList DList Text
dl)
      Maybe Text
Nothing -> Bool
True

    goTree :: DList Text -> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
    goTree :: DList Text -> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
goTree DList Text
dl = \case
      DefSpecifyNode Text
t TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
td c
e -> do
        let tl :: DList Text
tl = DList Text -> Text -> DList Text
forall a. DList a -> a -> DList a
DList.snoc DList Text
dl Text
t
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ DList Text -> Bool
filterGuard DList Text
tl
        SpecDefTree a b c -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SpecDefTree a b c -> Maybe (SpecDefTree a b c))
-> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
forall a b. (a -> b) -> a -> b
$ Text
-> TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
-> c
-> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text
-> TDef
     (((HList outers -> inner -> IO ()) -> IO ()) -> IO TestRunResult)
-> extra
-> SpecDefTree outers inner extra
DefSpecifyNode Text
t TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
td c
e
      DefPendingNode Text
t Maybe Text
mr -> do
        let tl :: DList Text
tl = DList Text -> Text -> DList Text
forall a. DList a -> a -> DList a
DList.snoc DList Text
dl Text
t
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Maybe ()) -> Bool -> Maybe ()
forall a b. (a -> b) -> a -> b
$ DList Text -> Bool
filterGuard DList Text
tl
        SpecDefTree a b c -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SpecDefTree a b c -> Maybe (SpecDefTree a b c))
-> SpecDefTree a b c -> Maybe (SpecDefTree a b c)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text -> Maybe Text -> SpecDefTree outers inner extra
DefPendingNode Text
t Maybe Text
mr
      DefDescribeNode Text
t SpecDefForest a b c
sdf -> Text -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefDescribeNode Text
t (SpecDefForest a b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest a b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest (DList Text -> Text -> DList Text
forall a. DList a -> a -> DList a
DList.snoc DList Text
dl Text
t) SpecDefForest a b c
sdf
      DefWrapNode IO () -> IO ()
func SpecDefForest a b c
sdf -> (IO () -> IO ()) -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
(IO () -> IO ())
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefWrapNode IO () -> IO ()
func (SpecDefForest a b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest a b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest a b c
sdf
      DefBeforeAllNode IO outer
func SpecDefForest (outer : a) b c
sdf -> IO outer -> SpecDefForest (outer : a) b c -> SpecDefTree a b c
forall outer (otherOuters :: [*]) inner extra.
IO outer
-> SpecDefForest (outer : otherOuters) inner extra
-> SpecDefTree otherOuters inner extra
DefBeforeAllNode IO outer
func (SpecDefForest (outer : a) b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest (outer : a) b c)
-> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (outer : a) b c
-> Maybe (SpecDefForest (outer : a) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (outer : a) b c
sdf
      DefAroundAllNode (outer -> IO ()) -> IO ()
func SpecDefForest (outer : a) b c
sdf -> ((outer -> IO ()) -> IO ())
-> SpecDefForest (outer : a) b c -> SpecDefTree a b c
forall outer (otherOuters :: [*]) inner extra.
((outer -> IO ()) -> IO ())
-> SpecDefForest (outer : otherOuters) inner extra
-> SpecDefTree otherOuters inner extra
DefAroundAllNode (outer -> IO ()) -> IO ()
func (SpecDefForest (outer : a) b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest (outer : a) b c)
-> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (outer : a) b c
-> Maybe (SpecDefForest (outer : a) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (outer : a) b c
sdf
      DefAroundAllWithNode (newOuter -> IO ()) -> oldOuter -> IO ()
func SpecDefForest (newOuter : oldOuter : otherOuters) b c
sdf -> ((newOuter -> IO ()) -> oldOuter -> IO ())
-> SpecDefForest (newOuter : oldOuter : otherOuters) b c
-> SpecDefTree (oldOuter : otherOuters) b c
forall newOuter oldOuter (otherOuters :: [*]) inner extra.
((newOuter -> IO ()) -> oldOuter -> IO ())
-> SpecDefForest (newOuter : oldOuter : otherOuters) inner extra
-> SpecDefTree (oldOuter : otherOuters) inner extra
DefAroundAllWithNode (newOuter -> IO ()) -> oldOuter -> IO ()
func (SpecDefForest (newOuter : oldOuter : otherOuters) b c
 -> SpecDefTree (oldOuter : otherOuters) b c)
-> Maybe (SpecDefForest (newOuter : oldOuter : otherOuters) b c)
-> Maybe (SpecDefTree (oldOuter : otherOuters) b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (newOuter : oldOuter : otherOuters) b c
-> Maybe (SpecDefForest (newOuter : oldOuter : otherOuters) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (newOuter : oldOuter : otherOuters) b c
sdf
      DefAfterAllNode HList a -> IO ()
func SpecDefForest a b c
sdf -> (HList a -> IO ()) -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
(HList outers -> IO ())
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefAfterAllNode HList a -> IO ()
func (SpecDefForest a b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest a b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest a b c
sdf
      DefParallelismNode Parallelism
func SpecDefForest a b c
sdf -> Parallelism -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Parallelism
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefParallelismNode Parallelism
func (SpecDefForest a b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest a b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest a b c
sdf
      DefRandomisationNode ExecutionOrderRandomisation
func SpecDefForest a b c
sdf -> ExecutionOrderRandomisation
-> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
ExecutionOrderRandomisation
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefRandomisationNode ExecutionOrderRandomisation
func (SpecDefForest a b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest a b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest a b c
sdf

randomiseTestForest :: MonadRandom m => SpecDefForest outers inner result -> m (SpecDefForest outers inner result)
randomiseTestForest :: SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
randomiseTestForest = SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest
  where
    goForest :: MonadRandom m => SpecDefForest a b c -> m (SpecDefForest a b c)
    goForest :: SpecDefForest a b c -> m (SpecDefForest a b c)
goForest = (SpecDefTree a b c -> m (SpecDefTree a b c))
-> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse SpecDefTree a b c -> m (SpecDefTree a b c)
forall (m :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefTree a b c -> m (SpecDefTree a b c)
goTree (SpecDefForest a b c -> m (SpecDefForest a b c))
-> (SpecDefForest a b c -> m (SpecDefForest a b c))
-> SpecDefForest a b c
-> m (SpecDefForest a b c)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) a. MonadRandom m => [a] -> m [a]
shuffleM
    goTree :: MonadRandom m => SpecDefTree a b c -> m (SpecDefTree a b c)
    goTree :: SpecDefTree a b c -> m (SpecDefTree a b c)
goTree = \case
      DefSpecifyNode Text
t TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
td c
e -> SpecDefTree a b c -> m (SpecDefTree a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SpecDefTree a b c -> m (SpecDefTree a b c))
-> SpecDefTree a b c -> m (SpecDefTree a b c)
forall a b. (a -> b) -> a -> b
$ Text
-> TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
-> c
-> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text
-> TDef
     (((HList outers -> inner -> IO ()) -> IO ()) -> IO TestRunResult)
-> extra
-> SpecDefTree outers inner extra
DefSpecifyNode Text
t TDef (((HList a -> b -> IO ()) -> IO ()) -> IO TestRunResult)
td c
e
      DefPendingNode Text
t Maybe Text
mr -> SpecDefTree a b c -> m (SpecDefTree a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SpecDefTree a b c -> m (SpecDefTree a b c))
-> SpecDefTree a b c -> m (SpecDefTree a b c)
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text -> Maybe Text -> SpecDefTree outers inner extra
DefPendingNode Text
t Maybe Text
mr
      DefDescribeNode Text
t SpecDefForest a b c
sdf -> Text -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Text
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefDescribeNode Text
t (SpecDefForest a b c -> SpecDefTree a b c)
-> m (SpecDefForest a b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest a b c
sdf
      DefWrapNode IO () -> IO ()
func SpecDefForest a b c
sdf -> (IO () -> IO ()) -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
(IO () -> IO ())
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefWrapNode IO () -> IO ()
func (SpecDefForest a b c -> SpecDefTree a b c)
-> m (SpecDefForest a b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest a b c
sdf
      DefBeforeAllNode IO outer
func SpecDefForest (outer : a) b c
sdf -> IO outer -> SpecDefForest (outer : a) b c -> SpecDefTree a b c
forall outer (otherOuters :: [*]) inner extra.
IO outer
-> SpecDefForest (outer : otherOuters) inner extra
-> SpecDefTree otherOuters inner extra
DefBeforeAllNode IO outer
func (SpecDefForest (outer : a) b c -> SpecDefTree a b c)
-> m (SpecDefForest (outer : a) b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (outer : a) b c -> m (SpecDefForest (outer : a) b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest (outer : a) b c
sdf
      DefAroundAllNode (outer -> IO ()) -> IO ()
func SpecDefForest (outer : a) b c
sdf -> ((outer -> IO ()) -> IO ())
-> SpecDefForest (outer : a) b c -> SpecDefTree a b c
forall outer (otherOuters :: [*]) inner extra.
((outer -> IO ()) -> IO ())
-> SpecDefForest (outer : otherOuters) inner extra
-> SpecDefTree otherOuters inner extra
DefAroundAllNode (outer -> IO ()) -> IO ()
func (SpecDefForest (outer : a) b c -> SpecDefTree a b c)
-> m (SpecDefForest (outer : a) b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (outer : a) b c -> m (SpecDefForest (outer : a) b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest (outer : a) b c
sdf
      DefAroundAllWithNode (newOuter -> IO ()) -> oldOuter -> IO ()
func SpecDefForest (newOuter : oldOuter : otherOuters) b c
sdf -> ((newOuter -> IO ()) -> oldOuter -> IO ())
-> SpecDefForest (newOuter : oldOuter : otherOuters) b c
-> SpecDefTree (oldOuter : otherOuters) b c
forall newOuter oldOuter (otherOuters :: [*]) inner extra.
((newOuter -> IO ()) -> oldOuter -> IO ())
-> SpecDefForest (newOuter : oldOuter : otherOuters) inner extra
-> SpecDefTree (oldOuter : otherOuters) inner extra
DefAroundAllWithNode (newOuter -> IO ()) -> oldOuter -> IO ()
func (SpecDefForest (newOuter : oldOuter : otherOuters) b c
 -> SpecDefTree (oldOuter : otherOuters) b c)
-> m (SpecDefForest (newOuter : oldOuter : otherOuters) b c)
-> m (SpecDefTree (oldOuter : otherOuters) b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (newOuter : oldOuter : otherOuters) b c
-> m (SpecDefForest (newOuter : oldOuter : otherOuters) b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest (newOuter : oldOuter : otherOuters) b c
sdf
      DefAfterAllNode HList a -> IO ()
func SpecDefForest a b c
sdf -> (HList a -> IO ()) -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
(HList outers -> IO ())
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefAfterAllNode HList a -> IO ()
func (SpecDefForest a b c -> SpecDefTree a b c)
-> m (SpecDefForest a b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest a b c
sdf
      DefParallelismNode Parallelism
func SpecDefForest a b c
sdf -> Parallelism -> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
Parallelism
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefParallelismNode Parallelism
func (SpecDefForest a b c -> SpecDefTree a b c)
-> m (SpecDefForest a b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest a b c
sdf
      DefRandomisationNode ExecutionOrderRandomisation
eor SpecDefForest a b c
sdf ->
        ExecutionOrderRandomisation
-> SpecDefForest a b c -> SpecDefTree a b c
forall (outers :: [*]) inner extra.
ExecutionOrderRandomisation
-> SpecDefForest outers inner extra
-> SpecDefTree outers inner extra
DefRandomisationNode ExecutionOrderRandomisation
eor (SpecDefForest a b c -> SpecDefTree a b c)
-> m (SpecDefForest a b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> case ExecutionOrderRandomisation
eor of
          ExecutionOrderRandomisation
RandomiseExecutionOrder -> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (outers :: [*]) inner result.
MonadRandom m =>
SpecDefForest outers inner result
-> m (SpecDefForest outers inner result)
goForest SpecDefForest a b c
sdf
          ExecutionOrderRandomisation
DoNotRandomiseExecutionOrder -> SpecDefForest a b c -> m (SpecDefForest a b c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure SpecDefForest a b c
sdf