pandoc-citeproc-0.17: tests/test-pandoc-citeproc.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Prelude
import qualified Data.Aeson as Aeson
import qualified Data.ByteString as B
import Data.List (isSuffixOf)
import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Text as T
import Data.Maybe (fromMaybe)
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO
import System.IO.Temp (withSystemTempDirectory)
import System.Process (rawSystem)
import Text.CSL.Compat.Pandoc (pipeProcess, writeNative)
import Text.Pandoc.Definition
import qualified Text.Pandoc.UTF8 as UTF8
#if MIN_VERSION_pandoc(2,0,0)
import qualified Control.Exception as E
#endif
main :: IO ()
main = do
args <- getArgs
let regenerate = "--accept" `elem` args
testnames <- (map (dropExtension . takeBaseName) .
filter (".in.native" `isSuffixOf`)) <$>
getDirectoryContents "tests"
citeprocTests <- mapM (testCase regenerate) testnames
fs <- filter (\f -> takeExtension f `elem` [".bibtex",".biblatex"])
`fmap` getDirectoryContents "tests/biblio2yaml"
biblio2yamlTests <- mapM (biblio2yamlTest regenerate) fs
let allTests = citeprocTests ++ biblio2yamlTests
let numpasses = length $ filter (== Passed) allTests
let numskipped = length $ filter (== Skipped) allTests
let numfailures = length $ filter (== Failed) allTests
let numerrors = length $ filter (== Errored) allTests
putStrLn $ show numpasses ++ " passed; " ++ show numfailures ++
" failed; " ++ show numskipped ++ " skipped; " ++
show numerrors ++ " errored."
exitWith $ if numfailures == 0 && numerrors == 0
then ExitSuccess
else ExitFailure $ numfailures + numerrors
err :: String -> IO ()
err = hPutStrLn stderr
data TestResult =
Passed
| Skipped
| Failed
| Errored
deriving (Show, Eq)
testCase :: Bool -> String -> IO TestResult
testCase regenerate csl = do
hPutStr stderr $ "[" ++ csl ++ ".in.native] "
indataNative <- UTF8.readFile $ "tests/" ++ csl ++ ".in.native"
expectedNative <- UTF8.readFile $ "tests/" ++ csl ++ ".expected.native"
let jsonIn = Aeson.encode (read indataNative :: Pandoc)
let expectedDoc = read expectedNative
testProgPath <- getExecutablePath
let pandocCiteprocPath = takeDirectory testProgPath </> ".." </>
"pandoc-citeproc" </> "pandoc-citeproc"
(ec, jsonOut) <- pipeProcess
(Just [("LANG","en_US.UTF-8"),("HOME",".")])
pandocCiteprocPath
[] jsonIn
if ec == ExitSuccess
then do
let outDoc = fromMaybe mempty $Aeson.decode jsonOut
if outDoc == expectedDoc
then err "PASSED" >> return Passed
else
if regenerate
then do
B.writeFile ("tests/" ++ csl ++ ".expected.native") $
encodeUtf8 (writeNative outDoc)
err "PASSED (accepted)"
return Passed
else do
err "FAILED"
showDiff (writeNative expectedDoc) (writeNative outDoc)
return Failed
else do
err "ERROR"
err $ "Error status " ++ show ec
return Errored
showDiff :: Text -> Text -> IO ()
showDiff expected result =
withSystemTempDirectory "test-pandoc-citeproc-XXX" $ \fp -> do
let expectedf = fp </> "expected"
let actualf = fp </> "actual"
UTF8.writeFile expectedf $ T.unpack expected
UTF8.writeFile actualf $ T.unpack result
oldDir <- getCurrentDirectory
setCurrentDirectory fp
_ <- rawSystem "diff" ["-U1","expected","actual"]
setCurrentDirectory oldDir
biblio2yamlTest :: Bool -> String -> IO TestResult
biblio2yamlTest regenerate fp = do
hPutStr stderr $ "[biblio2yaml/" ++ fp ++ "] "
let yamld = "tests/biblio2yaml/"
#if MIN_VERSION_pandoc(2,0,0)
-- in a few cases we need different test output for pandoc >= 2
-- because smallcaps render differently, for example.
raw <- E.catch (UTF8.readFile (yamld ++ "/pandoc-2/" ++ fp))
(\(_ :: E.SomeException) ->
(UTF8.readFile (yamld ++ fp)))
#else
raw <- UTF8.readFile (yamld ++ fp)
#endif
let yamlStart = "---"
let (biblines, yamllines) = break (== yamlStart) $ lines raw
let bib = unlines biblines
let expected = unlines yamllines
testProgPath <- getExecutablePath
let pandocCiteprocPath = takeDirectory testProgPath </> ".." </>
"pandoc-citeproc" </> "pandoc-citeproc"
(ec, result') <- pipeProcess
(Just [("LANG","en_US.UTF-8"),("HOME",".")])
pandocCiteprocPath
["--bib2yaml", "-f", drop 1 $ takeExtension fp,
"--columns=0"]
(UTF8.fromStringLazy bib)
let result = UTF8.toStringLazy result'
if ec == ExitSuccess
then do
if expected == result
then err "PASSED" >> return Passed
else
if regenerate
then do
let accepted = bib ++ result
#if MIN_VERSION_pandoc(2,0,0)
p2version <- doesFileExist (yamld ++ "/pandoc-2/" ++ fp)
UTF8.writeFile (if p2version
then (yamld ++ "/pandoc-2/" ++ fp)
else (yamld ++ fp)) accepted
#else
UTF8.writeFile (yamld ++ fp) accepted
#endif
err "PASSED (accepted)"
return Passed
else do
err "FAILED"
showDiff (T.pack expected) (T.pack result)
return Failed
else do
err "ERROR"
err $ "Error status " ++ show ec
return Errored