packages feed

vintage-basic-1.0: test/Language/VintageBasic/Asserts.hs

module Language.VintageBasic.Asserts where

import Data.IORef
import Data.List(isInfixOf)
import Test.HUnit
import Text.ParserCombinators.Parsec(eof,parse,sourceLine,sourceColumn,(<?>))
import Language.VintageBasic.LexCommon
import IO.IOStream

-- | Make an input stream for testing.
mkInput :: String -> IO IOStream
mkInput s = do
    input <- newIORef s
    return $ IOStream input

-- | Make an empty input stream for testing.
noInput :: IO IOStream
noInput = mkInput ""

-- | Make an empty output stream for testing.
mkOutput :: IO IOStream
mkOutput = do
    output <- newIORef ""
    return $ IOStream output

-- | Assert the output of a program, with empty input.
assertOutputEq output expected = do
    got <- vGetContents output
    assertEqual "Output not as expected" expected got

-- | Extracts line number and token from tagged tokens. Useful for asserting these when you don't care about column number.
withCol taggedToks = [(sourceColumn pos, tok) | (Tagged pos tok) <- taggedToks]

-- | Extracts line number, column number, and token from tagged tokens. Useful for assertion position and token value.
withLineAndCol taggedToks = [(sourceLine pos, sourceColumn pos, tok) | (Tagged pos tok) <- taggedToks]

-- | A parser that wraps a check for end of input around another parser.
-- Useful when checking isolated expressions that don't normally reach end of input.
parserWithEof parser = do
    result <- parser
    eof <?> "END OF INPUT"
    return result

-- | Assert a parse result, expecting success.
assertParseResult normalizeResult normalizeError parser input expected = do
    case parse (parserWithEof parser) "" input of
        (Left err) -> assertFailure ("Parse error: " ++ show (normalizeError err))
        (Right rls) -> assertEqual "Parse result not as expected" expected (normalizeResult rls)

-- | Assert an expected parse error.
assertParseError normalizeResult normalizeError parser input expected = do
    case parse (parserWithEof parser) "" input of
        (Left err) -> assertBool
            ("Parser reported wrong error.\n\nGot:\n" ++ show (normalizeError err) ++ "\n\nExpected error to contain:\n" ++ expected)
            (isInfixOf expected (show (normalizeError err)))
        (Right rls) -> assertFailure ("Parser didn't report error, instead got result: " ++ show (normalizeResult rls))