[project @ 2003-08-05 12:13:29 by panne]
[haskell-directory.git] / Debug / QuickCheck / Batch.hs
diff --git a/Debug/QuickCheck/Batch.hs b/Debug/QuickCheck/Batch.hs
deleted file mode 100644 (file)
index faaa808..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Debug.QuickCheck.Batch
--- Copyright   :  (c) Andy Gill 2001
--- License     :  BSD-style (see the file libraries/base/LICENSE)
--- 
--- Maintainer  :  libraries@haskell.org
--- Stability   :  experimental
--- Portability :  non-portable (uses Control.Exception, Control.Concurrent)
---
--- This is a batch driver for running QuickCheck (GHC only).
---
------------------------------------------------------------------------------
-
-{-
- - Here is the key for reading the output.
- -  . = test successful
- -  ? = every example passed, but quickcheck did not find enough good examples
- -  * = test aborted for some reason (out-of-time, bottom, etc)
- -  # = test failed outright
- - 
- - We also provide the dangerous "isBottom".
- -
- - Here is is an example of use for sorting:
- - 
- - testOptions :: TestOptions
- - testOptions = TestOptions 
- -                 { no_of_tests = 100         -- number of tests to run
- -                 , length_of_tests = 1       -- 1 second max per check
- -                                             -- where a check == n tests
- -                 , debug_tests = False       -- True => debugging info
- -                 }
- - 
- - prop_sort1 xs = sort xs == sortBy compare xs
- -   where types = (xs :: [OrdALPHA])
- - prop_sort2 xs = 
- -         (not (null xs)) ==>
- -         (head (sort xs) == minimum xs)
- -   where types = (xs :: [OrdALPHA])
- - prop_sort3 xs = (not (null xs)) ==>
- -         last (sort xs) == maximum xs
- -   where types = (xs :: [OrdALPHA])
- - prop_sort4 xs ys =
- -         (not (null xs)) ==>
- -         (not (null ys)) ==>
- -         (head (sort (xs ++ ys)) == min (minimum xs) (minimum ys))
- -   where types = (xs :: [OrdALPHA], ys :: [OrdALPHA])
- - prop_sort6 xs ys =
- -         (not (null xs)) ==>
- -         (not (null ys)) ==>
- -         (last (sort (xs ++ ys)) == max (maximum xs) (maximum ys))
- -   where types = (xs :: [OrdALPHA], ys :: [OrdALPHA])
- - prop_sort5 xs ys =
- -         (not (null xs)) ==>
- -         (not (null ys)) ==>
- -         (head (sort (xs ++ ys)) == max (maximum xs) (maximum ys))
- -   where types = (xs :: [OrdALPHA], ys :: [OrdALPHA])
- - 
- - test_sort = runTests "sort" testOptions
- -         [ run prop_sort1
- -         , run prop_sort2
- -         , run prop_sort3
- -         , run prop_sort4
- -         , run prop_sort5
- -         ]
- - 
- - When run, this gives
- - Main> test_sort
- -                     sort : .....
- - 
- - You would tie together all the test_* functions
- - into one test_everything, on a per module basis.
- -
- - Examples of use of bottom and isBottom:
- -      {- test for abort -}
- -     prop_head2 = isBottom (head [])
- -      {- test for strictness -}
- -     prop_head3 = isBottom (head bottom)
- -}
-
-module Debug.QuickCheck.Batch
-   ( run               -- :: Testable a => a -> TestOptions -> IO TestResult
-   , runTests          -- :: String -> TestOptions -> 
-                       --      [TestOptions -> IO TestResult] -> IO ()
-   , defOpt            -- :: TestOptions
-   , TestOptions (..)
-   , TestResult (..)
-   , isBottom          -- :: a -> Bool
-   , bottom            -- :: a                 {- _|_ -}
-   ) where
-
-import Prelude
-
-import System.Random
-import Control.Concurrent
-import Control.Exception hiding (catch, evaluate)
-import qualified Control.Exception as Exception (catch, evaluate)
-import Debug.QuickCheck
-import System.IO.Unsafe
-
-data TestOptions = TestOptions {
-       no_of_tests     :: Int,
-       length_of_tests :: Int,
-       debug_tests     :: Bool }
-
-defOpt :: TestOptions
-defOpt = TestOptions 
-       { no_of_tests = 100
-       , length_of_tests = 1
-       , debug_tests = False
-       }
-
-data TestResult = TestOk       String  Int [[String]]
-               | TestExausted  String  Int [[String]]
-               | TestFailed   [String] Int
-               | TestAborted   Exception
-
-tests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] 
-      -> IO TestResult
-tests config gen rnd0 ntest nfail stamps
-  | ntest == configMaxTest config = return (TestOk  "OK, passed" ntest stamps)
-  | nfail == configMaxFail config = return (TestExausted "Arguments exhausted after"
-                                        ntest stamps)
-  | otherwise               =
-      do (if not (null txt) then putStr txt else return ())
-        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 ->
-             do return (TestFailed (arguments result) ntest)
-     where
-      txt         = configEvery config ntest (arguments result)
-      result      = generate (configSize config ntest) rnd2 gen
-      (rnd1,rnd2) = split rnd0
-
-batch n v = Config
-  { configMaxTest = n
-  , configMaxFail = n * 10
-  , configSize    = (+ 3) . (`div` 2)
-  , configEvery   = \n args -> if v then show n ++ ":\n" ++ unlines args else ""
-  }
-
--- Here we use the same random number each time,
--- so we get reproducable results!
-run :: Testable a => a -> TestOptions -> IO TestResult
-run a TestOptions { no_of_tests = n, length_of_tests = len, debug_tests = debug } =
-  do me <- myThreadId
-     ready <- newEmptyMVar
-     r <- if len == 0
-          then try theTest
-          else try (do
-            -- This waits a bit, then raises an exception in its parent,
-             -- saying, right, you've had long enough!
-            watcher <- forkIO (Exception.catch
-                             (do threadDelay (len * 1000 * 1000)
-                                 takeMVar ready
-                                 throwTo me NonTermination
-                                 return ())
-                             (\ _ -> return ()))
-            -- Tell the watcher we are starting...
-            putMVar ready ()
-             -- This is cheating, because possibly some of the internal message
-             -- inside "r" might be _|_, but anyway....
-            r <- theTest
-            -- Now, we turn off the watcher.
-            -- Ignored if the watcher is already dead, 
-            -- (unless some unlucky thread picks up the same name)
-            killThread watcher
-            return r)
-     case r of
-        Right r -> return r
-        Left  e -> return (TestAborted e)
-  where
-       theTest = tests (batch n debug) (evaluate a) (mkStdGen 0) 0 0 []     
-
--- Prints a one line summary of various tests with common theme
-runTests :: String -> TestOptions -> [TestOptions -> IO TestResult] -> IO ()
-runTests name scale actions =
-  do putStr (rjustify 25 name ++ " : ")
-     f <- tr 1 actions [] 0
-     mapM fa f
-     return ()
-  where
-       rjustify n s = replicate (max 0 (n - length s)) ' ' ++ s
-
-       tr n [] xs c = do
-                       putStr (rjustify (max 0 (35-n)) " (" ++ show c ++ ")\n")
-                       return xs
-       tr n (action:actions) others c = 
-          do r <- action scale
-             case r of
-               (TestOk _ m _) 
-                       -> do { putStr "." ;
-                              tr (n+1) actions others (c+m) }
-               (TestExausted s m ss) 
-
-                       -> do { putStr "?" ;
-                              tr (n+1) actions others (c+m) }
-               (TestAborted e) 
-                       -> do { putStr "*" ;
-                              tr (n+1) actions others c }
-               (TestFailed f num)
-                       -> do { putStr "#" ;
-                               tr (n+1) actions ((f,n,num):others) (c+num) }
-
-       fa :: ([String],Int,Int) -> IO ()
-       fa (f,n,no) = 
-         do putStr "\n"
-            putStr ("    ** test " 
-                       ++ show (n  :: Int)
-                       ++ " of "
-                       ++ name
-                       ++ " failed with the binding(s)\n")
-            sequence_ [putStr ("    **   " ++ v ++ "\n")
-                       | v <- f ]
-            putStr "\n"
-
--- Look out behind you! These can be misused badly.
--- However, in the context of a batch tester, can also be very useful.
-
-bottom = error "_|_"
-
-isBottom :: a -> Bool
-isBottom a = unsafePerformIO (do
-       a' <- try (Exception.evaluate a)
-       case a' of
-          Left _ -> return True
-          Right _ -> return False)