module Assertion(Assertion(..),
checkAssertion,
seqStrActions,writeAssertResult,
ProtocolMsg(..),
showTestMod,showTestCase,showTestEnd,showTestCompileError)
where
import AllSolutions
import List((\\))
import Ports
infixl 1 `seqStrActions`
data Assertion a = AssertTrue String Bool
| AssertEqual String a a
| AssertValues String a [a]
| AssertSolutions String (a->Success) [a]
| AssertIO String (IO a) a
| AssertEqualIO String (IO a) (IO a)
seqStrActions :: IO (String,Bool) -> IO (String,Bool) -> IO (String,Bool)
seqStrActions a1 a2 =
do (s1,b1) <- a1
(s2,b2) <- a2
return (s1++s2,b1&&b2)
checkAssertion :: ((String,Bool) -> IO (String,Bool)) -> Assertion _
-> IO (String,Bool)
checkAssertion prot (AssertTrue name cond) =
catchFail (checkAssertTrue name cond)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertion prot (AssertEqual name call result) =
catchFail (checkAssertEqual name call result)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertion prot (AssertValues name expr results) =
catchFail (checkAssertValues name expr results)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertion prot (AssertSolutions name constr results) =
catchFail (checkAssertSolutions name constr results)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertion prot (AssertIO name action result) =
catchFail (checkAssertIO name action result)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertion prot (AssertEqualIO name action1 action2) =
catchFail (checkAssertEqualIO name action1 action2)
(return ("FAILURE of "++name++": no solution or error\n",False))
>>= prot
checkAssertTrue :: String -> Bool -> IO (String,Bool)
checkAssertTrue name cond =
if cond
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": assertion not satisfied\n",False)
checkAssertEqual :: String -> a -> a -> IO (String,Bool)
checkAssertEqual name call result = do
let r = call
if r==result
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": equality assertion not satisfied:\n"++
"Computed answer: "++show r++"\n"++
"Expected answer: "++show result++"\n",False)
checkAssertValues :: String -> a -> [a] -> IO (String,Bool)
checkAssertValues name call results = do
rs <- getAllValues call
if null (rs \\ results) && null (results \\ rs)
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": values assertion not satisfied:\n"++
"Computed values: "++show rs++"\n"++
"Expected values: "++show results++"\n",False)
checkAssertSolutions :: String -> (a->Success) -> [a] -> IO (String,Bool)
checkAssertSolutions name constr results = do
rs <- getAllSolutions constr
if null (rs \\ results) && null (results \\ rs)
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": solutions assertion not satisfied:\n"++
"Computed values: "++show rs++"\n"++
"Expected values: "++show results++"\n",False)
checkAssertIO :: String -> IO a -> a -> IO (String,Bool)
checkAssertIO name action result = do
r <- action
if r==result
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": IO assertion not satisfied:\n"++
"Computed answer: "++show r++"\n"++
"Expected answer: "++show result++"\n\n",False)
checkAssertEqualIO :: String -> IO a -> IO a -> IO (String,Bool)
checkAssertEqualIO name action1 action2 = do
r1 <- action1
r2 <- action2
if r1==r2
then return ("OK: "++name++"\n",True)
else return ("FAILURE of "++name++": IO equality assertion not satisfied:\n"++
"Computed answer 1: "++show r1++"\n"++
"Computed answer 2: "++show r2++"\n\n",False)
writeAssertResult :: (String,Bool) -> IO ()
writeAssertResult (result,flag) =
if flag
then putStrLn (result++"All tests successfully passed.")
else putStrLn (result++"FAILURE occurred in some assertions!\n")
data ProtocolMsg = TestModule String | TestCase String Bool | TestFinished
| TestCompileError
showTestMod :: String -> String -> IO ()
showTestMod portname modname = sendToLocalPort portname (TestModule modname)
showTestCase :: String -> (String,Bool) -> IO (String,Bool)
showTestCase portname (s,b) = do
sendToLocalPort portname (TestCase s b)
return (s,b)
showTestEnd :: String -> IO ()
showTestEnd portname = sendToLocalPort portname TestFinished
showTestCompileError :: String -> IO ()
showTestCompileError portname = sendToLocalPort portname TestCompileError
sendToLocalPort :: String -> ProtocolMsg -> IO ()
sendToLocalPort portname msg =
connectPort (portname++"@localhost") >>= doSend msg