{-# LANGUAGE CPP #-} -- | -- Module : EasyTest.Internal.Hedgehog -- Copyright : (c) Joel Burget, 2018-2019 -- License : MIT -- Maintainer : joelburget@gmail.com -- Stability : experimental -- -- This module defines 'recheckSeed', which just checks a 'Group' using a given -- seed. module EasyTest.Internal.Hedgehog (recheckSeed) where import Control.Monad.IO.Class import Control.Concurrent.STM.TVar (TVar, modifyTVar', newTVar, readTVar) import Control.Monad.STM (atomically) #if !(MIN_VERSION_base(4,11,0)) import Data.Semigroup #endif import Hedgehog hiding (Test) import Hedgehog.Internal.Config import Hedgehog.Internal.Property import Hedgehog.Internal.Queue import Hedgehog.Internal.Region import Hedgehog.Internal.Report import Hedgehog.Internal.Runner hiding (checkNamed) -- | 'Hedgehog.Internal.Runner.checkNamed' modified to take a 'Seed' checkNamed :: MonadIO m => Region -> Maybe UseColor -> Maybe PropertyName -> Seed -> Property -> m (Report Result) checkNamed region mcolor name seed prop = checkRegion region mcolor name 0 seed prop -- | 'Hedgehog.Internal.Runner.updateSummary' exposed. updateSummary :: Region -> TVar Summary -> Maybe UseColor -> (Summary -> Summary) -> IO () updateSummary sregion svar mcolor f = do summary <- atomically (modifyTVar' svar f >> readTVar svar) setRegion sregion =<< renderSummary mcolor summary -- | 'Hedgehog.Internal.Runner.checkGroupWith' modified to take a 'Seed' checkGroupWith :: WorkerCount -> Verbosity -> Maybe UseColor -> Seed -> [(PropertyName, Property)] -> IO Summary checkGroupWith n verbosity mcolor seed props = displayRegion $ \sregion -> do svar <- atomically . newTVar $ mempty { summaryWaiting = PropertyCount (length props) } let start (TasksRemaining tasks) _ix (name, prop) = liftIO $ do updateSummary sregion svar mcolor $ \x -> x { summaryWaiting = PropertyCount tasks , summaryRunning = summaryRunning x + 1 } atomically $ do region <- case verbosity of Quiet -> newEmptyRegion Normal -> newOpenRegion moveToBottom sregion pure (name, prop, region) finish (_name, _prop, _region) = updateSummary sregion svar mcolor $ \x -> x { summaryRunning = summaryRunning x - 1 } finalize (_name, _prop, region) = finishRegion region summary <- fmap (mconcat . fmap (fromResult . reportStatus)) $ runTasks n props start finish finalize $ \(name, prop, region) -> do result <- checkNamed region mcolor (Just name) seed prop updateSummary sregion svar mcolor (<> fromResult (reportStatus result)) pure result updateSummary sregion svar mcolor (const summary) pure summary -- | 'Hedgehog.checkSequential' modified to take a seed and exit on failure recheckSeed :: MonadIO m => Seed -> Group -> m Summary recheckSeed seed (Group group props) = liftIO $ do let config = RunnerConfig { runnerWorkers = Just 1 , runnerColor = Nothing , runnerVerbosity = Nothing } n <- resolveWorkers (runnerWorkers config) -- ensure few spare capabilities for concurrent-output, it's likely that -- our tests will saturate all the capabilities they're given. updateNumCapabilities (n + 2) #if mingw32_HOST_OS hSetEncoding stdout utf8 hSetEncoding stderr utf8 #endif putStrLn $ "━━━ " ++ unGroupName group ++ " ━━━" verbosity <- resolveVerbosity (runnerVerbosity config) checkGroupWith n verbosity (runnerColor config) seed props