File: QuickCheckUtils.hs

package info (click to toggle)
haskell-binary 0.4.1-3
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 292 kB
  • ctags: 11
  • sloc: haskell: 4,054; makefile: 88; ansic: 39
file content (258 lines) | stat: -rw-r--r-- 7,608 bytes parent folder | download | duplicates (5)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
{-# OPTIONS_GHC -fglasgow-exts #-}
--
-- Uses multi-param type classes
--
module QuickCheckUtils where

import Control.Monad

import Test.QuickCheck.Batch
import Test.QuickCheck
import Text.Show.Functions

import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
import qualified Data.ByteString.Internal as B
import qualified Data.ByteString.Lazy as L
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet

import qualified Control.Exception as C (evaluate)

import Control.Monad        ( liftM2 )
import Data.Char
import Data.List
import Data.Word
import Data.Int
import System.Random
import System.IO

-- import Control.Concurrent
import System.Mem
import System.CPUTime
import Text.Printf

import qualified Data.ByteString      as P
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Internal as L

-- import qualified Data.Sequence as Seq

-- Enable this to get verbose test output. Including the actual tests.
debug = False

mytest :: Testable a => a -> Int -> IO ()
mytest a n = mycheck defaultConfig
    { configMaxTest=n
    , configEvery= \n args -> if debug then show n ++ ":\n" ++ unlines args else [] } a

mycheck :: Testable a => Config -> a -> IO ()
mycheck config a = do
     rnd <- newStdGen
     performGC -- >> threadDelay 100
     t <- mytests config (evaluate a) rnd 0 0 [] 0 -- 0
     printf " %0.3f seconds\n" (t :: Double)
     hFlush stdout

time :: a -> IO (a , Double)
time a = do
    start <- getCPUTime
    v     <- C.evaluate a
    v `seq` return ()
    end   <- getCPUTime
    return (v,     (      (fromIntegral (end - start)) / (10^12)))

mytests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> Double -> IO  Double
mytests config gen rnd0 ntest nfail stamps t0
  | ntest == configMaxTest config = do done "OK," ntest stamps
                                       return t0

  | nfail == configMaxFail config = do done "Arguments exhausted after" ntest stamps
                                       return t0

  | otherwise = do
     (result,t1) <- time (generate (configSize config ntest) rnd2 gen)

     putStr (configEvery config ntest (arguments result)) >> hFlush stdout
     case ok result of
       Nothing    ->
         mytests config gen rnd1 ntest (nfail+1) stamps (t0 + t1)
       Just True  ->
         mytests config gen rnd1 (ntest+1) nfail (stamp result:stamps) (t0 + t1)
       Just False -> do
         putStr ( "Falsifiable after "
               ++ show ntest
               ++ " tests:\n"
               ++ unlines (arguments result)
                ) >> hFlush stdout
         return t0

     where
      (rnd1,rnd2) = split rnd0

done :: String -> Int -> [[String]] -> IO ()
done mesg ntest stamps = putStr ( mesg ++ " " ++ show ntest ++ " tests" ++ table )
 where
  table = display
        . map entry
        . reverse
        . sort
        . map pairLength
        . group
        . sort
        . filter (not . null)
        $ stamps

  display []  = ". "
  display [x] = " (" ++ x ++ "). "
  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) ++ "%"

------------------------------------------------------------------------

instance Random Word8 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Int8 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Word16 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Int16 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Word where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Word32 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Int32 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Word64 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

instance Random Int64 where
  randomR = integralRandomR
  random = randomR (minBound,maxBound)

------------------------------------------------------------------------

integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
integralRandomR  (a,b) g = case randomR (fromIntegral a :: Integer,
                                         fromIntegral b :: Integer) g of
                            (x,g) -> (fromIntegral x, g)

------------------------------------------------------------------------

instance Arbitrary Word8 where
    arbitrary       = choose (0, 2^8-1)
    coarbitrary w   = variant 0

instance Arbitrary Word16 where
    arbitrary       = choose (0, 2^16-1)
    coarbitrary     = undefined

instance Arbitrary Word32 where
--  arbitrary       = choose (0, 2^32-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary     = undefined

instance Arbitrary Word64 where
--  arbitrary       = choose (0, 2^64-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary     = undefined

instance Arbitrary Int8 where
--  arbitrary       = choose (0, 2^8-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary w   = variant 0

instance Arbitrary Int16 where
--  arbitrary       = choose (0, 2^16-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary     = undefined

instance Arbitrary Int32 where
--  arbitrary       = choose (0, 2^32-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary     = undefined

instance Arbitrary Int64 where
--  arbitrary       = choose (0, 2^64-1)
    arbitrary       = choose (minBound, maxBound)
    coarbitrary     = undefined

instance Arbitrary Word where
    arbitrary       = choose (minBound, maxBound)
    coarbitrary w   = variant 0

------------------------------------------------------------------------

instance Arbitrary Char where
    arbitrary = choose (maxBound, minBound)
    coarbitrary = undefined

{-
instance Arbitrary a => Arbitrary (Maybe a) where
    arbitrary = oneof [ return Nothing, liftM Just arbitrary]
    coarbitrary = undefined
    -}

instance Arbitrary Ordering where
    arbitrary = oneof [ return LT,return  GT,return  EQ ]
    coarbitrary = undefined

{-
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b) where
    arbitrary = oneof [ liftM Left arbitrary, liftM Right arbitrary]
    coarbitrary = undefined
    -}

instance Arbitrary IntSet.IntSet where
    arbitrary = fmap IntSet.fromList arbitrary
    coarbitrary = undefined

instance (Arbitrary e) => Arbitrary (IntMap.IntMap e) where
    arbitrary = fmap IntMap.fromList arbitrary
    coarbitrary = undefined

instance (Arbitrary a, Ord a) => Arbitrary (Set.Set a) where
    arbitrary = fmap Set.fromList arbitrary
    coarbitrary = undefined

instance (Arbitrary a, Ord a, Arbitrary b) => Arbitrary (Map.Map a b) where
    arbitrary = fmap Map.fromList arbitrary
    coarbitrary = undefined

{-
instance (Arbitrary a) => Arbitrary (Seq.Seq a) where
    arbitrary = fmap Seq.fromList arbitrary
    coarbitrary = undefined
-}

instance Arbitrary L.ByteString where
    arbitrary     = arbitrary >>= return . L.fromChunks . filter (not. B.null) -- maintain the invariant.
    coarbitrary s = coarbitrary (L.unpack s)

instance Arbitrary B.ByteString where
  arbitrary = B.pack `fmap` arbitrary
  coarbitrary s = coarbitrary (B.unpack s)