{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-} import JSON import Text.Printf import System.Exit import qualified Control.Exception as E import Text.Pandoc 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 Text.Pandoc.Generic import Text.Pandoc.Walk import Data.Maybe (mapMaybe) import Data.Aeson import Data.Aeson.Types (Parser) import System.FilePath import System.Directory import Data.List (intercalate, sort, isInfixOf) import qualified Data.Vector as V import qualified Data.Map as M import qualified Data.Text as T import qualified Data.Text.Encoding as T import Text.CSL.Style hiding (Number) import Text.CSL.Reference import Text.CSL import Control.Monad import Control.Applicative 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" .!= [] <*> 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" handleError :: FilePath -> E.SomeException -> IO TestResult handleError path e = do putStrLn $ "[ERROR] " ++ path ++ "\n" ++ show e return Errored runTest :: FilePath -> IO TestResult runTest path = E.handle (handleError path) $ do raw <- BL.readFile path let testCase = either error id $ eitherDecode raw let procOpts = ProcOpts (testBibopts testCase) 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 = "