hedgehog 1.2 → 1.3
raw patch · 11 files changed
+152/−29 lines, 11 filesdep +safe-exceptionsdep ~ansi-terminal
Dependencies added: safe-exceptions
Dependency ranges changed: ansi-terminal
Files
- CHANGELOG.md +44/−0
- README.md +2/−0
- hedgehog.cabal +6/−5
- src/Hedgehog/Internal/Exception.hs +1/−1
- src/Hedgehog/Internal/Gen.hs +83/−12
- src/Hedgehog/Internal/Property.hs +2/−2
- src/Hedgehog/Internal/Region.hs +1/−1
- src/Hedgehog/Internal/Runner.hs +2/−2
- src/Hedgehog/Internal/Seed.hs +1/−0
- src/Hedgehog/Internal/State.hs +3/−3
- src/Hedgehog/Internal/Tree.hs +7/−3
CHANGELOG.md view
@@ -1,3 +1,16 @@+## Version 1.3 (2023-06-22)++* Better documentation for `Var` ([#491][491], [@endgame][endgame])+* Bump upper bounds for `ansi-terminal` ([#486][486], [@mpilgrem][mpilgrem])+* Better documentation for `Gen.filter[T]`, `Gen.mapMaybe[T]`, `Tree.prune` ([#485][485], [@ChickenProp][ChickenProp])+* Update Github CI actions, exclude Haddocks for old GHCs ([#482][482], [@ysangkok][ysangkok])+* Support GHC 9.6 ([#481][481], [@ysangkok][ysangkok])+* Bump upper bounds for `resourcet` and `primitive` ([#478][478], [@shlevy][shlevy])+* Export `Hedgehog.Internal.Seed.seed` ([#477][477], [@sol][sol])+* Better documentation for `sample` ([#468][468], [@parsonsmatt][parsonsmatt])+* Replace exceptions dependency with safe-exceptions ([#466][466], [@ocharles][ocharles])+* Generalise `Hedgehog.Gen.element` ([#411](411), [@ocharles][ocharles])+ ## Version 1.2 (2022-08-28) * Allow skipping to a specific test number or shrink result ([#454][454], [@ChickenProp][ChickenProp])@@ -8,6 +21,11 @@ * Add example for Gen.subsequence ([#450][450], [@chris-martin][chris-martin]) * Don't drop actions depending on shrunk predecessors ([#453][453], [@ChickenProp][ChickenProp]) +## Version 1.1.2 (2022-09-02)++* Support GHC 9.4 ([#461][461], [@ysangkok][ysangkok])+* Allow newer dependencies ([#457][457], [@ysangkok][ysangkok])+ ## Version 1.1.1 (2022-01-29) * Support using fixed seed via `HEDGEHOG_SEED` ([#446][446], [@simfleischman][simfleischman] / [@moodmosaic][moodmosaic])@@ -262,6 +280,30 @@ https://github.com/jhrcek +[parsonsmatt]:+ https://github.com/parsonsmatt+[shlevy]:+ https://github.com/shlevy+++[491]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/491+[486]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/486+[485]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/485+[482]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/482+[481]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/481+[478]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/478+[477]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/477+[468]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/468+[466]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/466 [462]: https://github.com/hedgehogqa/haskell-hedgehog/pull/462 [461]:@@ -292,6 +334,8 @@ https://github.com/hedgehogqa/haskell-hedgehog/pull/413 [412]: https://github.com/hedgehogqa/haskell-hedgehog/pull/412+[411]:+ https://github.com/hedgehogqa/haskell-hedgehog/pull/411 [409]: https://github.com/hedgehogqa/haskell-hedgehog/pull/409 [408]:
README.md view
@@ -3,6 +3,8 @@ doesn't seem to render the HTML portion of the markdown spec so you may be better off paying us a visit on GitHub instead: https://github.com/hedgehogqa/haskell-hedgehog++https://preview.webflow.com/preview/hedgehogqa?utm_medium=preview_link&utm_source=dashboard&utm_content=hedgehogqa&preview=e42e956627c1ec686ee73fc48a20fb71&workflow=preview --> <div align="center">
hedgehog.cabal view
@@ -1,4 +1,4 @@-version: 1.2+version: 1.3 name: hedgehog@@ -52,7 +52,7 @@ build-depends: -- GHC 8.0.1 / base-4.9.0.0 (May 2016) base >= 4.9 && < 5- , ansi-terminal >= 0.6 && < 0.12+ , ansi-terminal >= 0.6 && < 1.1 , async >= 2.0 && < 2.3 , barbies >= 1.0 && < 2.1 , bytestring >= 0.10 && < 0.12@@ -67,11 +67,12 @@ , monad-control >= 1.0 && < 1.1 , mtl >= 2.1 && < 2.4 , pretty-show >= 1.6 && < 1.11- , primitive >= 0.6 && < 0.8+ , primitive >= 0.6 && < 0.9 , random >= 1.1 && < 1.3- , resourcet >= 1.1 && < 1.3+ , resourcet >= 1.1 && < 1.4+ , safe-exceptions >= 0.1 && < 0.2 , stm >= 2.4 && < 2.6- , template-haskell >= 2.10 && < 2.20+ , template-haskell >= 2.10 && < 2.21 , text >= 1.1 && < 2.1 , time >= 1.4 && < 1.13 , transformers >= 0.5 && < 0.7
src/Hedgehog/Internal/Exception.hs view
@@ -5,7 +5,7 @@ ) where import Control.Exception (Exception(..), AsyncException, SomeException(..), evaluate)-import Control.Monad.Catch (MonadCatch(..), throwM)+import Control.Exception.Safe (MonadCatch, catch, throwM) import System.IO.Unsafe (unsafePerformIO)
src/Hedgehog/Internal/Gen.hs view
@@ -175,11 +175,14 @@ , subtermMVec ) where -import Control.Applicative (Alternative(..),liftA2)+#if !MIN_VERSION_base(4,18,0)+import Control.Applicative (liftA2)+#endif+import Control.Applicative (Alternative(..)) import Control.Monad (MonadPlus(..), filterM, guard, replicateM, join) import Control.Monad.Base (MonadBase(..))+import Control.Monad.Catch (MonadThrow(throwM), MonadCatch(catch)) import Control.Monad.Trans.Control (MonadBaseControl(..))-import Control.Monad.Catch (MonadThrow(..), MonadCatch(..)) import Control.Monad.Error.Class (MonadError(..)) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Morph (MFunctor(..), MMonad(..))@@ -1188,10 +1191,10 @@ -- -- /The input list must be non-empty./ ---element :: MonadGen m => [a] -> m a-element = \case+element :: (Foldable f, MonadGen m) => f a -> m a+element fa = case toList fa of [] ->- error "Hedgehog.Gen.element: used with empty list"+ error "Hedgehog.Gen.element: used with empty Foldable" xs -> do n <- integral $ Range.constant 0 (length xs - 1) pure $ xs !! n@@ -1325,19 +1328,33 @@ -- | Generates a value that satisfies a predicate. ----- This is essentially:------ @--- filter p gen = 'mfilter' p gen '<|>' filter p gen--- @+-- Shrinks of the generated value will also satisfy the predicate. From the+-- original generator's shrink tree, any values that fail the predicate will+-- be removed, but any subsequent shrinks that satisfy it will be retained.+-- Compared to 'filter', shrinking may be slower but will be optimal. ----- It differs from the above in that we keep some state to avoid looping--- forever. If we trigger these limits then the whole generator is discarded.+-- It's possible that the predicate will never pass, or will only pass at a+-- larger size than we're currently running at. To avoid looping forever, we+-- limit the number of retries, and grow the size with each retry. If we retry+-- too many times then the whole generator is discarded. -- filter :: (MonadGen m, GenBase m ~ Identity) => (a -> Bool) -> m a -> m a filter p = mapMaybe (fromPred p) +-- | Generates a value which is the result of the given function returning a+-- 'Just'.+--+-- The original generator's shrink tree will be retained, with values+-- returning 'Nothing' removed. Subsequent shrinks of those values will be+-- retained. Compared to 'mapMaybeT', shrinking may be slower but will be+-- optimal.+--+-- It's possible that the function will never return 'Just', or will only do+-- so a larger size than we're currently running at. To avoid looping forever,+-- we limit the number of retries, and grow the size with each retry. If we+-- retry too many times then the whole generator is discarded.+-- mapMaybe :: (MonadGen m, GenBase m ~ Identity) => (a -> Maybe b) -> m a -> m b mapMaybe p gen0 = let@@ -1355,10 +1372,50 @@ in try 0 +-- | Generates a value that satisfies a predicate.+--+-- Shrinks of the generated value will also satisfy the predicate. From the+-- original generator's shrink tree, any values that fail the predicate will+-- be removed, along with their subsequent shrinks. Compared to 'filter',+-- shrinking may be faster but may also be less optimal.+--+-- The type is also more general, because the shrink behavior from 'filter'+-- would force the entire shrink tree to be evaluated when applied to an+-- impure tree.+--+-- This is essentially:+--+-- @+-- filterT p gen = 'mfilter' p gen '<|>' filterT p gen+-- @+--+-- But that could loop forever, if the predicate will never pass or will only+-- pass at a larger size than we're currently running at. We differ from the+-- above in keeping some state to avoid that. We limit the number of retries,+-- and grow the size with each retry. If we retry too many times then the+-- whole generator is discarded.+-- filterT :: MonadGen m => (a -> Bool) -> m a -> m a filterT p = mapMaybeT (fromPred p) +-- | Generates a value which is the result of the given function returning a+-- 'Just'.+--+-- The original generator's shrink tree will be retained, with values+-- returning 'Nothing' removed. Subsequent shrinks of those values will be+-- retained. Compared to 'mapMaybeT', shrinking may be slower but will be+-- optimal.+--+-- The type is also more general, because the shrink behavior from 'mapMaybe'+-- would force the entire shrink tree to be evaluated when applied to an+-- impure tree.+--+-- It's possible that the function will never return 'Just', or will only do+-- so a larger size than we're currently running at. To avoid looping forever,+-- we limit the number of retries, and grow the size with each retry. If we+-- retry too many times then the whole generator is discarded.+-- mapMaybeT :: MonadGen m => (a -> Maybe b) -> m a -> m b mapMaybeT p gen0 = let@@ -1744,6 +1801,20 @@ -- | Generate a sample from a generator. --+-- This function is useful for examining a 'Gen' in GHCi or other contexts.+-- It is not appropriate for use in a test suite directly. You will only+-- get a single sample from this function, and it will not give you+-- a property test. The seed is random, so the test is not deterministic.+--+-- If you only want a single test to run, then use @'withTests' 1@:+--+-- @+-- prop_OnlyRunOnce :: Property+-- prop_OnlyRunOnce =+-- 'withTests' 1 $ 'property' $ do+-- i <- Gen.int+-- i /== 0+-- @ sample :: MonadIO m => Gen a -> m a sample gen = liftIO $
src/Hedgehog/Internal/Property.hs view
@@ -136,10 +136,10 @@ import Control.Applicative (Alternative(..)) import Control.DeepSeq (NFData, rnf)+import Control.Exception.Safe (MonadThrow, MonadCatch)+import Control.Exception.Safe (SomeException(..), displayException) import Control.Monad (MonadPlus(..), (<=<)) import Control.Monad.Base (MonadBase(..))-import Control.Monad.Catch (MonadThrow(..), MonadCatch(..))-import Control.Monad.Catch (SomeException(..), displayException) import Control.Monad.Error.Class (MonadError(..)) import qualified Control.Monad.Fail as Fail import Control.Monad.IO.Class (MonadIO(..))
src/Hedgehog/Internal/Region.hs view
@@ -14,7 +14,7 @@ import Control.Concurrent.STM (STM, TVar) import qualified Control.Concurrent.STM.TMVar as TMVar import qualified Control.Concurrent.STM.TVar as TVar-import Control.Monad.Catch (MonadMask(..), bracket)+import Control.Exception.Safe (MonadMask, bracket) import Control.Monad.IO.Class (MonadIO(..)) import System.Console.Regions (ConsoleRegion, RegionLayout(..), LiftRegion(..))
src/Hedgehog/Internal/Runner.hs view
@@ -29,7 +29,7 @@ import Control.Concurrent.STM (TVar, atomically) import qualified Control.Concurrent.STM.TVar as TVar-import Control.Monad.Catch (MonadCatch(..), catchAll)+import Control.Exception.Safe (MonadCatch, catchAny) import Control.Monad.IO.Class (MonadIO(..)) import Data.Maybe (isJust) @@ -226,7 +226,7 @@ (Just t, Just s) test =- catchAll test0 (fail . show)+ catchAny test0 (fail . show) terminationCriteria = propertyTerminationCriteria cfg
src/Hedgehog/Internal/Seed.hs view
@@ -46,6 +46,7 @@ , mix64variant13 , mix32 , mixGamma+ , global ) where import Control.Monad.IO.Class (MonadIO(..))
src/Hedgehog/Internal/State.hs view
@@ -52,8 +52,8 @@ ) where import qualified Control.Concurrent.Async.Lifted as Async+import Control.Exception.Safe (MonadCatch) import Control.Monad (foldM, foldM_)-import Control.Monad.Catch (MonadCatch) import Control.Monad.State.Class (MonadState, get, put, modify) import Control.Monad.Morph (MFunctor(..)) import Control.Monad.Trans.Class (lift)@@ -170,8 +170,8 @@ -- type of variable because it is used in both the generation and the -- execution phase. ----- The order of arguments makes 'Var' 'HTraverable', which is how 'Symbolic'--- values are turned into 'Concrete' ones.+-- The order of arguments makes 'Var' 'FunctorB' and 'TraversableB', which is+-- how 'Symbolic' values are turned into 'Concrete' ones. -- newtype Var a v = Var (v a)
src/Hedgehog/Internal/Tree.hs view
@@ -49,11 +49,15 @@ , renderT ) where -import Control.Applicative (Alternative(..), liftA2)+#if !MIN_VERSION_base(4,18,0)+import Control.Applicative (liftA2)+#endif+import Control.Applicative (Alternative(..))+import Control.Exception.Safe (Exception) import Control.Monad (MonadPlus(..), guard, join) import Control.Monad.Base (MonadBase(..))+import Control.Monad.Catch (MonadThrow(throwM), MonadCatch(catch)) import Control.Monad.Trans.Control ()-import Control.Monad.Catch (MonadThrow(..), MonadCatch(..), Exception) import Control.Monad.Error.Class (MonadError(..)) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Morph (MFunctor(..), MMonad(..), generalize)@@ -184,7 +188,7 @@ pure . NodeT x $ fmap (expand f) xs ++ unfoldForest f x --- | Throw away @n@ levels of a tree's children.+-- | Throw away all but the top @n@ levels of a tree's children. -- -- /@prune 0@ will throw away all of a tree's children./ --