packages feed

setdown-0.2.1.0: test/GoldenTests.hs

module Main where

import Test.Tasty
import Test.Tasty.Golden
import Test.Tasty.HUnit
import System.FilePath      ((</>))
import System.Process       (callProcess, readProcessWithExitCode)
import System.Exit          (ExitCode(..))
import Data.List            (isInfixOf)

main :: IO ()
main = defaultMain tests

tests :: TestTree
tests = testGroup "setdown golden tests"
   [ goldenTest "intersection"
   , goldenTest "union"
   , goldenTest "difference"
   , goldenTest "symmetric-difference"
   , goldenTest "single-element-distinct"
   , goldenTest "single-element-identical"
   , errorDetectionTests
   ]

-- | Run setdown on a fixture directory and compare the Result.txt output
-- against the committed golden file.
--
-- Each fixture lives under test/golden/<name>/ and contains:
--   a.txt, b.txt        – input files
--   example.setdown     – the definitions file (references a.txt and b.txt)
--   golden/Result.txt   – the committed expected output
--
-- setdown writes its result to test/golden/<name>/output/Result.txt,
-- which is what tasty-golden compares against the golden file.
--
-- To regenerate golden files after an intentional change:
--   stack test setdown:setdown-golden-tests --test-arguments=--accept
goldenTest :: String -> TestTree
goldenTest name =
   goldenVsFile
      name
      (fixtureDir </> "golden" </> "Result.txt")   -- expected (committed)
      (fixtureDir </> "output" </> "Result.txt")   -- actual (generated)
      (runSetdown (fixtureDir </> "example.setdown"))
   where
      fixtureDir = "test" </> "golden" </> name

runSetdown :: FilePath -> IO ()
runSetdown inputFile =
   callProcess "stack" ["exec", "--", "setdown", "-i", inputFile]

-- ---------------------------------------------------------------------------
-- Error detection (CLI integration)
-- ---------------------------------------------------------------------------

-- | Each fixture lives under test/golden/errors/<name>/example.setdown and is
-- expected to make setdown exit with a specific failure code, printing a
-- message containing the given fragment. There is no golden output file
-- here, since setdown exits before writing any results.
errorDetectionTests :: TestTree
errorDetectionTests = testGroup "error detection"
   [ errorTest "duplicate-definition" 11 "Duplicate definitions found"
   , errorTest "unknown-identifier"   12 "Unknown identifiers used"
   , errorTest "missing-file"         13 "the following files could not be found"
   ]

errorTest :: String -> Int -> String -> TestTree
errorTest name expectedCode expectedFragment =
   testCase name $ do
      (exitCode, stdout, _stderr) <- readProcessWithExitCode "stack"
         ["exec", "--", "setdown", "-i", fixtureDir </> "example.setdown"]
         ""
      exitCode @?= ExitFailure expectedCode
      assertBool
         ("expected stdout to mention \"" ++ expectedFragment ++ "\", got:\n" ++ stdout)
         (expectedFragment `isInfixOf` stdout)
   where
      fixtureDir = "test" </> "golden" </> "errors" </> name