Blame tests/Generators.hs

Packit 1d8052
{-# LANGUAGE TemplateHaskell, GeneralizedNewtypeDeriving, Rank2Types, NoMonomorphismRestriction #-}
Packit 1d8052
import Test.QuickCheck
Packit 1d8052
import Test.QuickCheck.Gen.Unsafe
Packit 1d8052
import Data.List
Packit 1d8052
import Data.Int
Packit 1d8052
import Data.Word
Packit 1d8052
import Data.Version (showVersion, parseVersion)
Packit 1d8052
import Text.ParserCombinators.ReadP (readP_to_S)
Packit 1d8052
Packit 1d8052
newtype Path a = Path [a] deriving (Show, Functor)
Packit 1d8052
Packit 1d8052
instance Arbitrary a => Arbitrary (Path a) where
Packit 1d8052
  arbitrary = do
Packit 1d8052
    x <- arbitrary
Packit 1d8052
    fmap Path (pathFrom x)
Packit 1d8052
    where
Packit 1d8052
      pathFrom x = sized $ \n ->
Packit 1d8052
        fmap (x:) $
Packit 1d8052
        oneof $
Packit 1d8052
          [return []] ++
Packit 1d8052
          [resize (n-1) (pathFrom y) | n > 0, y <- shrink x]
Packit 1d8052
Packit 1d8052
  shrink (Path xs) = map Path [ ys | ys <- inits xs, length ys > 0 && length ys < length xs ]
Packit 1d8052
Packit 1d8052
path :: (a -> Bool) -> Path a -> Bool
Packit 1d8052
path p (Path xs) = all p xs
Packit 1d8052
Packit 1d8052
somePath :: (a -> Bool) -> Path a -> Property
Packit 1d8052
somePath p = expectFailure . path (not . p)
Packit 1d8052
Packit 1d8052
newtype Extremal a = Extremal { getExtremal :: a } deriving (Show, Eq, Ord, Num, Enum, Real, Integral)
Packit 1d8052
Packit 1d8052
instance (Arbitrary a, Bounded a) => Arbitrary (Extremal a) where
Packit 1d8052
  arbitrary =
Packit 1d8052
    fmap Extremal $
Packit 1d8052
    frequency
Packit 1d8052
      [(1, return minBound),
Packit 1d8052
       (1, return maxBound),
Packit 1d8052
       (8, arbitrary)]
Packit 1d8052
  shrink (Extremal x) = map Extremal (shrink x)
Packit 1d8052
Packit 1d8052
smallProp :: Integral a => Path a -> Bool
Packit 1d8052
smallProp = path (\x -> (x >= -100 || -100 `asTypeOf` x >= 0) && x <= 100)
Packit 1d8052
Packit 1d8052
largeProp :: Integral a => Path a -> Property
Packit 1d8052
largeProp = somePath (\x -> x < -1000000 || x > 1000000)
Packit 1d8052
Packit 1d8052
prop_int :: Path Int -> Bool
Packit 1d8052
prop_int = smallProp
Packit 1d8052
Packit 1d8052
prop_int32 :: Path Int32 -> Property
Packit 1d8052
prop_int32 = largeProp
Packit 1d8052
Packit 1d8052
prop_word :: Path Word -> Property
Packit 1d8052
prop_word = largeProp
Packit 1d8052
Packit 1d8052
prop_word32 :: Path Word32 -> Property
Packit 1d8052
prop_word32 = largeProp
Packit 1d8052
Packit 1d8052
prop_integer :: Path Integer -> Bool
Packit 1d8052
prop_integer = smallProp
Packit 1d8052
Packit 1d8052
prop_small :: Path (Small Int) -> Bool
Packit 1d8052
prop_small = smallProp
Packit 1d8052
Packit 1d8052
prop_large :: Path (Large Int) -> Property
Packit 1d8052
prop_large = largeProp
Packit 1d8052
Packit 1d8052
prop_smallWord :: Path (Small Word) -> Bool
Packit 1d8052
prop_smallWord = smallProp
Packit 1d8052
Packit 1d8052
prop_largeWord :: Path (Large Word) -> Property
Packit 1d8052
prop_largeWord = largeProp
Packit 1d8052
Packit 1d8052
data Choice a b = Choice a b deriving Show
Packit 1d8052
instance (Arbitrary a, Arbitrary b) => Arbitrary (Choice a b) where
Packit 1d8052
  arbitrary = do
Packit 1d8052
    Capture eval <- capture
Packit 1d8052
    return (Choice (eval arbitrary) (eval arbitrary))
Packit 1d8052
Packit 1d8052
idemProp :: (Eq a, Arbitrary a, Arbitrary b) => (b -> a) -> Choice a b -> Bool
Packit 1d8052
idemProp f (Choice x y) = x == f y
Packit 1d8052
Packit 1d8052
prop_fixed_length :: Arbitrary a => Path (Fixed a) -> Bool
Packit 1d8052
prop_fixed_length (Path xs) = length xs == 1
Packit 1d8052
Packit 1d8052
prop_fixed_idem = idemProp getFixed
Packit 1d8052
prop_blind_idem = idemProp getBlind
Packit 1d8052
Packit 1d8052
prop_ordered_list = path (\(Ordered xs) -> sort xs == xs)
Packit 1d8052
prop_nonempty_list = path (\(NonEmpty xs) -> not (null xs))
Packit 1d8052
Packit 1d8052
pathInt, somePathInt ::
Packit 1d8052
  (Arbitrary (f (Extremal Int)), Show (f (Extremal Int)),
Packit 1d8052
   Arbitrary (f Integer), Show (f Integer),
Packit 1d8052
   Arbitrary (f (Extremal Int8)), Show (f (Extremal Int8)),
Packit 1d8052
   Arbitrary (f (Extremal Int16)), Show (f (Extremal Int16)),
Packit 1d8052
   Arbitrary (f (Extremal Int32)), Show (f (Extremal Int32)),
Packit 1d8052
   Arbitrary (f (Extremal Int64)), Show (f (Extremal Int64)),
Packit 1d8052
   Arbitrary (f (Extremal Word)), Show (f (Extremal Word)),
Packit 1d8052
   Arbitrary (f (Extremal Word8)), Show (f (Extremal Word8)),
Packit 1d8052
   Arbitrary (f (Extremal Word16)), Show (f (Extremal Word16)),
Packit 1d8052
   Arbitrary (f (Extremal Word32)), Show (f (Extremal Word32)),
Packit 1d8052
   Arbitrary (f (Extremal Word64)), Show (f (Extremal Word64))) =>
Packit 1d8052
  (forall a. f a -> a) -> (forall a. Integral a => a -> Bool) -> Property
Packit 1d8052
pathInt f p =
Packit 1d8052
  conjoin
Packit 1d8052
    [counterexample "Int" (path ((p :: Int -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Integer" (path ((p :: Integer -> Bool) . f)),
Packit 1d8052
     counterexample "Int8" (path ((p :: Int8 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Int16" (path ((p :: Int16 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Int32" (path ((p :: Int32 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Int64" (path ((p :: Int64 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Word" (path ((p :: Word -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Word8" (path ((p :: Word8 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Word16" (path ((p :: Word16 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Word32" (path ((p :: Word32 -> Bool) . getExtremal . f)),
Packit 1d8052
     counterexample "Word64" (path ((p :: Word64 -> Bool) . getExtremal . f))]
Packit 1d8052
somePathInt f p = expectFailure (pathInt f (not . p))
Packit 1d8052
Packit 1d8052
prop_positive = pathInt getPositive (> 0)
Packit 1d8052
prop_positive_bound = somePathInt getPositive (== 1)
Packit 1d8052
Packit 1d8052
prop_nonzero = pathInt getNonZero (/= 0)
Packit 1d8052
prop_nonzero_bound_1 = somePathInt getNonZero (== 1)
Packit 1d8052
prop_nonzero_bound_2 = somePathInt getNonZero (== -1)
Packit 1d8052
Packit 1d8052
prop_nonnegative = pathInt getNonNegative (>= 0)
Packit 1d8052
prop_nonnegative_bound = somePathInt getNonNegative (== 0)
Packit 1d8052
Packit 1d8052
reachesBound :: (Bounded a, Integral a, Arbitrary a) =>
Packit 1d8052
  a -> Property
Packit 1d8052
reachesBound x = expectFailure (x < 3 * (maxBound `div` 4))
Packit 1d8052
Packit 1d8052
prop_reachesBound_Int8 = reachesBound :: Int8 -> Property
Packit 1d8052
prop_reachesBound_Int16 = reachesBound :: Int16 -> Property
Packit 1d8052
prop_reachesBound_Int32 = reachesBound :: Int32 -> Property
Packit 1d8052
prop_reachesBound_Int64 = reachesBound :: Int64 -> Property
Packit 1d8052
prop_reachesBound_Word = reachesBound :: Word -> Property
Packit 1d8052
prop_reachesBound_Word8 = reachesBound :: Word8 -> Property
Packit 1d8052
prop_reachesBound_Word16 = reachesBound :: Word16 -> Property
Packit 1d8052
prop_reachesBound_Word32 = reachesBound :: Word32 -> Property
Packit 1d8052
prop_reachesBound_Word64 = reachesBound :: Word64 -> Property
Packit 1d8052
Packit 1d8052
-- Bad shrink: infinite list
Packit 1d8052
--
Packit 1d8052
-- remove unexpectedFailure in prop_B1, shrinking should not loop forever.
Packit 1d8052
data B1 = B1 Int deriving (Eq, Show)
Packit 1d8052
Packit 1d8052
instance Arbitrary B1 where
Packit 1d8052
    arbitrary = fmap B1 arbitrary
Packit 1d8052
    shrink x = x : shrink x
Packit 1d8052
Packit 1d8052
prop_B1 :: B1 -> Property
Packit 1d8052
prop_B1 (B1 n) = expectFailure $ n === n + 1
Packit 1d8052
Packit 1d8052
return []
Packit 1d8052
main = $forAllProperties (quickCheckWithResult stdArgs { maxShrinks = 10000 }) >>= print