-- Print tests in any of the supported formats.
-- Useful for debugging and for migrating between formats.
-- Issues:
-- converting v1 -> v2/v3
-- a >>>= 0 often gets converted to a >>>2 // or >2 //, when >= or nothing would be preferred (but semantically less accurate, therefore risky to choose automatically)
-- converting v3 -> v3
-- loses comments at the top of the file, even above an explicit < delimiter
-- may lose other data
module Print
where
import Safe (lastMay)
import Import
import Types
-- | Print a shell test. See CLI documentation for details.
-- For v3 (the preferred, lightweight format), avoid printing most unnecessary things
-- (stdout delimiter, 0 exit status value).
printShellTest
:: String -- ^ Shelltest format. Value of option @--print[=FORMAT]@.
-> ShellTest -- ^ Test to print
-> IO ()
printShellTest format ShellTest{command=c,stdin=i,comments=comments,trailingComments=trailingComments,
stdoutExpected=o_expected,stderrExpected=e_expected,exitCodeExpected=x_expected}
= do
case format of
"v1" -> do
printComments comments
printCommand "" c
printStdin "<<<" i
printStdouterr False ">>>" o_expected
printStdouterr False ">>>2" e_expected
printExitStatus True True ">>>=" x_expected
printComments trailingComments
"v2" -> do
printComments comments
printStdin "<<<" i
printCommand "$$$ " c
printStdouterr True ">>>" o_expected
printStdouterr True ">>>2" e_expected
printExitStatus trailingblanklines True ">>>=" x_expected
printComments trailingComments
"v3" -> do
printComments comments
printStdin "<" i
printCommand "$ " c
printStdouterr True ">" o_expected
printStdouterr True ">2" e_expected
printExitStatus trailingblanklines False ">=" x_expected
printComments trailingComments
_ -> fail $ "Unsupported --print format: " ++ format
where
trailingblanklines = case (o_expected, e_expected) of
(Just (Lines _ o), Just (Lines _ e)) -> hasblanks $ if null e then o else e
_ -> False
where hasblanks s = maybe False null $ lastMay $ lines s
printComments :: [String] -> IO ()
printComments = mapM_ putStrLn
printStdin :: String -> Maybe String -> IO ()
printStdin _ (Just "") = return ()
printStdin _ Nothing = return ()
printStdin prefix (Just s) = printf "%s\n%s" prefix s
printCommand :: String -> TestCommand -> IO ()
printCommand prefix (ReplaceableCommand s) = printf "%s%s\n" prefix s
printCommand prefix (FixedCommand s) = printf "%s %s\n" prefix s
-- Print an expected stdout or stderr test, prefixed with the given delimiter.
-- If no expected value is specified, print nothing if first argument is true
-- (for format 1, which ignores unspecified out/err), otherwise print a dummy test.
printStdouterr :: Bool -> String -> Maybe Matcher -> IO ()
printStdouterr alwaystest prefix Nothing = when alwaystest $ printf "%s //\n" prefix
printStdouterr _ _ (Just (Lines _ "")) = return ()
printStdouterr _ _ (Just (Numeric _)) = fail "FATAL: Cannot handle Matcher (Numeric) for stdout/stderr."
printStdouterr _ _ (Just (NegativeNumeric _)) = fail "FATAL: Cannot handle Matcher (NegativeNumeric) for stdout/stderr."
printStdouterr _ prefix (Just (Lines _ s)) | prefix==">" = printf "%s" s -- omit v3's > delimiter, really no need for it
printStdouterr _ prefix (Just (Lines _ s)) = printf "%s\n%s" prefix s
printStdouterr _ prefix (Just regex) = printf "%s %s\n" prefix (show regex)
-- | Print an expected exit status clause, prefixed with the given delimiter.
-- If zero is expected:
-- if the first argument is not true, nothing will be printed;
-- otherwise if the second argument is not true, only the delimiter will be printed.
printExitStatus :: Bool -> Bool -> String -> Matcher -> IO ()
printExitStatus _ _ _ (Lines _ _) = fail "FATAL: Cannot handle Matcher (Lines) for exit status."
printExitStatus always showzero prefix (Numeric "0") = when always $ printf "%s %s\n" prefix (if showzero then "0" else "")
printExitStatus _ _ prefix s = printf "%s %s\n" prefix (show s)