module Main where import Plugin.Lambda.LMEngine (evaluate, define) #if __GLASGOW_HASKELL__ >= 604 import Test.HUnit #else import HUnit #endif -- import QuickCheck -- import QuickCheckM import qualified Map (empty) -- TODO: add tests for define, need to test List interactions (e.g. 1+head l) main = runTestTT tests >>= print tests = TestList [ test_Arith, test_Rel, test_List, test_Lambda, test_Misc, list_ender -- for rearranging and removing tests ] list_ender = TestCase $ return () typeErrorMsg = "type error" -- outOfFuelMsg = "out of fuel" divideByZeroMsg = "divide by zero" unboundVariableMsg = "unbound variable" tailMsg = "tail of empty list" headMsg = "head of empty list" infFuel = -1 emptyEnv = Map.empty -- no label genericTest' :: String -> String -> Test genericTest' expected code = expected ~=? case evaluate code emptyEnv infFuel of Left _ -> error "shouldn't get here" Right s -> s -- labelled with code genericTest :: String -> String -> Test genericTest expected code = genericTestLbl code expected code -- explicit label genericTestLbl :: String -> String -> String -> Test genericTestLbl lbl expected code = lbl ~: genericTest' expected code -- The tests ------------------------------------------------------------------- -- Arith -- test_Arith = TestLabel "Arith" $ TestList [ genericTest "-85" "4 + 3-2*(6+5*8)", genericTest divideByZeroMsg "1/0", genericTest "5" "5", list_ender ] -- Lambda -- test_Lambda = TestLabel "Lambda" $ TestList [ genericTest "10" "(\\x.x) 10", genericTest "5" "(\\x.x+3) 2", genericTestLbl "factorial" "120" "(\\f.(\\x.f(x x))(\\x.f(x x)))(\\fac n.if n == 0 then 1 else n*fac (n-1)) 5", genericTest "10" "(\\n.if n == 0 then n+3 else n+5) 5", genericTest "12" "(\\f.f 7) ((\\x y.x+y) 5)", genericTest "0" "(\\f.(\\x.f(x x))(\\x.f(x x)))(\\count n.if n==0 then 0 else count (n-1)) 1000", genericTest "15" "(\\S K I g f.(S (S (K S) (K I)) (S (K K) I)) g f) (\\f g x.f x (g x)) (\\r t.r) (\\l.l) 5 (\\m.m+10)", genericTest "14" "(\\x.x*2) $ 4+3", genericTest "-6" "((\\x.x*3) . (\\x.x-2)) 0", list_ender ] -- Rel -- test_Rel = TestLabel "Rel" $ TestList [ genericTest "True" "if 10 == 10 then True else False", genericTest "True" "5 == 5", genericTest "True" "5 /= 6", genericTest "False" "5 /= 5", genericTest "False" "5 == 6", genericTest "True" "5 <= 6", genericTest "False" "5 >= 6", genericTest "True" "5 < 6", genericTest "False" "5 > 6", genericTest "True" "5 == 10 || 6 == 6", genericTest "False" "5 == 10 && 6 == 6", genericTest "True" "True == True", genericTest "False" "'b' == 'c'", genericTest "True" "[] == []", genericTest "True" "[5,\"aoe\"] == [5,\"aoe\"]", genericTest "True" "null [] || 5 <= 6", genericTest "False" "\"aoeu\" == \"\"", genericTest "True" "1 == 1 || 1/0 == 1", genericTest "False" "1 == 0 && 1/0 == 1", list_ender ] -- List -- test_List = TestLabel "List" $ TestList [ genericTest "aoeu" "\"aoeu\"", genericTest "aoeu" "['a','o','e','u']", genericTest "a" "'a'", genericTest "[1, True, 3]" "[1,True,3]", genericTest "[1, True, 3]" "1:True:3:[]", genericTest "[True, 3]" "tail [1,True,3]", genericTest "1" "head [1,2,3]", genericTest tailMsg "tail []", genericTest headMsg "head []", genericTest "False" "null \"aoeu\"", genericTest "True" "null []", genericTest "True" "null \"\"", genericTest "[]" "[]", genericTest "1" "(\\f.f [1,2]) head", genericTestLbl "Tree" "(a (b c))" "(\\Leaf Branch tree.(\\f.(\\x.f(x x))(\\x.f(x x)))(\\showTree t.tree (\\l.[l]) (\\l r.'(':showTree l++' ':showTree r++\")\") t) (Branch (Leaf 'a') (Branch (Leaf 'b') (Leaf 'c')))) (\\c l b.l c) (\\l r lk bk.bk l r) (\\l b t.t l b)", list_ender ] -- Misc -- test_Misc = TestLabel "Misc" $ TestList [ test_TypeError, "ConsStrictness" ~: "1" ~=? case evaluate "head [1,(\\x.x x)(\\x.x x)]" emptyEnv 100 of Left _ -> "ConsStrictness";Right s -> s, "NullStrictness" ~: "False" ~=? case evaluate "null [1,(\\x.x x)(\\x.x x)]" emptyEnv 100 of Left _ -> "NullStrictness";Right s -> s, "ConsStrictness2" ~: "1" ~=? case evaluate "head ((\\f.(\\x.f(x x))(\\x.f(x x))) (\\x.1:x))" emptyEnv 100 of Left _ -> "ConsStrictness";Right s -> s, -- "OutOfFuel" ~: (outOfFuelMsg ~=? evaluate "(\\x.x x) (\\x.x x)" emptyEnv 100), list_ender ] test_TypeError = TestLabel "TypeError" $ TestList [ genericTest typeErrorMsg "(\\f.f 5) 7", genericTest typeErrorMsg "(\\x.x)+4", genericTest typeErrorMsg "if 4 then True else False", genericTest typeErrorMsg "null 5", list_ender ]