packages feed

sydtest-0.27.2.0: src/Test/Syd/MutationMode/CoverageListLocations.hs

-- | The child-process entry point that lists each leaf test's source
-- location.
--
-- Prints, as a JSON array, the source location of every leaf test's
-- @it@\/@prop@\/@specify@ call site, then exits.  Used by the diff-scoped
-- mutation runner to map a changed test-source line back to the tests defined
-- there.
module Test.Syd.MutationMode.CoverageListLocations
  ( runCoverageListLocationsMode,
  )
where

import qualified Data.ByteString.Lazy as LB
import GHC.Stack (getCallStack, srcLocFile, srcLocStartLine)
import Path
import Test.Syd.Def
import Test.Syd.Mutation.Forest (flattenTestForestWithIdsAndCallStacks)
import Test.Syd.Mutation.TestLocation (TestLocation (..), encodeTestLocations)
import Test.Syd.OptParse

-- | Child-side entry point that prints, as a JSON array, the source location
-- of every leaf test's @it@\/@prop@\/@specify@ call site, then exits.  Each
-- element is a 'TestLocation' (test id, source file, line).
--
-- A leaf whose 'CallStack' is empty (it carries no recorded frame), or whose
-- source file does not parse as a relative path, is omitted: it cannot be
-- mapped to a source line, so the diff-scoped runner has no use for it.
--
-- The most-recent ('head') frame of the 'CallStack' is the
-- @it@\/@prop@\/@specify@ call site, because those combinators use
-- 'withFrozenCallStack' to fix the user's call site as the top frame.
runCoverageListLocationsMode :: Settings -> Spec -> IO ()
runCoverageListLocationsMode sets spec = do
  specForest <- execTestDefM sets spec
  let leaves = flattenTestForestWithIdsAndCallStacks specForest
      locations =
        [ TestLocation
            { testLocationTestId = tid,
              testLocationFile = relFile,
              testLocationLine = fromIntegral (srcLocStartLine srcLoc)
            }
        | (tid, cs) <- leaves,
          (_, srcLoc) : _ <- [getCallStack cs],
          Just relFile <- [parseRelFile (srcLocFile srcLoc)]
        ]
  LB.putStr (encodeTestLocations locations)