forked from mgsloan/ActiveHs
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathQuickCheck.hs
More file actions
117 lines (97 loc) · 3.87 KB
/
Copy pathQuickCheck.hs
File metadata and controls
117 lines (97 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
module QuickCheck where
import Smart
import ActiveHs.Base (WrapData2 (WrapData2), TestCase (TestCase))
import Lang
import Result
import Logger
import Qualify (qualify)
import Hash
import Specialize (specialize)
import Test.QuickCheck hiding (Result)
import qualified Test.QuickCheck.Property as QC
import Data.Char (isLower)
import Data.List (intercalate)
import Control.Monad (join,forM,void)
import Control.Monad.Trans (liftIO)
import Control.Concurrent.MVar (newMVar, swapMVar, takeMVar)
---------------------------------------
quickCheck
:: String
-> Hash
-> Language
-> TaskChan
-> FilePath
-> String
-> [String]
-> [([String],String)] -- test cases
-> IO Result
quickCheck qualifier m5 lang ch fn ft funnames testcases = do
logStrMsg 3 (logger ch) $ "test cases: " ++ show testcases
logStrMsg 3 (logger ch) $ "names to be qualified: " ++ show funnames
case allRight $ map (qualify qualifier funnames . snd) testcases of
Left err -> do
logStrMsg 3 (logger ch) $ "Error in qualification: " ++ err
return $ Error True err
Right s_ -> do
logStrMsg 3 (logger ch) $ "Qualified expressions: " ++ show s_
interp False m5 lang ch fn "" $ Just $ \a ->
do ss <- forM (testcases `zip` s_) $ \((v,s1),s2) -> do
ts1 <- typeOf s1
ts2 <- typeOf s2
let [x1,x2] = map fixType [(s1,ts1),(s2,ts2)]
return $ mkTestCase (v,x1,x2)
let ts = "[" ++ intercalate ", " ss ++ "]"
liftIO $ logStrMsg 3 (logger ch) $ "Test cases: " ++ ts
liftIO $ logStrMsg 3 (logger ch) "Before interpretation"
m <- interpret ts (as :: [TestCase])
liftIO $ logStrMsg 3 (logger ch) "After interpretation"
liftIO $ qcs lang (logger ch) m
where
fixType (s,t) =
case (specialize t) of
Right (st,_) | t /= st -> unwords [s, "::", st]
_ -> s
mkTestCase (vars, s, s2)
= "TestCase (\\qcinner "
++ unwords ["(" ++ v ++ ")" | v<-vars]
++ " -> qcinner (" ++ showTr vars s ++ ", " ++ parens s ++ ", " ++ parens s2 ++ "))"
showTr vars s = "unwords [" ++ intercalate ", " (map g $ words s) ++ "]" -- !!!
where
vs = concatMap f vars
f = filter (isLower . head) . words
g x | x `elem` vs = {- "\"(\" ++ -} " show " ++ x -- ++ " ++ \")\""
g x = show x
qcs :: Language -> Logger -> [TestCase] -> IO Result
qcs lang log = foldM (Message (translate lang "All test cases are completed.") Nothing) (qc lang log)
-- test = qc $ TestCase $ \f (QCNat x) (QCInt y) -> f (show x ++ " + " ++ show y, min 10 (x + y), x + y)
-- test' = qc $ TestCase $ \f (QCInt x) -> f ("sqr " ++ show x, min 10 (x*x), x*x)
qc :: Language -> Logger -> TestCase -> IO (Maybe Result)
qc lang log (TestCase p) = do
v <- newMVar Nothing
let ff (s, x, y)
= QC.morallyDubiousIOProperty $ do
r <- res
if hasError [r]
then do
void $ swapMVar v $ Just $ ShowFailedTestCase s r
return QC.failed
else return QC.succeeded
where
res :: IO Result
res = do
logStrMsg 4 log $ "compare: " ++ s
compareClearGen lang "noId" $ WrapData2 x y
_ <- quickCheckWithResult (stdArgs { chatty = False }) $ {- QC.noShrinking $ -} p ff
takeMVar v
------------------------------------
allRight :: [Either a b] -> Either a [b]
allRight x = case [s | Left s<-x] of
(y:_) -> Left y
[] -> Right [s | Right s<-x]
foldM :: Monad m => r -> (a -> m (Maybe r)) -> [a] -> m r
foldM end _ [] = return end
foldM end f (t:ts) = do
x <- f t
case x of
Just r -> return r
Nothing -> foldM end f ts