File: MiniQC.hs

package info (click to toggle)
haskell-splitmix 0.1.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 200 kB
  • sloc: haskell: 1,337; ansic: 125; sh: 53; makefile: 3
file content (81 lines) | stat: -rw-r--r-- 2,417 bytes parent folder | download
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
{-# LANGUAGE DeriveFunctor #-}
-- | This QC doesn't shrink :(
module MiniQC where

import Control.Monad                  (ap)
import Data.Int                       (Int32, Int64)
import Data.Word                      (Word32, Word64)
import Test.Framework.Providers.API   (Test, TestName)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit                     (assertFailure)

import System.Random.SplitMix

newtype Gen a = Gen { unGen :: SMGen -> a }
  deriving (Functor)

instance Applicative Gen where
    pure x = Gen (const x)
    (<*>) = ap

instance Monad Gen where
    return = pure

    m >>= k = Gen $ \g ->
        let (g1, g2) = splitSMGen g
        in unGen (k (unGen m g1)) g2

class Arbitrary a where
    arbitrary :: Gen a

instance Arbitrary Word32 where
    arbitrary = Gen $ \g -> fst (nextWord32 g)
instance Arbitrary Word64 where
    arbitrary = Gen $ \g -> fst (nextWord64 g)
instance Arbitrary Int32 where
    arbitrary = Gen $ \g -> fromIntegral (fst (nextWord32 g))
instance Arbitrary Int64 where
    arbitrary = Gen $ \g -> fromIntegral (fst (nextWord64 g))
instance Arbitrary Double where
    arbitrary = Gen $ \g -> fst (nextDouble g)

newtype Property = Property { unProperty :: Gen ([String], Bool) }

class Testable a where
    property :: a -> Property

instance Testable Property where
    property = id

instance Testable Bool where
    property b = Property $ pure ([show b], b)

instance (Arbitrary a, Show a, Testable b) => Testable (a -> b) where
    property f = Property $ do
        x <- arbitrary
        (xs, b) <- unProperty (property (f x))
        return (show x : xs, b)

forAllBlind :: Testable prop => Gen a -> (a -> prop) -> Property
forAllBlind g f = Property $ do
    x <- g
    (xs, b) <- unProperty (property (f x))
    return ("<blind>" : xs, b)

counterexample :: Testable prop => String -> prop -> Property
counterexample msg prop = Property $ do
    (xs, b) <- unProperty (property prop)
    return (msg : xs, b)

testMiniProperty :: Testable prop => TestName -> prop -> Test
testMiniProperty name prop = testCase name $ do
    g <- newSMGen
    go (100 :: Int) g
  where
    go n _ | n <= 0  = return ()
    go n g           = do
        let (g1, g2) = splitSMGen g
        case unGen (unProperty (property prop)) g1 of
            (_, True) -> return ()
            (xs, False) -> assertFailure (unlines (reverse xs))
        go (pred n) g2