Skip to content

Commit

Permalink
Merge pull request #276 from jystic/topic/tree-interleave
Browse files Browse the repository at this point in the history
Improved, and dare I say minimal, shrinking of lists
  • Loading branch information
jacobstanley committed Apr 28, 2019
2 parents 25f7a6d + 7cf1baf commit ff11493
Show file tree
Hide file tree
Showing 14 changed files with 757 additions and 417 deletions.
1 change: 1 addition & 0 deletions hedgehog-example/hedgehog-example.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ library
Test.Example.Basic
, Test.Example.Coverage
, Test.Example.Exception
, Test.Example.List
, Test.Example.QuickCheck
, Test.Example.References
, Test.Example.Registry
Expand Down
132 changes: 132 additions & 0 deletions hedgehog-example/src/Test/Example/List.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Test.Example.List where

import Control.Monad.Zip (mzip)
import qualified Control.Monad.State.Lazy as Lazy
import qualified Control.Monad.State.Class as State
import qualified Control.Monad.Writer.Lazy as Lazy
import qualified Control.Monad.Writer.Class as Writer
import Control.Monad.Morph (MFunctor(..))

import Data.Maybe (fromJust)
import Data.Foldable (toList)
import Data.Monoid (Sum(..))
import qualified Data.List as List

import Hedgehog
import qualified Hedgehog.Range as Range

import qualified Hedgehog.Internal.Gen as Gen
import qualified Hedgehog.Internal.Shrink as Shrink
import Hedgehog.Internal.Source (HasCallStack, withFrozenCallStack)
import Hedgehog.Internal.Tree (Tree)
import qualified Hedgehog.Internal.Tree as Tree


genInt :: MonadGen m => m Int
genInt =
Gen.int (Range.constant 0 2)

genList :: MonadGen m => m a -> m [a]
genList =
Gen.list (Range.constant 0 2)

prop_list :: Property
prop_list =
property $ do
let
cond :: [Int] -> Bool
cond xs =
all (>= length xs) xs

renderTree :: Tree [Int] -> String
renderTree =
Tree.render .
fmap show .
fmap (\xs -> (cond xs, xs))

ts <- forAllWith renderTree (Gen.toTree $ genList genInt)
xs0 <- forAll (Gen.fromTree ts)

assert (cond xs0)

newtype Index =
Index Int
deriving (Eq, Num, Show)

genStateInt :: (MonadGen m, State.MonadState Index m) => m (Index, Int)
genStateInt = do
x <- genInt
State.modify (+ 1)
index <- State.get
pure (index, x)

prop_state_list :: Property
prop_state_list =
property $ do
let
cond :: [(a, Int)] -> Bool
cond xs =
all ((>= length xs) . snd) xs

renderTree :: Tree [(Index, Int)] -> String
renderTree =
Tree.render .
fmap show .
fmap (\xs -> (cond xs, xs))

ts <- forAllWith renderTree (Gen.toTree $ hoist (`Lazy.evalStateT` 0) $ genList genStateInt)
xs0 <- forAll (Gen.fromTree ts)

assert (cond xs0)

data Log =
List Int
| Int Int
deriving (Show)

genWriterList :: (MonadGen m, Writer.MonadWriter [Log] m) => m a -> m [a]
genWriterList gen = do
xs <- Gen.list (Range.constant 0 2) gen
Writer.tell [List (length xs)]
pure xs

genWriterInt :: (MonadGen m, Writer.MonadWriter [Log] m) => m Int
genWriterInt = do
x <- genInt
Writer.tell [Int x]
pure x

renderLog :: [Log] -> String
renderLog xs =
concat . flip fmap xs $ \case
List n ->
" L" ++ show n
Int n ->
show n

prop_writer_list :: Property
prop_writer_list =
property $ do
let
cond :: [Int] -> Bool
cond xs =
all ((>= length xs)) xs

renderTree =
Tree.render .
fmap (\(ns, ws) -> show (cond ns, ns) ++ " (" ++ renderLog ws ++ ")")

ts <- forAllWith renderTree (Gen.toTree . Lazy.runWriterT $ genWriterList genWriterInt)
(xs0, _) <- forAll (Gen.fromTree ts)

assert (cond xs0)


tests :: IO Bool
tests =
checkParallel $$(discover)
2 changes: 1 addition & 1 deletion hedgehog-quickcheck/src/Hedgehog/Gen/QuickCheck.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import qualified Test.QuickCheck.Random as QuickCheck

seedQCGen :: MonadGen m => m QuickCheck.QCGen
seedQCGen =
QuickCheck.mkQCGen <$> Gen.lift (Gen.integral_ Range.constantBounded)
QuickCheck.mkQCGen <$> fromGenT (Gen.integral_ Range.constantBounded)

-- | Create a Hedgehog 'Gen' from a QuickCheck 'QuickCheck.Gen'.
--
Expand Down
8 changes: 4 additions & 4 deletions hedgehog-quickcheck/src/Test/QuickCheck/Hedgehog.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ module Test.QuickCheck.Hedgehog (
) where

import Hedgehog
import Hedgehog.Internal.Gen (runGen)
import Hedgehog.Internal.Gen (evalGen)
import qualified Hedgehog.Internal.Seed as Seed
import Hedgehog.Internal.Tree (NodeT(..), runTree)
import Hedgehog.Internal.Tree (treeValue)

import qualified Test.QuickCheck as QuickCheck

Expand All @@ -30,10 +30,10 @@ hedgehog gen =
else do
seed <- genSeed
size <- QuickCheck.sized (pure . fromIntegral)
case runGen size seed gen of
case evalGen size seed gen of
Nothing ->
loop (n - 1)
Just x ->
pure . nodeValue $ runTree x
pure $ treeValue x
in
loop (100 :: Int)
1 change: 1 addition & 0 deletions hedgehog/hedgehog.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ test-suite test
hedgehog
, base >= 3 && < 5
, containers >= 0.4 && < 0.7
, mtl >= 2.1 && < 2.3
, pretty-show >= 1.6 && < 1.10
, semigroups >= 0.16 && < 0.19
, text >= 1.1 && < 1.3
Expand Down
8 changes: 4 additions & 4 deletions hedgehog/src/Hedgehog.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ module Hedgehog (

, forAll
, forAllWith
, classify
, cover
, discard

, check
Expand Down Expand Up @@ -112,6 +110,8 @@ module Hedgehog (
, evalExceptT

-- * Coverage
, classify
, cover
, label
, collect

Expand All @@ -133,7 +133,7 @@ module Hedgehog (
, Opaque(..)

-- * Transformers
, distribute
, distributeT

-- * Functors
, HTraversable(..)
Expand All @@ -150,7 +150,7 @@ module Hedgehog (

import Data.Functor.Classes (Eq1, eq1, Ord1, compare1, Show1, showsPrec1)

import Hedgehog.Internal.Distributive (Distributive(..))
import Hedgehog.Internal.Distributive (distributeT)
import Hedgehog.Internal.Gen (Gen, GenT, MonadGen(..))
import Hedgehog.Internal.HTraversable (HTraversable(..))
import Hedgehog.Internal.Opaque (Opaque(..))
Expand Down
5 changes: 1 addition & 4 deletions hedgehog/src/Hedgehog/Gen.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
module Hedgehog.Gen (
-- * Combinators
lift

-- ** Shrinking
, shrink
shrink
, prune

-- ** Size
Expand Down
Loading

0 comments on commit ff11493

Please sign in to comment.