{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-} import Text.Printf import System.Exit import qualified Control.Exception as E import Text.Pandoc hiding (writeHtmlString) import Text.CSL.Compat.Pandoc (writeHtmlString) import Data.Char (isSpace, toLower) import System.Environment (getArgs) import System.Process import System.IO.Temp (withSystemTempDirectory) import Text.Pandoc.Definition (Inline(Span, Str)) import qualified Text.Pandoc.UTF8 as UTF8 import Data.Aeson import System.FilePath import System.Directory import Data.List (sort, isInfixOf) import qualified Data.Vector as V import qualified Data.Map as M import Text.CSL.Style hiding (Number) import Text.CSL.Reference import Text.CSL import Control.Monad import qualified Data.ByteString.Lazy as BL data TestCase = TestCase{ testMode :: Mode -- mode , testBibopts :: BibOpts -- bibsection , testCitations :: [CiteObject] -- citations , testCitationItems :: Citations -- citation-items , testCsl :: Style -- csl , testAbbreviations :: Abbreviations -- abbreviations , testReferences :: [Reference] -- input , testResult :: String -- result } deriving (Show) data Mode = CitationMode | BibliographyMode | BibliographyHeaderMode | BibliographyNoSortMode deriving Show instance FromJSON Mode where parseJSON (String "citation") = return CitationMode parseJSON (String "bibliography") = return BibliographyMode parseJSON (String "bibliography-header") = return BibliographyHeaderMode parseJSON (String "bibliography-nosort") = return BibliographyNoSortMode parseJSON _ = fail "Unknown mode" instance FromJSON TestCase where parseJSON (Object v) = TestCase <$> v .: "mode" <*> v .:? "bibsection" .!= Select [] [] <*> v .:? "citations" .!= [] <*> v .:? "citation_items" .!= [] <*> (parseCSL <$> (v .: "csl")) <*> v .:? "abbreviations" .!= (Abbreviations M.empty) <*> v .: "input" <*> v .: "result" parseJSON _ = fail "Could not parse test case" newtype CiteObject = CiteObject { unCiteObject :: [Cite] } deriving Show instance FromJSON CiteObject where parseJSON (Array v) = case fromJSON (Array v) of Success [Object x, Array _, Array _] -> CiteObject <$> x .: "citationItems" Error e -> fail $ "Could not parse CiteObject: " ++ e x -> fail $ "Could not parse CiteObject" ++ show x parseJSON x = fail $ "Could not parse CiteObject " ++ show x instance FromJSON [CiteObject] where parseJSON (Array v) = mapM parseJSON $ V.toList v parseJSON _ = return [] data TestResult = Passed | Skipped | Failed | Errored deriving (Show, Eq) testDir :: FilePath testDir = "citeproc-test" > "processor-tests" > "machines" handler :: FilePath -> E.SomeException -> IO TestResult handler path e = do putStrLn $ "[ERROR] " ++ path ++ "\n" ++ show e return Errored runTest :: FilePath -> IO TestResult runTest path = E.handle (handler path) $ do raw <- BL.readFile path let testCase = either error id $ eitherDecode raw let procOpts' = ProcOpts (testBibopts testCase) False style <- localizeCSL Nothing $ (testCsl testCase) { styleAbbrevs = testAbbreviations testCase } let refs = testReferences testCase let cites = map unCiteObject (testCitations testCase) ++ testCitationItems testCase let cites' = if null cites then [map (\ref -> emptyCite{ citeId = unLiteral $ refId ref}) refs] else cites let expected = adjustEntities $ fixBegins $ trimEnd $ testResult testCase let mode = testMode testCase let assemble BibliographyMode xs = "