module Runner.Example (
Result (..)
, mkResult
) where
import Data.Char
import Data.List
import Util
import Parse
data Result = Equal | NotEqual [String]
deriving (Eq, Show)
mkResult :: ExpectedResult -> [String] -> Result
mkResult expected actual
| expected `matches` actual = Equal
| otherwise = NotEqual (formatNotEqual expected actual)
where
chunksMatch :: [LineChunk] -> String -> Bool
chunksMatch [] "" = True
chunksMatch [LineChunk xs] ys = stripEnd xs == stripEnd ys
chunksMatch (LineChunk x : xs) ys =
x `isPrefixOf` ys && xs `chunksMatch` drop (length x) ys
chunksMatch zs@(WildCardChunk : xs) (_:ys) =
xs `chunksMatch` ys || zs `chunksMatch` ys
chunksMatch _ _ = False
matches :: ExpectedResult -> [String] -> Bool
matches (ExpectedLine x : xs) (y : ys) = x `chunksMatch` y && xs `matches` ys
matches (WildCardLine : xs) ys | xs `matches` ys = True
matches zs@(WildCardLine : _) (_ : ys) = zs `matches` ys
matches [] [] = True
matches [] _ = False
matches _ [] = False
formatNotEqual :: ExpectedResult -> [String] -> [String]
formatNotEqual expected_ actual = formatLines "expected: " expected ++ formatLines " but got: " actual
where
expected :: [String]
expected = map (\x -> case x of
ExpectedLine str -> concatMap lineChunkToString str
WildCardLine -> "..." ) expected_
escapeOutput
| any (not . isSafe) (concat $ expected ++ actual) = map show
| otherwise = id
isSafe :: Char -> Bool
isSafe c = c == ' ' || (isPrint c && (not . isSpace) c)
formatLines :: String -> [String] -> [String]
formatLines message xs = case escapeOutput xs of
y:ys -> (message ++ y) : map (padding ++) ys
[] -> [message]
where
padding = replicate (length message) ' '
lineChunkToString :: LineChunk -> String
lineChunkToString WildCardChunk = "..."
lineChunkToString (LineChunk str) = str