@@ -28,18 +28,17 @@ import System.IO.Unsafe (unsafePerformIO)
2828import System.Process
2929import Test.Tasty
3030import Test.Tasty.HUnit
31+import Test.Tasty.Golden.Advanced (goldenTest)
3132import Tests.Helpers
3233import Text.Pandoc
3334import qualified Text.Pandoc.UTF8 as UTF8
3435
35−-- | Run a test with normalize function, return True if test passed.
36−runTest :: String -- ^ Title of test
37− -> FilePath -- ^ Path to pandoc
38− -> String -- ^ Shell command
39− -> String -- ^ Input text
40− -> String -- ^ Expected output
41− -> TestTree
42−runTest testname pandocpath cmd inp norm = testCase testname $ do
36+-- | Run a test with and return output.
37+execTest :: FilePath -- ^ Path to pandoc
38+ -> String -- ^ Shell command
39+ -> String -- ^ Input text
40+ -> IO (ExitCode, String) -- ^ Exit code and actual output
41+execTest pandocpath cmd inp = do
4342 mldpath <- Env.lookupEnv "LD_LIBRARY_PATH"
4443 mdyldpath <- Env.lookupEnv "DYLD_LIBRARY_PATH"
4544 let findDynlibDir [] = Nothing
@@ -47,13 +46,32 @@ runTest testname pandocpath cmd inp norm = testCase testname $ do
4746 findDynlibDir (_:xs) = findDynlibDir xs
4847 let mbDynlibDir = findDynlibDir (reverse $ splitDirectories $
4948 takeDirectory $ takeWhile (/=' ') cmd)
50− let dynlibEnv = [("DYLD_LIBRARY_PATH", intercalate ":" $ catMaybes [mbDynlibDir, mdyldpath])
51− ,("LD_LIBRARY_PATH", intercalate ":" $ catMaybes [mbDynlibDir, mldpath])]
52− let env' = dynlibEnv ++ [("PATH",takeDirectory pandocpath),("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./"),("pandoc_datadir", "..")]
49+ let dynlibEnv = [("DYLD_LIBRARY_PATH",
50+ intercalate ":" $ catMaybes [mbDynlibDir, mdyldpath])
51+ ,("LD_LIBRARY_PATH",
52+ intercalate ":" $ catMaybes [mbDynlibDir, mldpath])]
53+ let env' = dynlibEnv ++ [("PATH",takeDirectory pandocpath),("TMP","."),
54+ ("LANG","en_US.UTF-8"),
55+ ("HOME", "./"),
56+ ("pandoc_datadir", "..")]
5357 let pr = (shell cmd){ env = Just env' }
5458 (ec, out', err') <- readCreateProcessWithExitCode pr inp
5559 -- filter \r so the tests will work on Windows machines
5660 let out = filter (/= '\r') $ err' ++ out'
61+ case ec of
62+ ExitFailure _ -> hPutStr stderr err'
63+ ExitSuccess -> return ()
64+ return (ec, out)
65+
66+-- | Run a test, return True if test passed.
67+runTest :: String -- ^ Title of test
68+ -> FilePath -- ^ Path to pandoc
69+ -> String -- ^ Shell command
70+ -> String -- ^ Input text
71+ -> String -- ^ Expected output
72+ -> TestTree
73+runTest testname pandocpath cmd inp norm = testCase testname $ do
74+ (ec, out) <- execTest pandocpath cmd inp
5775 result <- if ec == ExitSuccess
5876 then
5977 if out == norm
@@ -61,9 +79,7 @@ runTest testname pandocpath cmd inp norm = testCase testname $ do
6179 else return
6280 $ TestFailed cmd "expected"
6381 $ getDiff (lines out) (lines norm)
64− else do
65− hPutStr stderr err'
66− return $ TestError ec
82+ else return $ TestError ec
6783 assertBool (show result) (result == TestPassed)
6884
6985tests :: FilePath -> TestTree
@@ -86,18 +102,34 @@ dropPercent :: String -> String
86102dropPercent ('%':xs) = dropWhile (== ' ') xs
87103dropPercent xs = xs
88104
89−runCommandTest :: FilePath -> Int -> String -> TestTree
90−runCommandTest pandocpath num code =
91− let codelines = lines code
92− (continuations, r1) = span ("\\" `isSuffixOf`) codelines
93− (cmd, r2) = (dropPercent (unwords (map init continuations ++ take 1 r1)),
94− drop 1 r1)
95− (inplines, r3) = break (=="^D") r2
96− normlines = takeWhile (/=".") (drop 1 r3)
97− input = unlines inplines
98− norm = unlines normlines
99− shcmd = cmd -- trimr $ takeDirectory pandocpath </> cmd
100− in runTest ("#" ++ show num) pandocpath shcmd input norm
105+runCommandTest :: FilePath -> FilePath -> Int -> String -> TestTree
106+runCommandTest pandocpath fp num code =
107+ goldenTest testname getExpected getActual compareValues updateGolden
108+ where
109+ testname = "#" <> show num
110+ codelines = lines code
111+ (continuations, r1) = span ("\\" `isSuffixOf`) codelines
112+ cmd = dropPercent (unwords (map init continuations ++ take 1 r1))
113+ r2 = drop 1 r1
114+ (inplines, r3) = break (=="^D") r2
115+ normlines = takeWhile (/=".") (drop 1 r3)
116+ input = unlines inplines
117+ norm = unlines normlines
118+ getExpected = return norm
119+ getActual = snd <$> execTest pandocpath cmd input
120+ compareValues expected actual
121+ | actual == expected = return Nothing
122+ | otherwise = return $ Just $ "--- test/command/" ++ fp ++ "\n+++ " ++
123+ cmd ++ "\n" ++ showDiff (1,1)
124+ (getDiff (lines actual) (lines expected))
125+ updateGolden newnorm = do
126+ let fp' = "command" </> fp
127+ raw <- UTF8.readFile fp'
128+ let cmdline = "% " <> cmd
129+ let x = cmdline <> "\n" <> input <> "^D\n" <> norm
130+ let y = cmdline <> "\n" <> input <> "^D\n" <> newnorm
131+ let updated = T.unpack $ T.replace (T.pack x) (T.pack y) (T.pack raw)
132+ UTF8.writeFile fp' updated
101133
102134extractCommandTest :: FilePath -> FilePath -> TestTree
103135extractCommandTest pandocpath fp = unsafePerformIO $ do
@@ -105,5 +137,5 @@ extractCommandTest pandocpath fp = unsafePerformIO $ do
105137 Pandoc _ blocks <- runIOorExplode (readMarkdown
106138 def{ readerExtensions = pandocExtensions } contents)
107139 let codeblocks = map extractCode $ filter isCodeBlock blocks
108− let cases = zipWith (runCommandTest pandocpath) [1..] codeblocks
140+ let cases = zipWith (runCommandTest pandocpath fp) [1..] codeblocks
109141 return $ testGroup fp cases