{-# 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.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 a = SpecM a ()

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

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

-- | The test definition monad
--
-- This type has three parameters:
--
-- * @a@: The type of the result of `aroundAll`
-- * @b@: The type of the result of `around`
-- * @c@: The result
--
-- In practice, all of these three parameters should be '()' at the top level.
newtype TestDefM a b c = TestDefM
  { TestDefM a b c -> RWST TestRunSettings (TestForest a b) () IO c
unTestDefM :: RWST TestRunSettings (TestForest a b) () IO c
  }
  deriving (a -> TestDefM a b b -> TestDefM a b a
(a -> b) -> TestDefM a b a -> TestDefM a b b
(forall a b. (a -> b) -> TestDefM a b a -> TestDefM a b b)
-> (forall a b. a -> TestDefM a b b -> TestDefM a b a)
-> Functor (TestDefM a b)
forall (a :: [*]) b a b. a -> TestDefM a b b -> TestDefM a b a
forall (a :: [*]) b a b.
(a -> b) -> TestDefM a b a -> TestDefM a b b
forall a b. a -> TestDefM a b b -> TestDefM a b a
forall a b. (a -> b) -> TestDefM a b a -> TestDefM a b b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> TestDefM a b b -> TestDefM a b a
$c<$ :: forall (a :: [*]) b a b. a -> TestDefM a b b -> TestDefM a b a
fmap :: (a -> b) -> TestDefM a b a -> TestDefM a b b
$cfmap :: forall (a :: [*]) b a b.
(a -> b) -> TestDefM a b a -> TestDefM a b b
Functor, Functor (TestDefM a b)
a -> TestDefM a b a
Functor (TestDefM a b)
-> (forall a. a -> TestDefM a b a)
-> (forall a b.
    TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b)
-> (forall a b c.
    (a -> b -> c)
    -> TestDefM a b a -> TestDefM a b b -> TestDefM a b c)
-> (forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b b)
-> (forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b a)
-> Applicative (TestDefM a b)
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
TestDefM a b a -> TestDefM a b b -> TestDefM a b a
TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b
(a -> b -> c) -> TestDefM a b a -> TestDefM a b b -> TestDefM a b c
forall (a :: [*]) b. Functor (TestDefM a b)
forall (a :: [*]) b a. a -> TestDefM a b a
forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b a
forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
forall (a :: [*]) b a b.
TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b
forall (a :: [*]) b a b c.
(a -> b -> c) -> TestDefM a b a -> TestDefM a b b -> TestDefM a b c
forall a. a -> TestDefM a b a
forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b a
forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b b
forall a b.
TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b
forall a b c.
(a -> b -> c) -> TestDefM a b a -> TestDefM a b b -> TestDefM a b 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 a b a -> TestDefM a b b -> TestDefM a b a
$c<* :: forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b a
*> :: TestDefM a b a -> TestDefM a b b -> TestDefM a b b
$c*> :: forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
liftA2 :: (a -> b -> c) -> TestDefM a b a -> TestDefM a b b -> TestDefM a b c
$cliftA2 :: forall (a :: [*]) b a b c.
(a -> b -> c) -> TestDefM a b a -> TestDefM a b b -> TestDefM a b c
<*> :: TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b
$c<*> :: forall (a :: [*]) b a b.
TestDefM a b (a -> b) -> TestDefM a b a -> TestDefM a b b
pure :: a -> TestDefM a b a
$cpure :: forall (a :: [*]) b a. a -> TestDefM a b a
$cp1Applicative :: forall (a :: [*]) b. Functor (TestDefM a b)
Applicative, Applicative (TestDefM a b)
a -> TestDefM a b a
Applicative (TestDefM a b)
-> (forall a b.
    TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b b)
-> (forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b b)
-> (forall a. a -> TestDefM a b a)
-> Monad (TestDefM a b)
TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b b
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
forall (a :: [*]) b. Applicative (TestDefM a b)
forall (a :: [*]) b a. a -> TestDefM a b a
forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
forall (a :: [*]) b a b.
TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b b
forall a. a -> TestDefM a b a
forall a b. TestDefM a b a -> TestDefM a b b -> TestDefM a b b
forall a b.
TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b 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 a b a
$creturn :: forall (a :: [*]) b a. a -> TestDefM a b a
>> :: TestDefM a b a -> TestDefM a b b -> TestDefM a b b
$c>> :: forall (a :: [*]) b a b.
TestDefM a b a -> TestDefM a b b -> TestDefM a b b
>>= :: TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b b
$c>>= :: forall (a :: [*]) b a b.
TestDefM a b a -> (a -> TestDefM a b b) -> TestDefM a b b
$cp1Monad :: forall (a :: [*]) b. Applicative (TestDefM a b)
Monad, Monad (TestDefM a b)
Monad (TestDefM a b)
-> (forall a. IO a -> TestDefM a b a) -> MonadIO (TestDefM a b)
IO a -> TestDefM a b a
forall (a :: [*]) b. Monad (TestDefM a b)
forall (a :: [*]) b a. IO a -> TestDefM a b a
forall a. IO a -> TestDefM a b a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> TestDefM a b a
$cliftIO :: forall (a :: [*]) b a. IO a -> TestDefM a b a
$cp1MonadIO :: forall (a :: [*]) b. Monad (TestDefM a b)
MonadIO, MonadReader TestRunSettings, MonadWriter (TestForest a b), MonadState ())

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

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

toTestRunSettings :: Settings -> TestRunSettings
toTestRunSettings :: Settings -> TestRunSettings
toTestRunSettings Settings {Bool
Int
Maybe Bool
Maybe Text
Iterations
Threads
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
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 a b c -> SpecDefForest a b c
filterTestForest :: Maybe Text -> SpecDefForest a b c -> SpecDefForest a b c
filterTestForest Maybe Text
mf = SpecDefForest a b c
-> Maybe (SpecDefForest a b c) -> SpecDefForest a b c
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe (SpecDefForest a b c) -> SpecDefForest a b c)
-> (SpecDefForest a b c -> Maybe (SpecDefForest a b c))
-> SpecDefForest a b c
-> SpecDefForest a b c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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
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 (a :: [*]) c e.
Text
-> TDef (((HList a -> c -> IO ()) -> IO ()) -> IO TestRunResult)
-> e
-> SpecDefTree a c e
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 (a :: [*]) c e. Text -> Maybe Text -> SpecDefTree a c e
DefPendingNode Text
t Maybe Text
mr
      DefDescribeNode Text
t SpecDefForest a b c
sdf -> Text -> SpecDefForest a b c -> SpecDefTree a b c
forall (a :: [*]) c e.
Text -> SpecDefForest a c e -> SpecDefTree a c e
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 (a :: [*]) c e.
(IO () -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
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 a
func SpecDefForest (a : a) b c
sdf -> IO a -> SpecDefForest (a : a) b c -> SpecDefTree a b c
forall a (l :: [*]) c e.
IO a -> SpecDefForest (a : l) c e -> SpecDefTree l c e
DefBeforeAllNode IO a
func (SpecDefForest (a : a) b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest (a : a) b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (a : a) b c -> Maybe (SpecDefForest (a : a) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (a : a) b c
sdf
      DefAroundAllNode (a -> IO ()) -> IO ()
func SpecDefForest (a : a) b c
sdf -> ((a -> IO ()) -> IO ())
-> SpecDefForest (a : a) b c -> SpecDefTree a b c
forall a (l :: [*]) c e.
((a -> IO ()) -> IO ())
-> SpecDefForest (a : l) c e -> SpecDefTree l c e
DefAroundAllNode (a -> IO ()) -> IO ()
func (SpecDefForest (a : a) b c -> SpecDefTree a b c)
-> Maybe (SpecDefForest (a : a) b c) -> Maybe (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (a : a) b c -> Maybe (SpecDefForest (a : a) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (a : a) b c
sdf
      DefAroundAllWithNode (b -> IO ()) -> a -> IO ()
func SpecDefForest (b : a : l) b c
sdf -> ((b -> IO ()) -> a -> IO ())
-> SpecDefForest (b : a : l) b c -> SpecDefTree (a : l) b c
forall b a (l :: [*]) c e.
((b -> IO ()) -> a -> IO ())
-> SpecDefForest (b : a : l) c e -> SpecDefTree (a : l) c e
DefAroundAllWithNode (b -> IO ()) -> a -> IO ()
func (SpecDefForest (b : a : l) b c -> SpecDefTree (a : l) b c)
-> Maybe (SpecDefForest (b : a : l) b c)
-> Maybe (SpecDefTree (a : l) b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList Text
-> SpecDefForest (b : a : l) b c
-> Maybe (SpecDefForest (b : a : l) b c)
forall (a :: [*]) b c.
DList Text -> SpecDefForest a b c -> Maybe (SpecDefForest a b c)
goForest DList Text
dl SpecDefForest (b : a : l) 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 (a :: [*]) c e.
(HList a -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
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 (a :: [*]) c e.
Parallelism -> SpecDefForest a c e -> SpecDefTree a c e
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 (a :: [*]) c e.
ExecutionOrderRandomisation
-> SpecDefForest a c e -> SpecDefTree a c e
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 a b c -> m (SpecDefForest a b c)
randomiseTestForest :: SpecDefForest a b c -> m (SpecDefForest a b c)
randomiseTestForest = SpecDefForest a b c -> m (SpecDefForest a b c)
forall (m :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
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 (a :: [*]) c e.
Text
-> TDef (((HList a -> c -> IO ()) -> IO ()) -> IO TestRunResult)
-> e
-> SpecDefTree a c e
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 (a :: [*]) c e. Text -> Maybe Text -> SpecDefTree a c e
DefPendingNode Text
t Maybe Text
mr
      DefDescribeNode Text
t SpecDefForest a b c
sdf -> Text -> SpecDefForest a b c -> SpecDefTree a b c
forall (a :: [*]) c e.
Text -> SpecDefForest a c e -> SpecDefTree a c e
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 :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
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 (a :: [*]) c e.
(IO () -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
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 :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest a b c
sdf
      DefBeforeAllNode IO a
func SpecDefForest (a : a) b c
sdf -> IO a -> SpecDefForest (a : a) b c -> SpecDefTree a b c
forall a (l :: [*]) c e.
IO a -> SpecDefForest (a : l) c e -> SpecDefTree l c e
DefBeforeAllNode IO a
func (SpecDefForest (a : a) b c -> SpecDefTree a b c)
-> m (SpecDefForest (a : a) b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (a : a) b c -> m (SpecDefForest (a : a) b c)
forall (m :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest (a : a) b c
sdf
      DefAroundAllNode (a -> IO ()) -> IO ()
func SpecDefForest (a : a) b c
sdf -> ((a -> IO ()) -> IO ())
-> SpecDefForest (a : a) b c -> SpecDefTree a b c
forall a (l :: [*]) c e.
((a -> IO ()) -> IO ())
-> SpecDefForest (a : l) c e -> SpecDefTree l c e
DefAroundAllNode (a -> IO ()) -> IO ()
func (SpecDefForest (a : a) b c -> SpecDefTree a b c)
-> m (SpecDefForest (a : a) b c) -> m (SpecDefTree a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (a : a) b c -> m (SpecDefForest (a : a) b c)
forall (m :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest (a : a) b c
sdf
      DefAroundAllWithNode (b -> IO ()) -> a -> IO ()
func SpecDefForest (b : a : l) b c
sdf -> ((b -> IO ()) -> a -> IO ())
-> SpecDefForest (b : a : l) b c -> SpecDefTree (a : l) b c
forall b a (l :: [*]) c e.
((b -> IO ()) -> a -> IO ())
-> SpecDefForest (b : a : l) c e -> SpecDefTree (a : l) c e
DefAroundAllWithNode (b -> IO ()) -> a -> IO ()
func (SpecDefForest (b : a : l) b c -> SpecDefTree (a : l) b c)
-> m (SpecDefForest (b : a : l) b c) -> m (SpecDefTree (a : l) b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SpecDefForest (b : a : l) b c -> m (SpecDefForest (b : a : l) b c)
forall (m :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest (b : a : l) 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 (a :: [*]) c e.
(HList a -> IO ()) -> SpecDefForest a c e -> SpecDefTree a c e
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 :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest a b c
sdf
      DefParallelismNode Parallelism
func SpecDefForest a b c
sdf -> Parallelism -> SpecDefForest a b c -> SpecDefTree a b c
forall (a :: [*]) c e.
Parallelism -> SpecDefForest a c e -> SpecDefTree a c e
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 :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
goForest SpecDefForest a b c
sdf
      DefRandomisationNode ExecutionOrderRandomisation
eor SpecDefForest a b c
sdf ->
        ExecutionOrderRandomisation
-> SpecDefForest a b c -> SpecDefTree a b c
forall (a :: [*]) c e.
ExecutionOrderRandomisation
-> SpecDefForest a c e -> SpecDefTree a c e
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 :: * -> *) (a :: [*]) b c.
MonadRandom m =>
SpecDefForest a b c -> m (SpecDefForest a b c)
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