packages feed

heni-0.1.0.0: test/unit/Main.hs

module Main (main) where

import Consumer
import Control.Monad (forM_, unless)
import Data.Set qualified as Set
import Data.Text qualified
import Labels (labelWorks)
import Test.Heni

assert :: String -> Bool -> IO ()
assert name condition = unless condition (error name)

buildOk :: StageEvidence
buildOk = stageEvidence Build (Exited 0) ""

stageEvidence :: Stage -> ProcessOutcome -> String -> StageEvidence
stageEvidence s o text = StageEvidence s o (fromString text) False unknownSelection Nothing 0 []
  where
    fromString = Data.Text.pack

namedFailure :: StageEvidence
namedFailure =
  StageEvidence
    Test
    (Exited 1)
    ""
    False
    (SelectionEvidence (Just 1) (Just 1) (Just 1) intended intended Set.empty [])
    Nothing
    0
    []

intended :: Set.Set Data.Text.Text
intended = Set.singleton "rejects full capacity"

observations :: [StageEvidence] -> CaseEvidence
observations ss = CaseEvidence BaselinePassed Changed ss [] [] Nothing

verdictOf :: CaseDefinition -> CaseEvidence -> Verdict
verdictOf c e = case classifyCase c e of CaseResult {verdict} -> verdict

withSelection :: SelectionEvidence -> StageEvidence -> StageEvidence
withSelection sel (StageEvidence s o txt tr _ r d logs) = StageEvidence s o txt tr sel r d logs

withReplay :: ReplayEvidence -> StageEvidence -> StageEvidence
withReplay r (StageEvidence s o txt tr sel _ d logs) = StageEvidence s o txt tr sel (Just r) d logs

main :: IO ()
main = do
  assert "own label instance" labelWorks
  forM_ definitions (\c -> assert "public construction" (validateCase c == Right ()))
  let matching = observations [buildOk, namedFailure]
      wrongNamed =
        withSelection
          ( SelectionEvidence
              (Just 2)
              (Just 2)
              (Just 2)
              (Set.insert "unrelated" intended)
              (Set.singleton "unrelated")
              Set.empty
              []
          )
          namedFailure
      extraNamed =
        withSelection
          ( SelectionEvidence
              (Just 2)
              (Just 2)
              (Just 2)
              (Set.insert "unrelated" intended)
              (Set.insert "unrelated" intended)
              Set.empty
              []
          )
          namedFailure
      zero = withSelection (SelectionEvidence (Just 1) (Just 0) (Just 0) Set.empty Set.empty intended []) namedFailure
      setup = withSelection (SelectionEvidence (Just 1) (Just 1) (Just 1) intended intended Set.empty ["fixture setup failed"]) namedFailure
      testDiag = stageEvidence Test (Exited 1) "capacity rule violated"
      baselineFailed = CaseEvidence (BaselineFailed "unchanged test failed") Changed [] [] [] Nothing
      replayInfo = ReplayEvidence "seed:42" "size=20" intended
      replayStage = withReplay replayInfo (case namedFailure of StageEvidence _ o txt tr sel r d logs -> StageEvidence Replay o txt tr sel r d logs)
      replayMismatch = withReplay (ReplayEvidence "seed:43" "size=20" intended) replayStage
      scenarios =
        [ ("correct named failure", namedCase, matching, Caught),
          ("wrong named failure", namedCase, observations [buildOk, wrongNamed], WrongFailure),
          ("extra named failure", namedCase, observations [buildOk, extraNamed], WrongFailure),
          ("wrong exit", diagnosticCase, observations [buildOk, stageEvidence Test (Exited 2) "capacity rule violated"], WrongFailure),
          ("diagnostic before timeout", diagnosticCase, observations [buildOk, stageEvidence Test Timeout "capacity rule violated"], TimedOut),
          ("zero tests", namedCase, observations [buildOk, zero], Uncovered),
          ("unknown counts", namedCase, observations [buildOk, testDiag], Uncovered),
          ("skipped intended test", namedCase, observations [buildOk, zero], Uncovered),
          ("semantic compile failure", namedCase, observations [stageEvidence Build (Exited 1) "compile error"], UnexpectedBuildFailure),
          ("intentional compile rejection", buildCase, observations [stageEvidence Build (Exited 1) "unbound variable"], Caught),
          ("unrelated compile rejection", buildCase, observations [stageEvidence Build (Exited 1) "missing package"], WrongFailure),
          ("stale edit", namedCase, CaseEvidence BaselinePassed (EditRejected "anchor missing") [] [] [] Nothing, InvalidMutation),
          ("no-op edit", namedCase, CaseEvidence BaselinePassed Unchanged [] [] [] Nothing, InvalidMutation),
          ("baseline failure", namedCase, baselineFailed, NotRun),
          ("setup failure with named witness", namedCase, observations [buildOk, setup], InfrastructureError),
          ("cleanup failure with named witness", namedCase, CaseEvidence BaselinePassed Changed [buildOk, namedFailure] [] ["reset failed"] Nothing, InfrastructureError),
          ("crash without probe", crashCase, observations [buildOk, stageEvidence Test (Signaled 6) ""], WrongFailure),
          ("crash with probe", crashCase, observations [buildOk, stageEvidence Test (Signaled 6) "capacity-probe: native operation reached"], Caught),
          ("runner kill cannot be crash", crashCase, observations [buildOk, stageEvidence Test Timeout "capacity-probe: native operation reached"], TimedOut),
          ("missing replay", replayCase, matching, WrongFailure),
          ("matching replay", replayCase, observations [buildOk, withReplay replayInfo namedFailure, replayStage], Caught),
          ("replay identity mismatch", replayCase, observations [buildOk, withReplay replayInfo namedFailure, replayMismatch], WrongFailure),
          ("duplicate stage", namedCase, observations [buildOk, namedFailure, namedFailure], InfrastructureError),
          ("diagnostic detection", diagnosticCase, observations [buildOk, testDiag], Caught),
          ("survivor", diagnosticCase, observations [buildOk, stageEvidence Test (Exited 0) ""], Survived),
          ("passing control", controlCase, CaseEvidence BaselinePassed Unchanged [buildOk, stageEvidence Test (Exited 0) ""] [] [] Nothing, Caught),
          ("failing control", controlCase, CaseEvidence BaselinePassed Unchanged [buildOk, testDiag] [] [] Nothing, WrongFailure),
          ("truncated witness", diagnosticCase, observations [buildOk, StageEvidence Test (Exited 1) "capacity rule violated" True unknownSelection Nothing 0 []], InfrastructureError)
        ]
  forM_ scenarios $ \(name, c, e, expected) -> assert (name ++ ": " ++ show (classifyCase c e)) (verdictOf c e == expected)
  let checked = either (error . show) id
      i = case namedCase of CaseDefinition {caseId} -> caseId
      selected = checked (mkSelectedCases [i])
      result = classifyCase namedCase matching
      summary = checked (summarizeRun selected [result] [])
  assert "duplicate results rejected" (case summarizeRun selected [result, result] [] of Left _ -> True; _ -> False)
  assert "missing result accounted" (case checked (summarizeRun selected [] []) of RunResult {results = [CaseResult {verdict = NotRun}]} -> True; _ -> False)
  assert "single semantic score" (case summary of RunResult {score = Just (SemanticScore 1 1 True), status = RunPassed} -> True; _ -> False)
  assert "baseline becomes run failure" (case checked (summarizeRun selected [classifyCase namedCase baselineFailed] []) of RunResult {failures = [BaselineFailure {}], status = RunFailed} -> True; _ -> False)
  assert "control becomes run failure" (case checked (summarizeRun selected [classifyCase controlCase (CaseEvidence BaselinePassed Unchanged [buildOk, testDiag] [] [] Nothing)] []) of RunResult {failures = [ControlFailure {}]} -> True; _ -> False)
  assert "zero denominator" (case checked (summarizeRun selected [classifyCase buildCase (observations [stageEvidence Build (Exited 1) "unbound variable"])] []) of RunResult {score = Nothing} -> True; _ -> False)
  assert "infrastructure precedence" (case checked (summarizeRun selected [classifyCase diagnosticCase (observations [buildOk, stageEvidence Test (Exited 0) ""])] [RunInfrastructure "report failed"]) of RunResult {status = RunUntrustworthy} -> True; _ -> False)
  forM_ ["", "/absolute", "../escape", "a/../b", "a//b", "C:drive", "a\\b", "a/./b"] $ \p ->
    assert ("reject path " ++ p) (case mkRelativeTarget p of Left _ -> True; _ -> False)
  assert "budget zero rejected" (case mkStageBudget 0 of Left _ -> True; _ -> False)
  assert "empty selection rejected" (case mkSelectedCases [] of Left _ -> True; _ -> False)
  assert "duplicate selection rejected" (case mkSelectedCases [i, i] of Left _ -> True; _ -> False)
  -- Every permutation of unique stage evidence classifies identically; duplication
  -- is a protocol error rather than an inflated count.
  assert "stage reordering" (verdictOf namedCase (observations [namedFailure, buildOk]) == Caught)
  putStrLn (show (length scenarios) ++ " classifier scenarios and ledger/API invariants passed")