packages feed

tasty 1.5.3 → 1.5.4

raw patch · 22 files changed

+332/−166 lines, 22 filesdep −semigroups

Dependencies removed: semigroups

Files

CHANGELOG.md view
@@ -1,6 +1,26 @@ Changes ======= +Version 1.5.4+--------------++_2025-03-31_++* Fix display of `HasCallStack` backtraces when a test throws an error+  ([#472](https://github.com/UnkindPartition/tasty/pull/472)).+* Introduce `dependentTestGroup` and `inOrderTestGroup`,+  deprecate `sequentialTestGroup`+  ([#448](https://github.com/UnkindPartition/tasty/pull/448)).+* Add `instance IsTest t => IsTest (ContT () IO t)`+  ([#466](https://github.com/UnkindPartition/tasty/pull/466)).+* Limit maximum line length in console reporter+  ([#451](https://github.com/UnkindPartition/tasty/pull/451)).+* Make `-j` to entail `+RTS -N` automatically+  ([#457](https://github.com/UnkindPartition/tasty/pull/457)).+* Do not depend on `unbounded-delays` on `ppc64le` and `loongarch64`+  ([#460](https://github.com/UnkindPartition/tasty/pull/460),+   [#465](https://github.com/UnkindPartition/tasty/pull/465)).+ Version 1.5.3 -------------- @@ -521,7 +541,7 @@ * Better handling of exceptions that arise during resource creation or   disposal * Expose the `AppMonoid` wrapper-* Add `askOption` and `inludingOptions`+* Add `askOption` and `includingOptions`  Version 0.5.2.1 ---------------
Control/Concurrent/Async.hs view
@@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -} -{-# LANGUAGE DeriveDataTypeable, MagicHash, UnboxedTuples #-}+{-# LANGUAGE CPP, MagicHash, UnboxedTuples #-}  module Control.Concurrent.Async (   async, withAsync, wait, asyncThreadId, cancel, concurrently@@ -44,14 +44,40 @@  import Control.Concurrent.STM import Control.Exception+  ( BlockedIndefinitelyOnMVar(..)+  , BlockedIndefinitelyOnSTM(..)+  , Exception+  , SomeException+  , asyncExceptionFromException+  , asyncExceptionToException+  , catch+  , fromException+  , onException+  , toException+  , try+  ) import Control.Concurrent import Control.Monad import Data.IORef-import Data.Typeable import GHC.Conc (ThreadId(..)) import GHC.Exts import GHC.IO hiding (onException) +#if MIN_VERSION_base(4,21,0)+import Control.Exception (ExceptionWithContext, tryWithContext, catchNoPropagate, rethrowIO)+#else+type ExceptionWithContext x = x++catchNoPropagate :: IO a -> (ExceptionWithContext SomeException -> IO a) -> IO a+catchNoPropagate = catchAll++tryWithContext :: IO a -> IO (Either (ExceptionWithContext SomeException) a)+tryWithContext = try++rethrowIO :: ExceptionWithContext SomeException -> IO a+rethrowIO = throwIO+#endif+ -- | An asynchronous action spawned by 'async' or 'withAsync'. -- Asynchronous actions are executed in a separate thread, and -- operations are provided for waiting for asynchronous actions to@@ -59,9 +85,9 @@ -- data Async a = Async   { asyncThreadId :: {-# UNPACK #-} !ThreadId-                  -- ^ Returns the 'ThreadId' of the thread running-                  -- the given 'Async'.-  , _asyncWait    :: STM (Either SomeException a)+                  -- ^ Returns the t'ThreadId' of the thread running+                  -- the given t'Async'.+  , _asyncWait    :: STM (Either (ExceptionWithContext SomeException) a)   }  -- | Spawn an asynchronous action in a separate thread.@@ -103,11 +129,11 @@ withAsyncUsing doFork = \action inner -> do   var <- newEmptyTMVarIO   mask $ \restore -> do-    t <- doFork $ try (restore action) >>= atomically . putTMVar var+    t <- doFork $ tryWithContext (restore action) >>= atomically . putTMVar var     let a = Async t (readTMVar var)-    r <- restore (inner a) `catchAll` \e -> do+    r <- restore (inner a) `catchNoPropagate` \e -> do       uninterruptibleCancel a-      throwIO e+      rethrowIO (e :: ExceptionWithContext SomeException)     uninterruptibleCancel a     return r @@ -131,7 +157,7 @@ -- > waitCatch = atomically . waitCatchSTM -- {-# INLINE waitCatch #-}-waitCatch :: Async a -> IO (Either SomeException a)+waitCatch :: Async a -> IO (Either (ExceptionWithContext SomeException) a) waitCatch = tryAgain . atomically . waitCatchSTM   where     -- See: https://github.com/simonmar/async/issues/14@@ -147,16 +173,16 @@ -- | A version of 'waitCatch' that can be used inside an STM transaction. -- {-# INLINE waitCatchSTM #-}-waitCatchSTM :: Async a -> STM (Either SomeException a)+waitCatchSTM :: Async a -> STM (Either (ExceptionWithContext SomeException) a) waitCatchSTM (Async _ w) = w  -- | Cancel an asynchronous action by throwing the @AsyncCancelled@--- exception to it, and waiting for the `Async` thread to quit.--- Has no effect if the 'Async' has already completed.+-- exception to it, and waiting for the t'Async' thread to quit.+-- Has no effect if the t'Async' has already completed. -- -- > cancel a = throwTo (asyncThreadId a) AsyncCancelled <* waitCatch a ----- Note that 'cancel' will not terminate until the thread the 'Async'+-- Note that 'cancel' will not terminate until the thread the t'Async' -- refers to has terminated. This means that 'cancel' will block for -- as long said thread blocks when receiving an asynchronous exception. --@@ -172,13 +198,11 @@  -- | The exception thrown by `cancel` to terminate a thread. data AsyncCancelled = AsyncCancelled-  deriving (Show, Eq, Typeable)+  deriving (Show, Eq)  instance Exception AsyncCancelled where-#if __GLASGOW_HASKELL__ >= 708   fromException = asyncExceptionFromException   toException = asyncExceptionToException-#endif  -- | Cancel an asynchronous action --
README.md view
@@ -236,7 +236,7 @@   --quickcheck-max-size NUMBER                            Size of the biggest test cases quickcheck generates   --quickcheck-max-ratio NUMBER-                           Maximum number of discared tests per successful test+                           Maximum number of discarded tests per successful test                            before giving up   --quickcheck-verbose     Show the generated test cases   --quickcheck-shrinks NUMBER@@ -703,14 +703,14 @@ If this parallelism is not desirable, you can declare *dependencies* between tests, so that one test will not start until certain other tests finish. -Dependencies are declared using the `after` or `sequentialTestGroup` combinator:+Dependencies are declared using the `after` or `dependentTestGroup` combinator:  * `after AllFinish "pattern" my_tests` will execute the test tree `my_tests` only after all     tests that match the pattern finish. * `after AllSucceed "pattern" my_tests` will execute the test tree `my_tests` only after all     tests that match the pattern finish **and** only if they all succeed. If at     least one dependency fails, then `my_tests` will be skipped.-* `sequentialTestGroup groupName dependencyType [tree1, tree2, ..]` will execute all tests+* `dependentTestGroup groupName dependencyType [tree1, tree2, ..]` will execute all tests    in `tree1` first, after which it will execute all tests in `tree2`, and so forth. Like    `after`, `dependencyType` can either be set to `AllFinish` or `AllSucceed`. @@ -723,7 +723,7 @@   -> TestTree       -- ^ the subtree that depends on other tests   -> TestTree       -- ^ the subtree annotated with dependency information -sequentialTestGroup+dependentTestGroup   :: TestName       -- ^ name of the group   -> DependencyType -- ^ whether to run the tests even if some of the dependencies fail   -> [TestTree]     -- ^ trees to execute sequentially@@ -792,7 +792,7 @@    test tree, searching for the next test to execute may also have an    overhead quadratic in the number of tests. -Use `sequentialTestGroup` to mitigate these problems.+Use `dependentTestGroup` to mitigate these problems.   ## FAQ@@ -828,6 +828,22 @@    bash directly to prevent this behaviour, or follow other suggestions from    [Known    Issues](https://github.com/git-for-windows/build-extra/blob/main/ReleaseNotes.md#known-issues).++## Migration from `test-framework`++`tasty` architecture is quite similar to `test-framework`, so a few mechanical changes are usually enough to migrate:++* Replace packages in `build-depends`:+  * `test-framework` -> `tasty`,+  * `test-framework-hunit` -> `tasty-hunit`,+  * `test-framework-quickcheck2` -> `tasty-quickcheck`.+* Replace module imports:+  * `Test.Framework` -> `Test.Tasty`,+  * `Test.Framework.Providers.HUnit` -> `Test.Tasty.HUnit`,+  * `Test.Framework.Providers.QuickCheck2` -> `Test.Tasty.QuickCheck`.+* Replace in type signatures:+  * `Test` -> `TestTree`.+* Replace `defaultMain tests` with `defaultMain (testGroup "All" tests)`.  ## Press 
Test/Tasty.hs view
@@ -33,7 +33,9 @@     TestName   , TestTree   , testGroup+  , dependentTestGroup   , sequentialTestGroup+  , inOrderTestGroup   -- * Running tests   , defaultMain   , defaultMainWithIngredients
Test/Tasty/CmdLine.hs view
@@ -8,7 +8,6 @@   ) where  import Control.Arrow-import Control.Monad import Data.Maybe import Data.Proxy import Data.Typeable (typeRep)@@ -16,7 +15,6 @@ import Options.Applicative.Common (evalParser) import qualified Options.Applicative.Types as Applicative (Option(..)) import Options.Applicative.Types (Parser(..), OptProperties(..))-import Prelude  -- Silence AMP and FTP import warnings import System.Exit import System.IO #if !MIN_VERSION_base(4,11,0)@@ -156,9 +154,7 @@   mapM_ (hPutStrLn stderr) warnings   cmdlineOpts <- execParser $     info (helper <*> parser)-    ( fullDesc <>-      header "Mmm... tasty test suite"-    )+    (header "Mmm... tasty test suite")   envOpts <- suiteEnvOptions ins tree   return $ envOpts <> cmdlineOpts 
Test/Tasty/Core.hs view
@@ -1,8 +1,11 @@ -- | Core types and definitions {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ImplicitParams #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-} module Test.Tasty.Core   ( FailureReason(..)   , Outcome(..)@@ -18,9 +21,12 @@   , ResourceError(..)   , DependencyType(..)   , ExecutionMode(..)+  , Parallel(..)   , TestTree(..)   , testGroup   , sequentialTestGroup+  , dependentTestGroup+  , inOrderTestGroup   , after   , after_   , TreeFold(..)@@ -28,11 +34,15 @@   , foldTestTree   , foldTestTree0   , treeOptions+  , testFailed   ) where  import Control.Exception+import Control.Monad.Trans.Cont (ContT(..))+import Data.Coerce (coerce) import qualified Data.Map as Map import Data.Bifunctor (Bifunctor(second, bimap))+import Data.IORef (newIORef, readIORef, atomicModifyIORef') import Data.List (mapAccumR) import Data.Monoid (Any (getAny, Any)) import Data.Sequence ((|>))@@ -48,6 +58,10 @@ import Text.Printf import Text.Read (readMaybe) +#if MIN_VERSION_base(4,21,0) && !MIN_VERSION_base(4,22,0)+import Control.Exception.Context+#endif+ -- | If a test failed, 'FailureReason' describes why. -- -- @since 0.8@@ -156,16 +170,28 @@     Success -> True     Failure {} -> False --- | Shortcut for creating a 'Result' that indicates exception+-- | Shortcut for creating a t'Result' that indicates exception exceptionResult :: SomeException -> Result exceptionResult e = Result   { resultOutcome = Failure $ TestThrewException e-  , resultDescription = "Exception: " ++ displayException e+  , resultDescription = "Exception: " ++ displayException' e   , resultShortDescription = "FAIL"   , resultTime = 0   , resultDetailsPrinter = noResultDetails   } +displayException' :: SomeException -> String+#if MIN_VERSION_base(4,22,0)+displayException' = displayExceptionWithInfo+#elif MIN_VERSION_base(4,21,0)+displayException' (SomeException e) =+  displayException e ++ case displayExceptionContext ?exceptionContext of+    "" -> ""+    dc -> "\n\n" ++ dc+#else+displayException' = displayException+#endif+ -- | Test progress information. -- -- This may be used by a runner to provide some feedback to the user while@@ -201,7 +227,7 @@   -- | Run the test   --   -- This method should cleanly catch any exceptions in the code to test, and-  -- return them as part of the 'Result', see 'FailureReason' for an+  -- return them as part of the t'Result', see 'FailureReason' for an   -- explanation. It is ok for 'run' to raise an exception if there is a   -- problem with the test suite code itself (for example, if a file that   -- should contain example data or expected output is not found).@@ -214,12 +240,43 @@   -- | The list of options that affect execution of tests of this type   testOptions :: Tagged t [OptionDescription] +-- | @since 1.5.4+instance IsTest t => IsTest (ContT () IO t) where+  testOptions = coerce (testOptions @t)+  run opts (ContT k) yieldProgress = do+    resRef <- newIORef Nothing+    let runInIORef :: t -> IO ()+        runInIORef t = do+          res <- run opts t yieldProgress+          let err = testFailed "Continuation was called multiple times"+          atomicModifyIORef' resRef $ \prev ->+            (Just $ maybe res (const err) prev, ())+    k runInIORef+    maybeRes <- readIORef resRef+    pure $ case maybeRes of+      Nothing -> testFailed "Continuation was not called"+      Just r -> r++-- | t'Result' of a failed test.+--+-- @since 0.8+testFailed+  :: String -- ^ description+  -> Result+testFailed desc = Result+  { resultOutcome = Failure TestFailed+  , resultDescription = desc+  , resultShortDescription = "FAIL"+  , resultTime = 0+  , resultDetailsPrinter = noResultDetails+  }+ -- | The name of a test or a group of tests. -- -- @since 0.1 type TestName = String --- | 'ResourceSpec' describes how to acquire a resource (the first field)+-- | t'ResourceSpec' describes how to acquire a resource (the first field) -- and how to release it (the second field). -- -- @since 0.6@@ -230,7 +287,6 @@   = NotRunningTests   | UnexpectedState String String   | UseOutsideOfTest-  deriving Typeable  instance Show ResourceError where   show NotRunningTests =@@ -264,19 +320,26 @@  -- | Determines mode of execution of a 'TestGroup' data ExecutionMode-  = Sequential DependencyType-  -- ^ Execute tests one after another-  | Parallel-  -- ^ Execute tests in parallel+  = Dependent DependencyType+  -- ^ Test have dependencies+  | Independent Parallel+  -- ^ Test have no dependencies   deriving (Show, Read) +data Parallel+  = Parallel+  -- ^ Tests can be run in parallel+  | NonParallel+  -- ^ Tests should not be parallelized+  deriving (Show, Read)+ -- | Determines mode of execution of a 'TestGroup'. Note that this option is -- not exposed as a command line argument. instance IsOption ExecutionMode where-  defaultValue = Parallel+  defaultValue = Independent Parallel   parseValue = readMaybe   optionName = Tagged "execution-mode"-  optionHelp = Tagged "Whether to execute tests sequentially or in parallel"+  optionHelp = Tagged "Whether tests have dependencies or not"   optionCLParser = mkOptionCLParser internal  -- | The main data structure defining a test suite.@@ -316,20 +379,68 @@     -- @since 1.2  -- | Create a named group of test cases or other groups. Tests are executed in--- parallel. For sequential execution, see 'sequentialTestGroup'.+-- parallel. For sequential execution, see 'dependentTestGroup'. -- -- @since 0.1 testGroup :: TestName -> [TestTree] -> TestTree testGroup = TestGroup --- | Create a named group of test cases or other groups. Tests are executed in--- order. For parallel execution, see 'testGroup'.+{-# DEPRECATED sequentialTestGroup "Use dependentTestGroup instead" #-}+-- | Legacy name for 'dependentTestGroup'.+--+-- @since 1.5 sequentialTestGroup :: TestName -> DependencyType -> [TestTree] -> TestTree-sequentialTestGroup nm depType = setSequential . TestGroup nm . map setParallel+sequentialTestGroup = dependentTestGroup++-- | Create a named group of test cases or other groups. Tests are executed in+-- order and each test is considered a dependency of the next one.+-- If filtering by t'TestPattern' (@--pattern@) is in action,+-- any test matching the pattern also shields earlier tests from filtering out,+-- even if they themselves do not match the pattern.+--+-- For parallel execution, see 'testGroup'. For ordered test execution, but+-- with default filtering behavior, see 'inOrderTestGroup'.+--+-- Note that this is will only work when used with the default 'Test.Tasty.Ingredients.TestManager'.+-- If you use another manager, like @tasty-rerun@ for instance, sequentiality+-- might possibly be ignored.+--+-- @since 1.5.4+dependentTestGroup+  :: TestName+  -- ^ name of the group+  -> DependencyType+  -- ^ whether to run subsequent tests even if earlier ones have failed+  -> [TestTree]+  -- ^ tests to execute sequentially+  -> TestTree+dependentTestGroup nm depType = setDependent . TestGroup nm . map setParallel  where-  setParallel = PlusTestOptions (setOption Parallel)-  setSequential = PlusTestOptions (setOption (Sequential depType))+  setParallel = PlusTestOptions (setOption $ Independent Parallel)+  setDependent = PlusTestOptions (setOption (Dependent depType)) ++-- | Create a named group of test cases that will be played sequentially,+-- in the exact order provided. Similarly to 'testGroup'+-- and in contrast to 'dependentTestGroup',+-- filtering by t'TestPattern' is applied uniformly.+--+-- Note that this is will only work when used with the default 'Test.Tasty.Ingredients.TestManager'.+-- If you use another manager, like @tasty-rerun@ for instance, the fact that+-- these tests should be run in the given order might possibly be ignored.+--+-- @since 1.5.4+inOrderTestGroup+  :: TestName+  -- ^ name of the group+  -> [TestTree]+  -- ^ tests to execute sequentially+  -> TestTree+inOrderTestGroup nm = setSequential . TestGroup nm . map setParallel+ where+  setParallel = PlusTestOptions (setOption $ Independent Parallel)+  setSequential = PlusTestOptions (setOption (Independent NonParallel))+ -- | Like 'after', but accepts the pattern as a syntax tree instead -- of a string. Useful for generating a test tree programmatically. --@@ -408,7 +519,7 @@ -- -- Instead of constructing fresh records, build upon `trivialFold` -- instead. This way your code won't break when new nodes/fields are--- indroduced.+-- introduced. -- -- @since 0.7 data TreeFold b = TreeFold@@ -450,7 +561,7 @@ -- a user's filter. This is used to force dependencies of a test to run. For -- example, if test @A@ depends on test @B@ and test @A@ is selected to run, test -- @B@ will be forced to match. Note that this only applies to dependencies--- specified using 'sequentialTestGroup'.+-- specified using 'dependentTestGroup'. type ForceTestMatch = Any  -- | Fold a test tree into a single value.@@ -504,7 +615,7 @@       AnnWithResource opts res0 tree -> fResource opts res0 $ \res -> go (tree res)       AnnAfter opts deptype dep tree -> fAfter opts deptype dep (go tree) --- | 'TestTree' with arbitrary annotations, e. g., evaluated 'OptionSet'.+-- | 'TestTree' with arbitrary annotations, e. g., evaluated t'OptionSet'. data AnnTestTree ann   = AnnEmptyTestTree   -- ^ Just an empty test tree (e. g., when everything has been filtered out).@@ -581,15 +692,15 @@        AnnTestGroup (opts, _) name trees ->         case lookupOption opts of-          Parallel ->+          Dependent _ ->+            second+              (mkGroup opts name)+              (mapAccumR go forceMatch trees)+          Independent _ ->             bimap               mconcat               (mkGroup opts name)               (unzip (map (go forceMatch) trees))-          Sequential _ ->-            second-              (mkGroup opts name)-              (mapAccumR go forceMatch trees)        AnnWithResource (opts, _) res0 tree ->         ( fst (go forceMatch (tree (throwIO NotRunningTests)))
Test/Tasty/Ingredients.hs view
@@ -36,7 +36,7 @@ -- which options it cares about, so that those options are presented to -- the user if the ingredient is included in the test suite. ----- An ingredient can choose, typically based on the 'OptionSet', whether to+-- An ingredient can choose, typically based on the t'OptionSet', whether to -- run. That's what the 'Maybe' is for. The first ingredient that agreed to -- run does its work, and the remaining ingredients are ignored. Thus, the -- order in which you arrange the ingredients may matter.@@ -87,7 +87,7 @@  -- | Try to run an 'Ingredient'. ----- If the ingredient refuses to run (usually based on the 'OptionSet'),+-- If the ingredient refuses to run (usually based on the t'OptionSet'), -- the function returns 'Nothing'. -- -- For a 'TestReporter', this function automatically starts running the@@ -117,7 +117,7 @@ -- -- Note that this isn't the same as simply pattern-matching on -- 'Ingredient'. E.g. options for a 'TestReporter' automatically include--- 'NumThreads'.+-- t'NumThreads'. -- -- @since 0.4 ingredientOptions :: Ingredient -> [OptionDescription]
Test/Tasty/Ingredients/ConsoleReporter.hs view
@@ -1,5 +1,5 @@ -- vim:fdm=marker-{-# LANGUAGE BangPatterns, ImplicitParams, MultiParamTypeClasses, DeriveDataTypeable, FlexibleContexts, CApiFFI, NamedFieldPuns #-}+{-# LANGUAGE BangPatterns, ImplicitParams, MultiParamTypeClasses, FlexibleContexts, CApiFFI, NamedFieldPuns #-} -- | Console reporter ingredient. -- -- @since 0.11.3@@ -66,6 +66,7 @@ #if !MIN_VERSION_base(4,11,0) import Data.Foldable (foldMap) #endif+import System.IO.Unsafe  -------------------------------------------------- -- TestOutput base definitions@@ -124,7 +125,28 @@  type Level = Int --- | Build the 'TestOutput' for a 'TestTree' and 'OptionSet'. The @colors@+-- TODO before the next major release:+-- refactor this as an argument to 'buildTestOutput'+-- to avoid unsafePerformIO.+-- (We cannot add another argument to 'buildTestOutput'+-- in the middle of tasty-1.5 series, because it is exported)+terminalWidth :: Maybe Int+terminalWidth = unsafePerformIO $ do+  isTerminalStdin <- hIsTerminalDevice stdin+  if isTerminalStdin+  then fmap (fmap snd) getTerminalSize+  else pure Nothing+{-# NOINLINE terminalWidth #-}++-- | How wide could 'resultShortDescription' be (in non-extreme scenarios)?+-- Think of something like "OK", "FAIL (12.34s)", "TIMEOUT (100.00s)".+--+-- The field is freeform and test providers can put an arbitrarily long data,+-- so we just settle for a reasonable (over)approximation.+approxMaxResultShortDescriptionWidth :: Int+approxMaxResultShortDescriptionWidth = 20++-- | Build the 'TestOutput' for a 'TestTree' and t'OptionSet'. The @colors@ -- ImplicitParam controls whether the output is colored. -- -- @since 0.11.3@@ -132,7 +154,10 @@ buildTestOutput opts tree =   let     -- Do not retain the reference to the tree more than necessary-    !alignment = computeAlignment opts tree+    !rawAlignment = computeAlignment opts tree+    !alignment = case terminalWidth of+      Nothing -> rawAlignment+      Just width -> min (width - approxMaxResultShortDescriptionWidth) rawAlignment      MinDurationToReport{minDurationMicros} = lookupOption opts @@ -251,7 +276,7 @@   :: Monoid b   => (String -> IO () -> IO Result -> (Result -> IO ()) -> b)   -- ^ Eliminator for test cases. The @IO ()@ prints the testname. The-  -- @IO Result@ blocks until the test is finished, returning it's 'Result'.+  -- @IO Result@ blocks until the test is finished, returning it's t'Result'.   -- The @Result -> IO ()@ function prints the formatted output.   -> (String -> IO () -> b -> b)   -- ^ Eliminator for test groups. The @IO ()@ prints the test group's name.@@ -395,7 +420,7 @@   mappend = (Sem.<>) #endif --- | @computeStatistics@ computes a summary 'Statistics' for+-- | @computeStatistics@ computes a summary t'Statistics' for -- a given state of the 'StatusMap'. -- Useful in combination with 'printStatistics'. --@@ -597,7 +622,7 @@ -- -- @since 0.8 newtype Quiet = Quiet Bool-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord) instance IsOption Quiet where   defaultValue = Quiet False   parseValue = fmap Quiet . safeReadBool@@ -612,7 +637,7 @@ -- -- @since 0.8 newtype HideSuccesses = HideSuccesses Bool-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord) instance IsOption HideSuccesses where   defaultValue = HideSuccesses False   parseValue = fmap HideSuccesses . safeReadBool@@ -625,7 +650,7 @@ -- -- @since 1.5 newtype MinDurationToReport = MinDurationToReport { minDurationMicros :: Integer }-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord) instance IsOption MinDurationToReport where   defaultValue = MinDurationToReport 10000   parseValue = fmap MinDurationToReport . parseDuration@@ -644,7 +669,7 @@   = Never   | Always   | Auto -- ^ Only if stdout is an ANSI color supporting terminal-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord)  -- | Control color output instance IsOption UseColor where@@ -672,7 +697,6 @@ -- -- @since 1.3 newtype AnsiTricks = AnsiTricks { getAnsiTricks :: Bool }-  deriving Typeable  instance IsOption AnsiTricks where   defaultValue = AnsiTricks True@@ -821,7 +845,7 @@ -- line or console detection. -- -- Can be used by providers that wish to provider specific result details printing,--- while re-using the tasty formats and coloring logic.+-- while reusing the tasty formats and coloring logic. -- -- @since 1.3.1 withConsoleFormat :: (?colors :: Bool) => ConsoleFormatPrinter
Test/Tasty/Ingredients/ListTests.hs view
@@ -1,5 +1,5 @@ -- | Ingredient for listing test names-{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving #-} module Test.Tasty.Ingredients.ListTests   ( ListTests(..)   , testsNames@@ -7,7 +7,6 @@   ) where  import Data.Proxy-import Data.Typeable import Options.Applicative  import Test.Tasty.Core@@ -19,7 +18,7 @@ -- -- @since 0.4 newtype ListTests = ListTests Bool-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord) instance IsOption ListTests where   defaultValue = ListTests False   parseValue = fmap ListTests . safeReadBool
Test/Tasty/Options.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, DeriveDataTypeable,+{-# LANGUAGE ScopedTypeVariables,              ExistentialQuantification, GADTs,              FlexibleInstances, UndecidableInstances,              TypeOperators #-}@@ -135,7 +135,7 @@ changeOption :: forall v . IsOption v => (v -> v) -> OptionSet -> OptionSet changeOption f s = setOption (f $ lookupOption s) s --- | Create a singleton 'OptionSet'.+-- | Create a singleton t'OptionSet'. -- -- @since 0.8 singleOption :: IsOption v => v -> OptionSet
Test/Tasty/Options/Core.hs view
@@ -1,5 +1,5 @@ -- | Core options, i.e. the options used by tasty itself-{-# LANGUAGE CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} -- for (^) module Test.Tasty.Options.Core   ( NumThreads(..)@@ -14,13 +14,14 @@  import Control.Monad (mfilter) import Data.Proxy-import Data.Typeable import Data.Fixed import Options.Applicative hiding (str) import GHC.Conc #if !MIN_VERSION_base(4,11,0) import Data.Monoid #endif+import Control.Concurrent+import System.IO.Unsafe  import Test.Tasty.Options import Test.Tasty.Patterns@@ -36,14 +37,15 @@ -- -- @since 0.1 newtype NumThreads = NumThreads { getNumThreads :: Int }-  deriving (Eq, Ord, Num, Typeable)+  deriving (Eq, Ord, Num) instance IsOption NumThreads where-  defaultValue = NumThreads numCapabilities+  defaultValue = unsafePerformIO $ NumThreads <$>+      if rtsSupportsBoundThreads then getNumProcessors else pure 1   parseValue = mfilter onlyPositive . fmap NumThreads . safeRead   optionName = return "num-threads"   optionHelp = return "Number of threads to use for tests execution"   optionCLParser = mkOptionCLParser (short 'j' <> metavar "NUMBER")-  showDefaultValue _ = Just "# of cores/capabilities"+  showDefaultValue _ = Just "Number of cores when using threaded RTS, 1 for non-threaded"  -- | Filtering function to prevent non-positive number of threads onlyPositive :: NumThreads -> Bool@@ -60,15 +62,14 @@   | NoTimeout   deriving   ( Eq-  -- ^ Auto-derived instance, just to allow storing in a 'Map' and such.+  -- ^ Auto-derived instance, just to allow storing in a 'Data.Map.Map' and such.   --   -- @since 1.5.1   , Ord-  -- ^ Auto-derived instance, just to allow storing in a 'Map' and such.+  -- ^ Auto-derived instance, just to allow storing in a 'Data.Map.Map' and such.   --   -- @since 1.5.1   , Show-  , Typeable   )  instance IsOption Timeout where@@ -99,7 +100,7 @@         _ -> Nothing     _ -> Nothing --- | A shortcut for creating 'Timeout' values.+-- | A shortcut for creating v'Timeout' values. -- -- @since 0.8 mkTimeout@@ -116,7 +117,7 @@ -- -- @since 1.5 newtype HideProgress = HideProgress { getHideProgress :: Bool }-  deriving (Eq, Ord, Typeable)+  deriving (Eq, Ord) instance IsOption HideProgress where     defaultValue = HideProgress False     parseValue = fmap HideProgress . safeReadBool@@ -126,7 +127,7 @@  -- | The list of all core options, i.e. the options not specific to any -- provider or ingredient, but to tasty itself. Currently contains--- 'TestPattern' and 'Timeout'.+-- t'TestPattern', t'Timeout' and t'HideProgress'. -- -- @since 0.1 coreOptions :: [OptionDescription]
Test/Tasty/Options/Env.hs view
@@ -1,5 +1,5 @@ -- | Get options from the environment-{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-} module Test.Tasty.Options.Env (getEnvOptions, suiteEnvOptions) where  import Test.Tasty.Options@@ -8,14 +8,10 @@ import Test.Tasty.Runners.Reducers  import System.Environment-import Data.Foldable import Data.Tagged import Data.Proxy import Data.Char-import Data.Typeable import Control.Exception-import Control.Applicative-import Prelude  -- Silence AMP and FTP import warnings import Text.Printf  data EnvOptionException@@ -23,7 +19,6 @@       String -- option name       String -- variable name       String -- value-  deriving (Typeable)  instance Show EnvOptionException where   show (BadOption optName varName value) =
Test/Tasty/Parallel.hs view
@@ -1,5 +1,4 @@ -- | A helper module which takes care of parallelism-{-# LANGUAGE DeriveDataTypeable #-} module Test.Tasty.Parallel (ActionStatus(..), Action(..), runInParallel) where  import Control.Monad@@ -8,7 +7,7 @@ import Control.Concurrent.STM import Foreign.StablePtr --- | What to do about an 'Action'?+-- | What to do about an t'Action'? data ActionStatus   = ActionReady     -- ^ the action is ready to be executed@@ -42,6 +41,12 @@ -- actions themselves. Any exceptions that reach this function or its -- threads are by definition unexpected. runInParallel nthreads actions = do+  -- When linked with threaded RTS, ensure we have enough Capabilities+  -- so that all Haskell worker threads can truly run in parallel.+  when rtsSupportsBoundThreads $ do+    ncap <- getNumCapabilities+    when (ncap < nthreads) $ setNumCapabilities nthreads+   callingThread <- myThreadId    -- Don't let the main thread be garbage-collected
Test/Tasty/Patterns.hs view
@@ -1,6 +1,6 @@ -- | Test patterns -{-# LANGUAGE CPP, DeriveDataTypeable, TypeApplications #-}+{-# LANGUAGE CPP, TypeApplications #-}  module Test.Tasty.Patterns   ( TestPattern(..)@@ -21,7 +21,6 @@ import Data.Coerce (coerce) import Data.List.NonEmpty (nonEmpty) import Data.Maybe (catMaybes)-import Data.Typeable import Options.Applicative hiding (Success) #if !MIN_VERSION_base(4,11,0) import Data.Monoid@@ -33,8 +32,7 @@   TestPattern     (Maybe Expr)   deriving-  ( Typeable-  , Show -- ^ @since 1.1+  ( Show -- ^ @since 1.1   , Eq   -- ^ @since 1.1   ) 
Test/Tasty/Patterns/Eval.hs view
@@ -12,10 +12,6 @@ import Data.Maybe import Data.Char import Test.Tasty.Patterns.Types-#if !MIN_VERSION_base(4,9,0)-import Control.Applicative-import Data.Traversable-#endif  -- | @since 1.2 type Path = Seq.Seq String
Test/Tasty/Patterns/Parser.hs view
@@ -25,7 +25,7 @@  type Token = ReadP --- | A separate 'Parser' data type ensures that we don't forget to skip+-- | A separate t'Parser' data type ensures that we don't forget to skip -- spaces. -- -- @since 1.0
Test/Tasty/Providers.hs view
@@ -23,7 +23,7 @@ singleTest :: IsTest t => TestName -> t -> TestTree singleTest = SingleTest --- | 'Result' of a passed test.+-- | t'Result' of a passed test. -- -- @since 0.8 testPassed@@ -37,21 +37,7 @@   , resultDetailsPrinter = noResultDetails   } --- | 'Result' of a failed test.------ @since 0.8-testFailed-  :: String -- ^ description-  -> Result-testFailed desc = Result-  { resultOutcome = Failure TestFailed-  , resultDescription = desc-  , resultShortDescription = "FAIL"-  , resultTime = 0-  , resultDetailsPrinter = noResultDetails-  }---- | 'Result' of a failed test with custom details printer+-- | t'Result' of a failed test with custom details printer -- -- @since 1.3.1 testFailedDetails
Test/Tasty/Providers/ConsoleFormat.hs view
@@ -1,5 +1,5 @@ -- | This module can be used by providers to perform colorful/formatted--- output and possibly re-use tasty's own output formats.+-- output and possibly reuse tasty's own output formats. -- -- @since 1.3.1 module Test.Tasty.Providers.ConsoleFormat@@ -68,13 +68,13 @@ infoFailFormat :: ConsoleFormat infoFailFormat = ConsoleFormat NormalIntensity Dull  Red --- | Format used to display sucesses+-- | Format used to display successes -- -- @since 1.3.1 okFormat :: ConsoleFormat okFormat = ConsoleFormat NormalIntensity Dull  Green --- | Format used to display additional information on sucesses+-- | Format used to display additional information on successes -- -- @since 1.3.1 infoOkFormat :: ConsoleFormat
Test/Tasty/Run.hs view
@@ -1,6 +1,6 @@ -- | Running tests {-# LANGUAGE ScopedTypeVariables, ExistentialQuantification, RankNTypes,-             FlexibleContexts, CPP, DeriveDataTypeable, LambdaCase,+             FlexibleContexts, CPP, LambdaCase,              RecordWildCards, NamedFieldPuns #-} module Test.Tasty.Run   ( Status(..)@@ -18,7 +18,6 @@ import Data.List (intercalate) import Data.Graph (SCC(..), stronglyConnComp) import Data.Sequence (Seq, (|>), (<|), (><))-import Data.Typeable import Control.Monad (forever, guard, join, liftM) import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Reader (ReaderT(..), local, ask)@@ -27,11 +26,9 @@ import Control.Concurrent.STM import Control.Concurrent.Async import Control.Exception as E-import Control.Applicative import Control.Arrow import Data.Monoid (First(..)) import GHC.Conc (labelThread)-import Prelude  -- Silence AMP and FTP import warnings  #if MIN_VERSION_base(4,18,0) import Data.Traversable (mapAccumM)@@ -137,7 +134,7 @@       timed $ applyTimeout timeoutOpt $ do         r <- wait asy         -- Not only wait for the result to be returned, but make sure to-        -- evalute it inside applyTimeout; see #280.+        -- evaluate it inside applyTimeout; see #280.         evaluate $           resultOutcome r `seq`           forceElements (resultDescription r) `seq`@@ -249,7 +246,6 @@     -- A finishes. Field lists detected cycles.     --     -- @since 1.5-  deriving (Typeable)  instance Show DependencyException where   show (DependencyLoop css) = "Test dependencies have cycles:\n" ++ showCycles css@@ -282,7 +278,7 @@ data Dependency = Dependency DependencyType DependencySpec   deriving (Eq, Show) --- | Is given 'Dependency' a dependency that was introduced with 'After'?+-- | Is given t'Dependency' a dependency that was introduced with 'After'? isPatternDependency :: Dependency -> Bool isPatternDependency (Dependency _ (PatternDep {})) = True isPatternDependency _ = False@@ -291,7 +287,7 @@ -- The mapAccumM function behaves like a combination of mapM and mapAccumL that -- traverses the structure while evaluating the actions and passing an accumulating -- parameter from left to right. It returns a final value of this accumulator--- together with the new structure. The accummulator is often used for caching the+-- together with the new structure. The accumulator is often used for caching the -- intermediate results of a computation. mapAccumM :: Monad m => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y]) mapAccumM _ acc [] = return (acc, [])@@ -304,7 +300,7 @@ -- | An action with meta information data TestAction act = TestAction   { testAction :: act-    -- ^ Some action, typically 'UnresolvedAction', 'ResolvedAction', or 'Action'.+    -- ^ Some action, typically 'UnresolvedAction', 'ResolvedAction', or t'Action'.   , testPath :: Path     -- ^ Path pointing to this action (a series of group names + a test name)   , testDeps :: Seq Dependency@@ -325,8 +321,8 @@ type Size = Int  -- | Simplified version of 'TestTree' that only includes the tests to be run (as--- a 'TestAction') and the resources needed to run them (as 'Initializer's and--- 'Finalizer's).+-- a t'TestAction') and the resources needed to run them (as t'Initializer's and+-- t'Finalizer's). data TestActionTree act   = TResource Initializer Finalizer (TestActionTree act)   | TGroup Size [TestActionTree act]@@ -419,11 +415,14 @@     foldGroup opts name trees =       fmap tGroup $ local (first (|> name)) $         case lookupOption opts of-          Parallel ->-            sequence trees-          Sequential depType ->-            snd <$> mapAccumM (goSeqGroup depType) mempty trees+          Independent Parallel -> sequence trees+          Independent NonParallel -> foldSequential AllFinish trees+          Dependent depType -> foldSequential depType trees +    foldSequential :: DependencyType -> [Tr] -> ReaderT (Path, Seq Dependency) IO [TestActionTree UnresolvedAction]+    foldSequential depType =+      fmap snd . mapAccumM (goSeqGroup depType) mempty+     -- * Utility functions     collectTests :: TestActionTree act -> [TestAction act]     collectTests = \case@@ -577,7 +576,7 @@     FailedToCreate {} -> return $ return Nothing     Destroyed         -> return $ return Nothing --- While tasty allows to configure 'OptionSet' at any level of test tree,+-- While tasty allows to configure t'OptionSet' at any level of test tree, -- it often has any effect only on options of test providers (class IsTest). -- But test runners and reporters typically only look into the OptionSet -- they were given as an argument. This is not unreasonable: e. g., if an option@@ -586,9 +585,9 @@ -- a global option, without passing it via command line. -- -- 'applyTopLevelPlusTestOptions' allows for a compromise: unwrap top-level--- 'PlusTestOptions' from the 'TestTree' and apply them to the 'OptionSet'+-- 'PlusTestOptions' from the 'TestTree' and apply them to the t'OptionSet' -- from command line. This way a user can wrap their tests in--- 'adjustOption' / 'localOption' forcing, for instance, 'NumThreads' to 1.+-- 'adjustOption' / 'localOption' forcing, for instance, t'NumThreads' to 1. -- -- This function is not publicly exposed. applyTopLevelPlusTestOptions@@ -607,7 +606,7 @@ -- -- Once the callback returns, stop running the tests. ----- The number of test running threads is determined by the 'NumThreads'+-- The number of test running threads is determined by the t'NumThreads' -- option. -- -- @since 0.10
Test/Tasty/Runners/Reducers.hs view
@@ -41,8 +41,8 @@  module Test.Tasty.Runners.Reducers where +import Prelude hiding (Applicative(..)) import Control.Applicative-import Prelude  -- Silence AMP import warnings import qualified Data.Semigroup as Sem  -- | Monoid generated by '*>'.
Test/Tasty/Runners/Utils.hs view
@@ -4,11 +4,8 @@ module Test.Tasty.Runners.Utils where  import Control.Exception-import Control.Applicative import Control.Concurrent (mkWeakThreadId, myThreadId) import Control.Monad (forM_)-import Data.Typeable (Typeable)-import Prelude  -- Silence AMP import warnings import Text.Printf import Foreign.C (CInt) @@ -66,7 +63,7 @@  -- from https://ro-che.info/articles/2014-07-30-bracket -- | Install signal handlers so that e.g. the cursor is restored if the test--- suite is killed by SIGTERM. Upon a signal, a 'SignalException' will be+-- suite is killed by SIGTERM. Upon a signal, a t'SignalException' will be -- thrown to the thread that has executed this action. -- -- This function is called automatically from the @defaultMain*@ family of@@ -102,7 +99,7 @@ -- -- @since 1.2.1 newtype SignalException = SignalException CInt-  deriving (Show, Typeable)+  deriving (Show) instance Exception SignalException  -- | Measure the time taken by an 'IO' action to run.
tasty.cabal view
@@ -1,6 +1,6 @@ cabal-version:       >=1.10 name:                tasty-version:             1.5.3+version:             1.5.4 synopsis:            Modern and extensible testing framework description:         Tasty is a modern testing framework for Haskell.                      It lets you combine your unit tests, golden@@ -29,12 +29,12 @@  library   exposed-modules:-    Test.Tasty,-    Test.Tasty.Options,-    Test.Tasty.Providers,-    Test.Tasty.Providers.ConsoleFormat,+    Test.Tasty+    Test.Tasty.Options+    Test.Tasty.Providers+    Test.Tasty.Providers.ConsoleFormat     Test.Tasty.Runners-    Test.Tasty.Ingredients,+    Test.Tasty.Ingredients     Test.Tasty.Ingredients.Basic     Test.Tasty.Ingredients.ConsoleReporter @@ -45,36 +45,33 @@     Test.Tasty.Patterns.Eval   other-modules:     Control.Concurrent.Async-    Test.Tasty.Parallel,-    Test.Tasty.Core,-    Test.Tasty.Options.Core,-    Test.Tasty.Options.Env,-    Test.Tasty.Patterns,-    Test.Tasty.Patterns.Expr,-    Test.Tasty.Run,-    Test.Tasty.Runners.Reducers,-    Test.Tasty.Runners.Utils,-    Test.Tasty.CmdLine,+    Test.Tasty.Parallel+    Test.Tasty.Core+    Test.Tasty.Options.Core+    Test.Tasty.Options.Env+    Test.Tasty.Patterns+    Test.Tasty.Patterns.Expr+    Test.Tasty.Run+    Test.Tasty.Runners.Reducers+    Test.Tasty.Runners.Utils+    Test.Tasty.CmdLine     Test.Tasty.Ingredients.ListTests     Test.Tasty.Ingredients.IncludingOptions    build-depends:     base                 >= 4.9  && < 5,     stm                  >= 2.3  && < 2.6,-    containers           >= 0.5.8 && < 0.8,+    containers           >= 0.5.8 && < 0.9,     transformers         >= 0.5  && < 0.7,     tagged               >= 0.5  && < 0.9,-    optparse-applicative >= 0.14 && < 0.19,+    optparse-applicative >= 0.14 && < 0.20,     ansi-terminal        >= 0.9  && < 1.2    -- No reason to depend on unbounded-delays on 64-bit architecture-  if(!arch(x86_64) && !arch(aarch64) && !arch(ppc64) && !arch(s390x) && !arch(riscv64))+  if(!arch(x86_64) && !arch(aarch64) && !arch(ppc64le) && !arch(ppc64) && !arch(s390x) && !arch(riscv64) && !arch(loongarch64))     build-depends:       unbounded-delays >= 0.1 && < 0.2 -  if(!impl(ghc >= 8.0))-    build-depends: semigroups < 0.21-   if(!impl(ghc >= 8.4))     build-depends: time >= 1.4 && < 1.13 @@ -85,7 +82,7 @@    -- hs-source-dirs:   default-language:    Haskell2010-  default-extensions:  CPP, ScopedTypeVariables, DeriveDataTypeable+  default-extensions:  CPP, ScopedTypeVariables   ghc-options:     -Wall     -Wno-incomplete-uni-patterns