packages feed

sydtest 0.33.0.0 → 0.33.2.0

raw patch · 4 files changed

+133/−48 lines, 4 files

Files

CHANGELOG.md view
@@ -1,5 +1,24 @@ # Changelog +## [0.33.2.0] - 2026-10-24++### Fixed++* The warning to compile with `-threaded -rtsopts -with-rtsopts=-N` also fires+  when the thread count was asked for, such as `--jobs 4` on one capability.++## [0.33.1.0] - 2026-10-24++### Added++* `NIX_BUILD_CORES` narrows the thread count to the cores nix gave the build,+  when nothing else says how parallel to run.++### Fixed++* Zero threads means every capability, rather than an asynchronous runner with+  no workers to take tests off the queue.+ ## [0.33.0.0] - 2026-10-01  ### Fixed
src/Test/Syd/MutationMode/Common.hs view
@@ -459,14 +459,14 @@       ]  -- | Render the per-mutation progress line emitted as each mutation is--- tested.  @index@\/@total@ are this mutation's 1-based position in the run--- and the total mutation count, shown as a coloured @[X\/Y]@ counter.  The--- @verbose@ flag controls detail: in concise mode (the default) this is the--- single locating line @[X\/Y] Testing mutation \<operator\> at--- \<file\>:\<line\>:\<cols\>@, so a long run shows steady progress — including--- how far along it is — without flooding the log; in verbose\/debug mode the--- full source diff of the mutation follows — the same block the report prints--- for a survivor.+-- tested.  @index@\/@total@ are how many mutations have started, this one+-- included, and how many the run tests in total, shown as a coloured+-- @[X\/Y]@ counter.  The @verbose@ flag controls detail: in concise mode+-- (the default) this is the single locating line @[X\/Y] Testing mutation+-- \<operator\> at \<file\>:\<line\>:\<cols\>@, so a long run shows steady+-- progress — including how far along it is — without flooding the log; in+-- verbose\/debug mode the full source diff of the mutation follows — the+-- same block the report prints for a survivor. renderMutationProgressEvent :: Bool -> Int -> Int -> MutationProgressEvent -> [[Chunk]] renderMutationProgressEvent verbose index total (MutationProgressEvent rec) =   let logLines = formatMutationLog (augmentedMutationRecordId rec) rec
src/Test/Syd/OptParse.hs view
@@ -12,7 +12,6 @@ import Autodocodec import Control.Applicative import Control.Concurrent (getNumCapabilities)-import Control.Monad import Control.Monad.IO.Class import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe@@ -170,35 +169,34 @@             Just True -> pure WithoutColours             _ -> detectTerminalCapabilities -        let threads =+        let configuredThreads =               fromMaybe                 ( if flagDebug                     then Synchronous                     else d settingThreads                 )                 flagThreads-        case threads of-          ByCapabilities -> do-            i <- getNumCapabilities--            when (i == 1) $ do-              let outputLine :: [Chunk] -> IO ()-                  outputLine lineChunks =-                    liftIO $-                      -- Emit UTF-8 bytes directly so output never depends on the-                      -- handle's locale encoding; the trailing newline is folded-                      -- into the chunks to keep this one byte-level write.-                      putChunksUtf8With terminalCapabilities (lineChunks <> [chunk "\n"])-              mapM_-                ( outputLine-                    . (: [])-                    . fore red-                )-                [ chunk "WARNING: Only one CPU core detected, make sure to compile your test suite with these ghc options:",-                  chunk "         -threaded -rtsopts -with-rtsopts=-N",-                  chunk "         (This is important for correctness as well as speed, as a parallel test suite can find thread safety problems.)"-                ]-          _ -> pure ()+        numCapabilities <- getNumCapabilities+        let threads = threadsWithNixBuildCores numCapabilities flagNixBuildCores configuredThreads+        case oneCapabilityWarning numCapabilities threads of+          WarnAboutOneCapability -> do+            let outputLine :: [Chunk] -> IO ()+                outputLine lineChunks =+                  liftIO $+                    -- Emit UTF-8 bytes directly so output never depends on the+                    -- handle's locale encoding; the trailing newline is folded+                    -- into the chunks to keep this one byte-level write.+                    putChunksUtf8With terminalCapabilities (lineChunks <> [chunk "\n"])+            mapM_+              ( outputLine+                  . (: [])+                  . fore red+              )+              [ chunk "WARNING: This test suite can only use one capability, make sure to compile it with these ghc options:",+                chunk "         -threaded -rtsopts -with-rtsopts=-N",+                chunk "         (This is important for correctness as well as speed, as a parallel test suite can find thread safety problems.)"+              ]+          NoOneCapabilityWarning -> pure ()         errOrProgress <- case flagReportProgress of           Nothing ->             pure $@@ -377,6 +375,7 @@   { flagSeed :: !SeedSetting,     flagRandomiseExecutionOrder :: !(Maybe Bool),     flagThreads :: !(Maybe Threads),+    flagNixBuildCores :: !(Maybe Word),     flagMaxSize :: !Int,     flagMaxSuccess :: !Int,     flagMaxDiscard :: !Int,@@ -420,6 +419,7 @@             name "randomize-execution-order"           ]     flagThreads <- optional settingsParser+    flagNixBuildCores <- nixBuildCoresParser     flagMaxSize <-       setting         [ help "Maximum size parameter to pass to generators",@@ -702,13 +702,53 @@     Asynchronous !Word   deriving (Show, Read, Eq, Generic) +-- | Whether to tell a test suite's author that it can only use one+-- capability.+data OneCapabilityWarning+  = WarnAboutOneCapability+  | NoOneCapabilityWarning+  deriving (Show, Eq)++-- | Whether a test suite that would run tests at the same time can do so.+--+-- A suite with one capability runs its tests one at a time, so it gets+-- neither the speed of running them at the same time nor the thread safety+-- problems that only tests running at the same time find.  Compiling with+-- @-threaded@ and @-N@ is what raises the capability count, which is why+-- that is the advice, and it is advice about the suite rather than about the+-- machine it is on: a suite built without @-N@ has one capability on every+-- machine, so a single-processor machine is worth warning on too, even+-- though nothing would run at the same time there anyway.+--+-- Only a suite that would use more capabilities has anything to gain.+-- 'Synchronous' would not, and neither would an 'Asynchronous' bound of a+-- single test.+oneCapabilityWarning :: Int -> Threads -> OneCapabilityWarning+oneCapabilityWarning numCapabilities threads =+  if numCapabilities <= 1+    then case threads of+      Synchronous -> NoOneCapabilityWarning+      ByCapabilities -> WarnAboutOneCapability+      Asynchronous bound ->+        if bound > 1+          then WarnAboutOneCapability+          else NoOneCapabilityWarning+    else NoOneCapabilityWarning++-- | How parallel to run the test suite, from a number of threads.+--+-- 0 means every capability, both because zero threads would run no tests at+-- all, and because that is what nix means by 0 cores.+threadsFromWord :: Word -> Threads+threadsFromWord = \case+  0 -> ByCapabilities+  1 -> Synchronous+  w -> Asynchronous w+ instance HasCodec Threads where   codec = dimapCodec f g codec     where-      f = \case-        Nothing -> ByCapabilities-        Just 1 -> Synchronous-        Just n -> Asynchronous n+      f = maybe ByCapabilities threadsFromWord       g = \case         ByCapabilities -> Nothing         Synchronous -> Just 1@@ -717,12 +757,9 @@ instance HasParser Threads where   settingsParser =     choice-      [ ( \case-            1 -> Synchronous-            w -> Asynchronous w-        )+      [ threadsFromWord           <$> setting-            [ help "How many threads to use to execute tests in asynchronously",+            [ help "How many threads to use to execute tests in asynchronously, 0 means as many as you have capabilities",               reader auto,               option,               long "jobs",@@ -745,14 +782,43 @@             ],         setting           [ help "How parallel to run the test suite",-            confWith' "threads" $-              let f = \case-                    Nothing -> Just ByCapabilities-                    Just 1 -> Just Synchronous-                    Just n -> Just $ Asynchronous n-               in f <$> codec+            confWith' "threads" $ Just <$> codec           ]       ]++-- | Nix tells a build how many cores it may use with its @cores@ setting,+-- which reaches the build only as the @NIX_BUILD_CORES@ environment+-- variable.+nixBuildCoresParser :: Parser (Maybe Word)+nixBuildCoresParser =+  optional $+    setting+      [ help "How many threads to use to execute tests in asynchronously, if nothing else says",+        reader auto,+        unprefixedEnv "NIX_BUILD_CORES",+        metavar "INT"+      ]++-- | Narrow "as many threads as you have capabilities" down to the cores nix+-- gave the build.+--+-- Only that case is narrowed, so that anything configured explicitly still+-- decides.+--+-- Narrowed, never widened: more cores than the RTS has capabilities would+-- run more tests at once than it can overlap, which is contention without+-- any parallelism to show for it.  A suite not compiled with @-N@ has a+-- single capability, and running it 64 ways because the builder has 64 cores+-- would be a change for the worse.+threadsWithNixBuildCores :: Int -> Maybe Word -> Threads -> Threads+threadsWithNixBuildCores numCapabilities mCores = \case+  ByCapabilities -> case mCores of+    Nothing -> ByCapabilities+    Just cores+      | cores >= fromIntegral numCapabilities -> ByCapabilities+      | otherwise -> threadsFromWord cores+  Synchronous -> Synchronous+  Asynchronous w -> Asynchronous w  data Iterations   = -- | Run the test suite once, the default
sydtest.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           sydtest-version:        0.33.0.0+version:        0.33.2.0 synopsis:       A modern testing framework for Haskell with good defaults and advanced testing features. description:    A modern testing framework for Haskell with good defaults and advanced testing features. Sydtest aims to make the common easy and the hard possible. See https://github.com/NorfairKing/sydtest#readme for more information. category:       Testing