{-# LANGUAGE CPP #-}
{-# LANGUAGE KindSignatures #-}
{-# OPTIONS_GHC -Wall #-}
module Test.QuickCheck.Classes
(
lawsCheck
, lawsCheckMany
, lawsCheckOne
#if MIN_VERSION_base(4,7,0)
, bitsLaws
#endif
, eqLaws
, integralLaws
#if MIN_VERSION_base(4,7,0)
, isListLaws
#endif
#if HAVE_AESON
, jsonLaws
#endif
, monoidLaws
, commutativeMonoidLaws
, ordLaws
, enumLaws
, boundedEnumLaws
, primLaws
, semigroupLaws
, commutativeSemigroupLaws
, exponentialSemigroupLaws
, idempotentSemigroupLaws
, rectangularBandSemigroupLaws
#if HAVE_SEMIRINGS
, semiringLaws
#endif
, showLaws
, showReadLaws
, storableLaws
#if HAVE_UNARY_LAWS
, alternativeLaws
#if HAVE_SEMIGROUPOIDS
, altLaws
, applyLaws
#endif
, applicativeLaws
, foldableLaws
, functorLaws
, monadLaws
, monadPlusLaws
, monadZipLaws
#if HAVE_SEMIGROUPOIDS
, plusLaws
, extendedPlusLaws
#endif
, traversableLaws
#endif
#if HAVE_BINARY_LAWS
, bifunctorLaws
, categoryLaws
, commutativeCategoryLaws
#if HAVE_SEMIGROUPOIDS
, semigroupoidLaws
, commutativeSemigroupoidLaws
#endif
#endif
, Laws(..)
, Proxy1(..)
, Proxy2(..)
) where
import Test.QuickCheck.Classes.Bits
import Test.QuickCheck.Classes.Enum
import Test.QuickCheck.Classes.Eq
import Test.QuickCheck.Classes.Integral
#if MIN_VERSION_base(4,7,0)
import Test.QuickCheck.Classes.IsList
#endif
#if HAVE_AESON
import Test.QuickCheck.Classes.Json
#endif
import Test.QuickCheck.Classes.Monoid
import Test.QuickCheck.Classes.Ord
import Test.QuickCheck.Classes.Prim
import Test.QuickCheck.Classes.Semigroup
#if HAVE_SEMIRINGS
import Test.QuickCheck.Classes.Semiring
#endif
import Test.QuickCheck.Classes.Show
import Test.QuickCheck.Classes.ShowRead
import Test.QuickCheck.Classes.Storable
#if HAVE_UNARY_LAWS
import Test.QuickCheck.Classes.Alternative
#if HAVE_SEMIGROUPOIDS
import Test.QuickCheck.Classes.Alt
import Test.QuickCheck.Classes.Apply
#endif
import Test.QuickCheck.Classes.Applicative
import Test.QuickCheck.Classes.Foldable
import Test.QuickCheck.Classes.Functor
import Test.QuickCheck.Classes.Monad
import Test.QuickCheck.Classes.MonadPlus
import Test.QuickCheck.Classes.MonadZip
#if HAVE_SEMIGROUPOIDS
import Test.QuickCheck.Classes.Plus
#endif
import Test.QuickCheck.Classes.Traversable
#endif
#if HAVE_BINARY_LAWS
import Test.QuickCheck.Classes.Bifunctor
import Test.QuickCheck.Classes.Category
#if HAVE_SEMIGROUPOIDS
import Test.QuickCheck.Classes.Semigroupoid
#endif
#endif
import Test.QuickCheck
import Test.QuickCheck.Classes.Common (foldMapA, Laws(..))
import Control.Monad
import Data.Foldable
import Data.Monoid (Monoid(..))
import Data.Proxy (Proxy(..))
import Data.Semigroup (Semigroup)
import System.Exit (exitFailure)
import qualified Data.List as List
import qualified Data.Semigroup as SG
lawsCheck :: Laws -> IO ()
lawsCheck (Laws className properties) = do
flip foldMapA properties $ \(name,p) -> do
putStr (className ++ ": " ++ name ++ " ")
quickCheck p
lawsCheckOne :: Proxy a -> [Proxy a -> Laws] -> IO ()
lawsCheckOne p ls = foldlMapM (lawsCheck . ($ p)) ls
lawsCheckMany ::
[(String,[Laws])]
-> IO ()
lawsCheckMany xs = do
putStrLn "Testing properties for common typeclasses"
r <- flip foldMapA xs $ \(typeName,laws) -> do
putStrLn $ List.replicate (length typeName + 6) '-'
putStrLn $ "-- " ++ typeName ++ " --"
putStrLn $ List.replicate (length typeName + 6) '-'
flip foldMapA laws $ \(Laws typeClassName properties) -> do
flip foldMapA properties $ \(name,p) -> do
putStr (typeClassName ++ ": " ++ name ++ " ")
r <- quickCheckResult p
return $ case r of
Success{} -> Good
_ -> Bad
putStrLn ""
case r of
Good -> putStrLn "All tests succeeded"
Bad -> do
putStrLn "One or more tests failed"
exitFailure
data Status = Bad | Good
instance Semigroup Status where
Good <> x = x
Bad <> _ = Bad
instance Monoid Status where
mempty = Good
mappend = (SG.<>)
data Proxy1 (f :: * -> *) = Proxy1
data Proxy2 (f :: * -> * -> *) = Proxy2
foldlMapM :: (Foldable t, Monoid b, Monad m) => (a -> m b) -> t a -> m b
foldlMapM f = foldlM (\b a -> liftM (mappend b) (f a)) mempty