module AutoTest(module AutoTest, module Test.QuickCheck) where import Test.QuickCheck hiding (check) import Char import System.Random import List constTest :: Bool -> IO () constTest True = return () constTest False = error "Failed on constTest" data QFilePath = QFilePath FilePath deriving Show instance Arbitrary QFilePath where arbitrary = vector 25 >>= return . QFilePath instance Arbitrary Char where arbitrary = oneof $ map return "?|./:\\abcd 123;_" -- below is mainly stolen from Test.QuickCheck, modified to crash out on failure quickSafe :: Testable a => a -> IO () quickSafe prop = check quick prop quick :: Config quick = Config { configMaxTest = 500 , configMaxFail = 1000 , configSize = (+ 3) . (`div` 2) , configEvery = \n args -> let s = show n in s ++ [ '\b' | _ <- s ] } check :: Testable a => Config -> a -> IO () check config a = do rnd <- newStdGen tests config (evaluate a) rnd 0 0 [] tests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO () tests config gen rnd0 ntest nfail stamps | ntest == configMaxTest config = do done "OK, passed" ntest stamps | nfail == configMaxFail config = do done "Arguments exhausted after" ntest stamps error "More entropy required!" | otherwise = do putStr (configEvery config ntest (arguments result)) case ok result of Nothing -> tests config gen rnd1 ntest (nfail+1) stamps Just True -> tests config gen rnd1 (ntest+1) nfail (stamp result:stamps) Just False -> error ( "Falsifiable, after " ++ show ntest ++ " tests:\n" ++ unlines (arguments result) ) where result = generate (configSize config ntest) rnd2 gen (rnd1,rnd2) = split rnd0 done :: String -> Int -> [[String]] -> IO () done mesg ntest stamps = do putStr ( mesg ++ " " ++ show ntest ++ " tests" ++ table ) where table = display . map entry . reverse . sort . map pairLength . group . sort . filter (not . null) $ stamps display [] = ".\n" display [x] = " (" ++ x ++ ").\n" display xs = ".\n" ++ unlines (map (++ ".") xs) pairLength xss@(xs:_) = (length xss, xs) entry (n, xs) = percentage n ntest ++ " " ++ concat (intersperse ", " xs) percentage n m = show ((100 * n) `div` m) ++ "%"