123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- {-# LANGUAGE DoAndIfThenElse #-}
- module LaTeXAndHTML.Tests where
- import Control.Monad
- import Data.Char
- import qualified Data.List as List
- import Data.Maybe
- import Data.Text.Encoding
- import qualified Data.ByteString as BS
- import qualified Data.Text as T
- import qualified Network.URI.Encode
- import System.Directory
- import System.Exit
- import System.FilePath
- import System.IO.Temp
- import System.Process
- import qualified System.Process.Text as PT
- import qualified System.Process.ByteString as PB
- import Text.Read (readMaybe)
- import Test.Tasty
- import Test.Tasty.Silver
- import Test.Tasty.Silver.Advanced (readFileMaybe)
- import Test.Tasty.Silver.Filter
- import UserManual.Tests (examplesInUserManual)
- import Utils
- import Agda.Utils.Three
- type LaTeXProg = String
- allLaTeXProgs :: [LaTeXProg]
- allLaTeXProgs = ["pdflatex", "xelatex", "lualatex"]
- testDirPrefix :: FilePath -> FilePath
- testDirPrefix x = "test" </> "LaTeXAndHTML" </> x
- -- Andreas, 2021-01-30
- -- See issue #5140 for the split into these two directories.
- testDirs :: [FilePath]
- testDirs = map testDirPrefix
- [ "fail"
- , "succeed"
- ]
- userManualTestDir :: FilePath
- userManualTestDir = testDirPrefix "user-manual"
- disabledTests :: [RegexFilter]
- disabledTests = []
- -- | Filtering out tests using Text.ICU.
- icuTests :: [RegexFilter]
- icuTests = [ disable "LaTeXAndHTML/.*/Grapheme.*" ]
- where disable = RFInclude
- -- | Filtering out tests using latex.
- latexTests :: [RegexFilter]
- latexTests = [ disable "LaTeXAndHTML/.*LaTeX/.*" ]
- where disable = RFInclude
- -- | Test group with subgroups
- --
- -- @
- -- "LaTeXAndHTML" / [ "HTML" , "LaTeX" , "QuickLaTeX" ]
- -- @.
- --
- tests :: IO TestTree
- tests = do
- agdaBin <- getAgdaBin
- suiteTests <- concat <$> mapM (taggedListOfAllTests agdaBin) testDirs
- let allTests = suiteTests ++ userManualTests agdaBin
- let (html, latex, quicklatex) = (\ f -> partition3 (f . fst) allTests) $ \case
- HTML -> One
- LaTeX -> Two
- QuickLaTeX -> Three
- return $
- testGroup "LaTeXAndHTML"
- [ testGroup "HTML" $ map snd html
- , testGroup "LaTeX" $ map snd latex
- , testGroup "QuickLaTeX" $ map snd quicklatex
- ]
- taggedListOfAllTests :: FilePath -> FilePath -> IO [(Kind, TestTree)]
- taggedListOfAllTests agdaBin testDir = do
- inpFiles <- getAgdaFilesInDir NonRec testDir
- return $
- [ (k, mkLaTeXOrHTMLTest k False agdaBin testDir f)
- | f <- inpFiles
- -- Note that the LaTeX backends are only tested on the @.lagda@
- -- and @.lagda.tex@ files.
- , k <- HTML : concat [ [ LaTeX, QuickLaTeX ]
- | any (`List.isSuffixOf` takeExtensions f)
- [".lagda",".lagda.tex"]
- ]
- ]
- -- See issue #3372 for the origin of these tests.
- -- | These tests do not have a @.lagda[.tex]@ source.
- userManualTests :: FilePath -> [(Kind, TestTree)]
- userManualTests agdaBin =
- [ (k, mkLaTeXOrHTMLTest k True agdaBin userManualTestDir f)
- | f <- examplesInUserManual
- , k <- [LaTeX, QuickLaTeX]
- ]
- data LaTeXResult
- = AgdaFailed ProgramResult
- | LaTeXFailed [LaTeXProg]
- | Success T.Text -- ^ The resulting LaTeX or HTML file.
- data Kind = LaTeX | QuickLaTeX | HTML
- deriving Show
- -- The test output may not be very informative for failing tests. One
- -- can perhaps improve the user experience by switching from
- -- goldenVsAction to something else (see test/Fail/Tests.hs for one
- -- example).
- mkLaTeXOrHTMLTest
- :: Kind
- -> Bool -- ^ Should the file be copied to the temporary test
- -- directory before the test is run?
- -> FilePath -- ^ Agda binary.
- -> FilePath -- ^ Test directory in which input file resides.
- -> FilePath -- ^ Input file.
- -> TestTree
- mkLaTeXOrHTMLTest k copy agdaBin testDir inp =
- goldenVsAction'
- testName
- goldenFile
- (liftM2 (,) getCurrentDirectory doRun)
- (uncurry printLaTeXResult)
- where
- extension = case k of
- LaTeX -> "tex"
- QuickLaTeX -> "quick.tex"
- HTML -> if "MdHighlight" `List.isPrefixOf` inFileName
- then "md"
- else if "RsTHighlight" `List.isPrefixOf` inFileName
- then "rst"
- else if "OrgHighlight" `List.isPrefixOf` inFileName
- then "org"
- else "html"
- flags :: FilePath -> [String]
- flags dir = case k of
- LaTeX -> latexFlags
- QuickLaTeX -> latexFlags ++ ["--only-scope-checking"]
- HTML -> ["--html", "--html-dir=" ++ dir]
- where
- latexFlags = ["--latex", "--latex-dir=" ++ dir]
- inFileName = takeFileName inp
- testName = asTestName testDir inp ++ "_" ++ show k
- baseName = if copy
- then testDir </> dropAgdaExtension inFileName
- else dropAgdaExtension inp
- flagFile = baseName <.> "flags"
- goldenFile = baseName <.> extension
- -- For removing a LaTeX compiler when testing @Foo.lagda@, you can
- -- create a file @Foo.compile@ with the list of the LaTeX compilers
- -- that you want to use (e.g. ["xelatex", "lualatex"]).
- compFile = baseName <.> ".compile"
- outFileName = case k of
- LaTeX -> golden
- HTML -> Network.URI.Encode.encode golden
- QuickLaTeX -> replaceExtension (dropExtension golden) "tex"
- where
- golden = takeFileName goldenFile
- -- Andreas, 2017-04-14, issue #2317
- -- Create temporary files in system temp directory.
- -- This has the advantage that upon Ctrl-C no junk is left behind
- -- in the Agda directory.
- -- doRun = withTempDirectory "." testName $ \outDir -> do
- doRun = withSystemTempDirectory testName $ \outDir -> do
- -- One can give extra options in .flags files (one per line).
- flagFileExists <- doesFileExist flagFile
- extraFlags <- if flagFileExists
- then lines <$> readFile flagFile
- else return []
- let newFile = outDir </> inFileName
- agdaArgs = flags outDir ++
- [ "-i" ++ if copy then outDir else testDir
- , if copy then newFile else inp
- , "--ignore-interfaces"
- , "--no-libraries"
- ] ++ extraFlags
- when copy $ copyFile inp newFile
- (exitcode, out, err) <- PT.readProcessWithExitCode agdaBin agdaArgs T.empty
- if exitcode /= ExitSuccess then
- AgdaFailed <$> do
- ProgramResult exitcode
- <$> cleanOutput out
- <*> cleanOutput err
- else do
- output <- decodeUtf8 <$> BS.readFile (outDir </> outFileName)
- let done = return $ Success output
- compile = do
- rl <- doesEnvContain "DONT_RUN_LATEX"
- if rl
- then done
- else do
- -- read compile options
- doCompile <- readFileMaybe compFile
- case doCompile of
- -- there is no compile file, so we run all the LaTeX compilers
- Nothing -> foldl (runLaTeX outFileName outDir) done allLaTeXProgs
- -- there is a compile file, check it's content
- Just content -> do
- let latexProgs =
- fromMaybe allLaTeXProgs
- (readMaybe $ T.unpack $ decodeUtf8 content)
- -- run the selected LaTeX compilers
- foldl (runLaTeX outFileName outDir) done latexProgs
- case k of
- HTML -> done
- LaTeX -> compile
- QuickLaTeX -> compile
- runLaTeX :: FilePath -- tex file
- -> FilePath -- working dir
- -> IO LaTeXResult -- continuation
- -> LaTeXProg
- -> IO LaTeXResult
- runLaTeX texFile wd cont prog = do
- let proc' = (proc prog ["-interaction=errorstopmode", texFile]) { cwd = Just wd }
- (ret, _, _) <- PB.readCreateProcessWithExitCode proc' BS.empty
- if ret == ExitSuccess then
- cont
- else do
- r <- cont
- return $ case r of
- LaTeXFailed progs -> LaTeXFailed (prog : progs)
- _ -> LaTeXFailed [prog]
- printLaTeXResult
- :: FilePath -- ^ The current working directory.
- -> LaTeXResult
- -> T.Text
- printLaTeXResult dir r = case r of
- Success t -> t
- AgdaFailed p -> "AGDA_COMPILE_FAILED\n\n"
- `T.append`
- mangle (printProgramResult p)
- LaTeXFailed progs -> "LATEX_COMPILE_FAILED with "
- `T.append`
- T.intercalate ", " (map T.pack progs)
- where
- -- Tries to make the resulting string more platform-independent.
- mangle = T.unwords . T.words . removeCWD
- removeCWD
- | null dir = id
- | otherwise = T.concat . T.splitOn (T.pack dir)
|