From cdf63bc69dcec63e698e3f30eb978af4d2a1269a Mon Sep 17 00:00:00 2001 From: Vladimir Ciobanu Date: Thu, 29 Oct 2020 16:26:53 +0200 Subject: [PATCH 1/2] Add (Co)Arbitrary instances for Lazy Lists. --- src/Test/QuickCheck/Arbitrary.purs | 9 ++++++++- src/Test/QuickCheck/Gen.purs | 5 +++++ test/Main.purs | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Test/QuickCheck/Arbitrary.purs b/src/Test/QuickCheck/Arbitrary.purs index a547778..5136a29 100644 --- a/src/Test/QuickCheck/Arbitrary.purs +++ b/src/Test/QuickCheck/Arbitrary.purs @@ -27,6 +27,7 @@ import Data.Identity (Identity(..)) import Data.Int (toNumber) import Data.Lazy (Lazy, defer, force) import Data.List (List) +import Data.List.Lazy as Lazy import Data.List.NonEmpty (NonEmptyList(..)) import Data.Maybe (Maybe(..), fromJust) import Data.Newtype (wrap) @@ -42,7 +43,7 @@ import Partial.Unsafe (unsafePartial) import Prim.Row as Row import Prim.RowList as RL import Record as Record -import Test.QuickCheck.Gen (Gen, arrayOf, chooseInt, elements, listOf, oneOf, perturbGen, repeatable, sized, uniform) +import Test.QuickCheck.Gen (Gen, arrayOf, chooseInt, elements, lazyListOf, listOf, oneOf, perturbGen, repeatable, sized, uniform) import Type.Data.RowList (RLProxy(..)) -- | The `Arbitrary` class represents those types whose values can be @@ -168,6 +169,12 @@ instance arbitraryList :: Arbitrary a => Arbitrary (List a) where instance coarbList :: Coarbitrary a => Coarbitrary (List a) where coarbitrary = foldl (\f x -> f <<< coarbitrary x) identity +instance arbitraryLazyList :: Arbitrary a => Arbitrary (Lazy.List a) where + arbitrary = sized \n -> chooseInt zero n >>= flip lazyListOf arbitrary + +instance coarbLazyList :: Coarbitrary a => Coarbitrary (Lazy.List a) where + coarbitrary = foldl (\f x -> f <<< coarbitrary x) identity + instance arbitraryIdentity :: Arbitrary a => Arbitrary (Identity a) where arbitrary = Identity <$> arbitrary diff --git a/src/Test/QuickCheck/Gen.purs b/src/Test/QuickCheck/Gen.purs index b7ffc25..951c608 100644 --- a/src/Test/QuickCheck/Gen.purs +++ b/src/Test/QuickCheck/Gen.purs @@ -17,6 +17,7 @@ module Test.QuickCheck.Gen , frequency , arrayOf , arrayOf1 + , lazyListOf , listOf , vectorOf , elements @@ -43,6 +44,7 @@ import Data.Enum (class BoundedEnum, fromEnum, toEnum) import Data.Foldable (fold) import Data.Int (toNumber, floor) import Data.List (List(..), toUnfoldable) +import Data.List.Lazy as Lazy import Data.Maybe (fromMaybe, fromJust) import Data.Monoid.Additive (Additive(..)) import Data.Newtype (unwrap) @@ -200,6 +202,9 @@ replicateMRec k gen = tailRecM go (Tuple Nil k) listOf :: forall a. Int -> Gen a -> Gen (List a) listOf = replicateMRec +lazyListOf :: forall a. Int -> Gen a -> Gen (Lazy.List a) +lazyListOf n gen = Lazy.fromFoldable <$> listOf n gen + -- | Create a random generator which generates a vector of random values of a specified size. vectorOf :: forall a. Int -> Gen a -> Gen (Array a) vectorOf k g = toUnfoldable <$> listOf k g diff --git a/test/Main.purs b/test/Main.purs index 1a218cc..9e2282c 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -16,7 +16,7 @@ import Partial.Unsafe (unsafePartial) import Test.Assert (assert) import Test.QuickCheck (class Testable, quickCheck, (/=?), (<=?), (=?), (>?)) import Test.QuickCheck.Arbitrary (arbitrary, genericArbitrary, class Arbitrary) -import Test.QuickCheck.Gen (Gen, vectorOf, randomSample', resize, Size, runGen, sized) +import Test.QuickCheck.Gen (Gen, lazyListOf, vectorOf, randomSample', resize, Size, runGen, sized) import Random.LCG (mkSeed) data Foo a = F0 a | F1 a a | F2 { foo :: a, bar :: Array a } @@ -55,6 +55,7 @@ main = do log "Testing stack safety of Gen" logShow =<< go 20000 logShow =<< go 100000 + logShow =<< go' 100000 log "Generating via Generic" logShow =<< randomSample' 10 (arbitrary :: Gen (Foo Int)) @@ -86,6 +87,7 @@ main = do where go n = map (sum <<< unsafeHead) $ randomSample' 1 (vectorOf n (arbitrary :: Gen Int)) + go' n = map (sum <<< unsafeHead) $ randomSample' 1 (lazyListOf n (arbitrary :: Gen Int)) unsafeHead :: forall x. Array x -> x unsafeHead xs = unsafePartial (head xs) From b15e93d89085e02124710854b41a824858bc9d12 Mon Sep 17 00:00:00 2001 From: Vladimir Ciobanu Date: Thu, 29 Oct 2020 16:32:50 +0200 Subject: [PATCH 2/2] Minor refactor, also test 'listOf'. --- test/Main.purs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index 9e2282c..4952a65 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,22 +2,22 @@ module Test.Main where import Prelude -import Effect (Effect) -import Effect.Console (log, logShow) -import Effect.Exception (try) import Control.Monad.Gen.Class as MGen import Data.Array.Partial (head) import Data.Either (isLeft) -import Data.Foldable (sum) +import Data.Foldable (class Foldable, sum) import Data.Generic.Rep (class Generic) import Data.Generic.Rep.Show (genericShow) import Data.Tuple (fst) +import Effect (Effect) +import Effect.Console (log, logShow) +import Effect.Exception (try) import Partial.Unsafe (unsafePartial) +import Random.LCG (mkSeed) import Test.Assert (assert) import Test.QuickCheck (class Testable, quickCheck, (/=?), (<=?), (=?), (>?)) import Test.QuickCheck.Arbitrary (arbitrary, genericArbitrary, class Arbitrary) -import Test.QuickCheck.Gen (Gen, lazyListOf, vectorOf, randomSample', resize, Size, runGen, sized) -import Random.LCG (mkSeed) +import Test.QuickCheck.Gen (Gen, Size, lazyListOf, listOf, randomSample', resize, runGen, sized, vectorOf) data Foo a = F0 a | F1 a a | F2 { foo :: a, bar :: Array a } derive instance genericFoo :: Generic (Foo a) _ @@ -47,15 +47,16 @@ main = do assert (testResize (resize)) log "Try with some little Gens first" - logShow =<< go 10 - logShow =<< go 100 - logShow =<< go 1000 - logShow =<< go 10000 + logShow =<< go vectorOf 10 + logShow =<< go vectorOf 100 + logShow =<< go vectorOf 1000 + logShow =<< go vectorOf 10000 log "Testing stack safety of Gen" - logShow =<< go 20000 - logShow =<< go 100000 - logShow =<< go' 100000 + logShow =<< go vectorOf 20000 + logShow =<< go vectorOf 100000 + logShow =<< go listOf 100000 + logShow =<< go lazyListOf 100000 log "Generating via Generic" logShow =<< randomSample' 10 (arbitrary :: Gen (Foo Int)) @@ -86,8 +87,8 @@ main = do quickCheckFail $ 4 <=? 3 where - go n = map (sum <<< unsafeHead) $ randomSample' 1 (vectorOf n (arbitrary :: Gen Int)) - go' n = map (sum <<< unsafeHead) $ randomSample' 1 (lazyListOf n (arbitrary :: Gen Int)) + go :: forall f. Foldable f => (Int -> Gen Int -> Gen (f Int)) -> Int -> Effect Int + go f n = map (sum <<< unsafeHead) $ randomSample' 1 (f n (arbitrary :: Gen Int)) unsafeHead :: forall x. Array x -> x unsafeHead xs = unsafePartial (head xs)