module Tests.Command (findPandoc, runTest, tests) where import Data.Algorithm.Diff import Data.List (isSuffixOf) import Prelude hiding (readFile) import System.Directory import System.Exit import System.FilePath (joinPath, splitDirectories, takeDirectory, ()) import System.Process import Test.Framework import Test.Framework.Providers.HUnit import Test.HUnit (assertBool) import Tests.Helpers import Text.Pandoc import Text.Pandoc.Shared (trimr) import qualified Text.Pandoc.UTF8 as UTF8 -- | Run a test with normalize function, return True if test passed. runTest :: String -- ^ Title of test -> String -- ^ Shell command -> String -- ^ Input text -> String -- ^ Expected output -> Test runTest testname cmd inp norm = testCase testname $ do let cmd' = cmd ++ " --quiet --data-dir ../data" let findDynlibDir [] = Nothing findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) "build" findDynlibDir (_:xs) = findDynlibDir xs let mbDynlibDir = findDynlibDir (reverse $ splitDirectories $ takeDirectory $ takeWhile (/=' ') cmd) let dynlibEnv = case mbDynlibDir of Nothing -> [] Just d -> [("DYLD_LIBRARY_PATH", d), ("LD_LIBRARY_PATH", d)] let env' = dynlibEnv ++ [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./")] let pr = (shell cmd'){ env = Just env' } (ec, out', _err) <- readCreateProcessWithExitCode pr inp -- filter \r so the tests will work on Windows machines let out = filter (/= '\r') out' result <- if ec == ExitSuccess then do if out == norm then return TestPassed else return $ TestFailed cmd "expected" $ getDiff (lines out) (lines norm) else return $ TestError ec assertBool (show result) (result == TestPassed) tests :: Test tests = buildTest $ do files <- filter (".md" `isSuffixOf`) <$> getDirectoryContents "command" let cmds = map extractCommandTest files return $ testGroup "Command:" cmds isCodeBlock :: Block -> Bool isCodeBlock (CodeBlock _ _) = True isCodeBlock _ = False extractCode :: Block -> String extractCode (CodeBlock _ code) = code extractCode _ = "" dropPercent :: String -> String dropPercent ('%':xs) = dropWhile (== ' ') xs dropPercent xs = xs runCommandTest :: FilePath -> (Int, String) -> IO Test runCommandTest pandocpath (num, code) = do let codelines = lines code let (continuations, r1) = span ("\\" `isSuffixOf`) codelines let (cmd, r2) = (dropPercent (unwords (map init continuations ++ take 1 r1)), drop 1 r1) let (inplines, r3) = break (=="^D") r2 let normlines = takeWhile (/=".") (drop 1 r3) let input = unlines inplines let norm = unlines normlines let shcmd = trimr $ takeDirectory pandocpath cmd return $ runTest ("#" ++ show num) shcmd input norm extractCommandTest :: FilePath -> Test extractCommandTest fp = buildTest $ do pandocpath <- findPandoc contents <- UTF8.readFile ("command" fp) Pandoc _ blocks <- runIOorExplode (readMarkdown def{ readerExtensions = pandocExtensions } contents) let codeblocks = map extractCode $ filter isCodeBlock $ blocks cases <- mapM (runCommandTest pandocpath) $ zip [1..] codeblocks return $ testGroup fp cases