module Foundation.Check
( Gen
, Arbitrary(..)
, oneof
, elements
, frequency
, between
, Test(..)
, testName
, PropertyCheck
, Property(..)
, IsProperty(..)
, (===)
, propertyCompare
, propertyAnd
, propertyFail
, forAll
, Check
, validate
, pick
, iterateProperty
) where
import Foundation.Primitive.Imports
import Foundation.Primitive.IntegralConv
import Foundation.Primitive.Types.OffsetSize
import Foundation.Check.Gen
import Foundation.Check.Arbitrary
import Foundation.Check.Property
import Foundation.Check.Types
import Foundation.Check.Print
import Foundation.Monad
import Foundation.Monad.State
import Foundation.Numerical
import Control.Exception (evaluate, SomeException)
validate :: IsProperty prop => String -> prop -> Check ()
validate propertyName prop = Check $ do
(genrng, params) <- withState $ \st -> ( (planRng st, planParams st)
, st { planValidations = planValidations st + 1 }
)
(r,nb) <- liftIO $ iterateProperty 100 params genrng (property prop)
case r of
PropertySuccess -> return ()
PropertyFailed failMsg -> do
withState $ \st -> ((), st { planFailures = PropertyResult propertyName nb (PropertyFailed failMsg) : planFailures st })
return ()
pick :: String -> IO a -> Check a
pick _ io = Check $ do
r <- liftIO $ io
pure r
iterateProperty :: CountOf TestResult -> GenParams -> (Word64 -> GenRng) -> Property -> IO (PropertyResult, CountOf TestResult)
iterateProperty limit genParams genRngIter prop = iterProp 1
where
iterProp !iter
| iter == limit = return (PropertySuccess, iter)
| otherwise = do
r <- liftIO $ toResult
case r of
(PropertyFailed e, _) -> return (PropertyFailed e, iter)
(PropertySuccess, cont) | cont -> iterProp (iter+1)
| otherwise -> return (PropertySuccess, iter)
where
iterW64 :: Word64
iterW64 = let (CountOf iter') = iter in integralCast (integralUpsize iter' :: Int64)
toResult :: IO (PropertyResult, Bool)
toResult = (propertyToResult <$> evaluate (runGen (unProp prop) (genRngIter iterW64) genParams))
`catch` (\(e :: SomeException) -> return (PropertyFailed (show e), False))