packages feed

quickcheck-classes-base 0.6.0.0 → 0.6.1.0

raw patch · 9 files changed

+130/−16 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Test.QuickCheck.Classes.Base: substitutiveEqLaws :: forall a. (Eq a, Arbitrary a, CoArbitrary a, Function a, Show a) => Proxy a -> Laws

Files

changelog.md view
@@ -4,7 +4,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). -## [0.6.0.0] - 2019-08-07+Note that since `quickcheck-classes` reexports larges parts of+`quickcheck-classes-base`, changelog entries that deal with any of the+classes from `base` are duplicated across the two changelogs.++## [0.6.1.0] - 2020-09-09+### Added+- Laws for `abs` and `signum`+- Storable Set-Set Law (resolves issue 101).+- Add laws for `quotRem` and `divMod`.+- Use non-commutative monoid for bifoldable tests (resolves issue 98)+- `substitutiveEqLaws`, which tests for Eq substitutivity.+- Negation law check for `Eq`.+- Document that users can provide their own `Laws`.++## [0.6.0.0] - 2019-08-08 ### Added - Initial release. This factor out a subset of laws tests   from `quickcheck-classes` and depend on this library that
quickcheck-classes-base.cabal view
@@ -1,5 +1,5 @@ name: quickcheck-classes-base-version: 0.6.0.0+version: 0.6.1.0 synopsis: QuickCheck common typeclasses from `base` description:   This libary is a minimal variant of `quickcheck-classes` that@@ -87,9 +87,10 @@     , QuickCheck >= 2.7     , transformers >= 0.3 && < 0.6     , containers >= 0.4.2.1-    , semigroups >= 0.17     , tagged     , fail+  if impl(ghc < 8.0)+    build-depends: semigroups >= 0.17   if impl(ghc > 7.4) && impl(ghc < 7.6)     build-depends: ghc-prim   if impl(ghc > 8.5)
src/Test/QuickCheck/Classes/Base.hs view
@@ -22,6 +22,7 @@   , bitsLaws #endif   , eqLaws+  , substitutiveEqLaws   , numLaws   , integralLaws   , ixLaws@@ -62,7 +63,7 @@     -- ** Binary type constructors   , bifoldableLaws   , bifunctorLaws-  , bitraversableLaws +  , bitraversableLaws   , categoryLaws   , commutativeCategoryLaws #endif
src/Test/QuickCheck/Classes/Bifoldable.hs view
@@ -31,10 +31,10 @@ -- | Tests the following 'Bifunctor' properties: -- -- [/Bifold Identity/]---   @'bifold' ≡ 'bifoldMap' 'id' 'id'@  +--   @'bifold' ≡ 'bifoldMap' 'id' 'id'@ -- [/BifoldMap Identity/] --   @'bifoldMap' f g ≡ 'bifoldr' ('mappend' '.' f) ('mappend' '.' g) 'mempty'@--- [/Bifoldr Identity/] +-- [/Bifoldr Identity/] --   @'bifoldr' f g z t ≡ 'appEndo' ('bifoldMap' ('Endo' '.' f) ('Endo' '.' g) t) z@ -- -- /Note/: This property test is only available when this package is built with@@ -80,7 +80,7 @@   (Bifoldable f, Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f) #endif   => proxy f -> Property-bifoldableFunctorLaw _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap Sum Sum x == (bifold (bimap Sum Sum x))+bifoldableFunctorLaw _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap mkMonoid mkMonoid x == (bifold (bimap mkMonoid mkMonoid x))  bifoldableFunctorImplication :: forall proxy f. #if HAVE_QUANTIFIED_CONSTRAINTS@@ -89,7 +89,7 @@   (Bifoldable f, Bifunctor f, Eq2 f, Show2 f, Arbitrary2 f) #endif   => proxy f -> Property-bifoldableFunctorImplication _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap Sum Sum (bimap Product Product x) == bifoldMap (Sum . Product) (Sum . Product) x+bifoldableFunctorImplication _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap mkMonoid mkMonoid (bimap mkMonoid mkMonoid x) == bifoldMap (mkMonoid . mkMonoid) (mkMonoid . mkMonoid) x  bifoldIdentity :: forall proxy f. #if HAVE_QUANTIFIED_CONSTRAINTS@@ -98,7 +98,7 @@   (Bifoldable f, Eq2 f, Show2 f, Arbitrary2 f) #endif   => proxy f -> Property-bifoldIdentity _ = property $ \(Apply2 (x :: f (Sum Integer) (Sum Integer))) -> (bifold x) == (bifoldMap id id x)+bifoldIdentity _ = property $ \(Apply2 (x :: f [Integer] [Integer])) -> (bifold x) == (bifoldMap id id x)  bifoldMapIdentity :: forall proxy f. #if HAVE_QUANTIFIED_CONSTRAINTS@@ -107,7 +107,7 @@   (Bifoldable f, Eq2 f, Show2 f, Arbitrary2 f) #endif   => proxy f -> Property-bifoldMapIdentity _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap Sum Sum x == bifoldr (mappend . Sum) (mappend . Sum) mempty x+bifoldMapIdentity _ = property $ \(Apply2 (x :: f Integer Integer)) -> bifoldMap mkMonoid mkMonoid x == bifoldr (mappend . mkMonoid) (mappend . mkMonoid) mempty x  bifoldrIdentity :: forall proxy f. #if HAVE_QUANTIFIED_CONSTRAINTS@@ -119,6 +119,8 @@ bifoldrIdentity _ = property $ \(Apply2 (x :: f Integer Integer)) ->   let f _ _ = mempty       g _ _ = mempty-  in bifoldr f g (mempty :: Sum Integer) x == appEndo (bifoldMap (Endo . f) (Endo . g) x) mempty+  in bifoldr f g (mempty :: [Integer]) x == appEndo (bifoldMap (Endo . f) (Endo . g) x) mempty +mkMonoid :: a -> [a]+mkMonoid x = [x] #endif
src/Test/QuickCheck/Classes/Eq.hs view
@@ -4,22 +4,26 @@  module Test.QuickCheck.Classes.Eq   ( eqLaws+  , substitutiveEqLaws   ) where  import Data.Proxy (Proxy) import Test.QuickCheck hiding ((.&.)) import Test.QuickCheck.Property (Property)+import Test.QuickCheck.Function  import Test.QuickCheck.Classes.Internal (Laws(..))  -- | Tests the following properties: -- -- [/Transitive/]---   @a == b ∧ b == c ⇒ a == c@+--   @a '==' b ∧ b '==' c ⇒ a '==' c@ -- [/Symmetric/]---   @a == b ⇒ b == a@+--   @a '==' b ⇒ b '==' a@ -- [/Reflexive/]---   @a == a@+--   @a '==' a@+-- [/Negation/]+--   @x '/=' y '==' 'not' (x '==' y)@ -- -- Some of these properties involve implication. In the case that -- the left hand side of the implication arrow does not hold, we@@ -48,3 +52,21 @@  eqReflexive :: forall a. (Show a, Eq a, Arbitrary a) => Proxy a -> Property eqReflexive _ = property $ \(a :: a) -> a == a++eqNegation :: forall a. (Show a, Eq a, Arbitrary a) => Proxy a -> Property+eqNegation _ = property $ \(x :: a) y -> (x /= y) == not (x == y)++-- | Tests the following properties:+--+-- [/Substitutive/]+--   @x '==' y ⇒ f x '==' f y@+--+-- /Note/: This does not test `eqLaws`.+-- If you want to use this, You should use it in addition to `eqLaws`.+substitutiveEqLaws :: forall a. (Eq a, Arbitrary a, CoArbitrary a, Function a, Show a) => Proxy a -> Laws+substitutiveEqLaws _ = Laws "Eq"+  [ ("Substitutivity"+    , property $ \(x :: a) y (f :: Fun a Integer) ->+        x == y ==> applyFun f x == applyFun f y+    )+  ]
src/Test/QuickCheck/Classes/Integral.hs view
@@ -20,11 +20,17 @@ --   @(div x y) * y + (mod x y) ≡ x@ -- [/Integer Roundtrip/] --   @fromInteger (toInteger x) ≡ x@+-- [/QuotRem is (Quot, Rem)/]+--   @quotRem x y ≡ (quot x y, rem x y)@+-- [/DivMod is (Div, Mod)/]+--   @divMod x y ≡ (div x y, mod x y)@ integralLaws :: (Integral a, Arbitrary a, Show a) => Proxy a -> Laws integralLaws p = Laws "Integral"   [ ("Quotient Remainder", integralQuotientRemainder p)   , ("Division Modulus", integralDivisionModulus p)   , ("Integer Roundtrip", integralIntegerRoundtrip p)+  , ("QuotRem is (Quot, Rem)", integralQuotRem p)+  , ("DivMod is (Div, Mod)", integralDivMod p)   ]  integralQuotientRemainder :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property@@ -50,3 +56,19 @@   (\x -> fromInteger (toInteger x))   "x"   (\x -> x)++integralQuotRem :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property+integralQuotRem _ = myForAllShrink False (\(_,y) -> y /= 0)+  (\(x :: a, y) -> ["x = " ++ show x, "y = " ++ show y])+  "quotRem x y"+  (\(x,y) -> quotRem x y)+  "(quot x y, rem x y)"+  (\(x,y) -> (quot x y, rem x y))++integralDivMod :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property+integralDivMod _ = myForAllShrink False (\(_,y) -> y /= 0)+  (\(x :: a, y) -> ["x = " ++ show x, "y = " ++ show y])+  "divMod x y"+  (\(x,y) -> divMod x y)+  "(div x y, mod x y)"+  (\(x,y) -> (div x y, mod x y))
src/Test/QuickCheck/Classes/Internal.hs view
@@ -15,14 +15,14 @@ -- public API and is not subject to PVP. It is used by other -- modules in @quickcheck-classes-base@ and by modules in the -- @quickcheck-classes@ library as well. Functions and types--- in this module are either auxiliary functions that are reused +-- in this module are either auxiliary functions that are reused -- by many different laws tests, or they are compatibility shims -- that make it possible to build with older versions GHC and -- transformers. module Test.QuickCheck.Classes.Internal   ( -- * Common Types and Functions     Laws(..)-  , foldMapA +  , foldMapA   , myForAllShrink   -- Modifiers   , SmallList(..)@@ -120,6 +120,12 @@ #endif  -- | A set of laws associated with a typeclass.+--+--   /Note/: Most of the top-level functions provided+--   by this library have the shape+--   `forall a. (Ctx a) => Proxy a -> Laws`. You can just+--   as easily provide your own `Laws` in libraries/test suites+--   using regular QuickCheck machinery. data Laws = Laws   { lawsTypeclass :: String     -- ^ Name of the typeclass whose laws are tested
src/Test/QuickCheck/Classes/Num.hs view
@@ -38,6 +38,12 @@ --   @'negate' a '+' a ≡ 0@ -- [/Subtraction/] --   @a '+' 'negate' b ≡ a '-' b@+-- [/Abs Is Idempotent/]+--   @'abs' ('abs' a) ≡ 'abs' a+-- [/Signum Is Idempotent/]+--   @'signum' ('signum' a) ≡ 'signum' a+-- [/Product Of Abs And Signum Is Id/]+--   @'abs' a * 'signum' a ≡ a@ numLaws :: (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws numLaws p = Laws "Num"   [ ("Additive Commutativity", numCommutativePlus p)@@ -52,6 +58,9 @@   , ("Multiplicative Right Annihilation", numRightAnnihilation p)   , ("Additive Inverse", numAdditiveInverse p)   , ("Subtraction", numSubtraction p)+  , ("Abs Is Idempotent", absIdempotence p)+  , ("Signum Is Idempotent", signumIdempotence p)+  , ("Product Of Abs And Signum Is Id", absSignumId p)   ]  numLeftMultiplicationDistributes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property@@ -149,3 +158,27 @@   (\(a,b) -> a + negate b)   "a - b"   (\(a,b) -> a - b)++absIdempotence :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property+absIdempotence _ = myForAllShrink True (const True)+  (\(a :: a) -> ["a = " ++ show a])+  "abs (abs a)"+  (abs . abs)+  "abs a"+  abs++signumIdempotence :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property+signumIdempotence _ = myForAllShrink True (const True)+  (\(a :: a) -> ["a = " ++ show a])+  "signum (signum a)"+  (signum . signum)+  "signum a"+  signum++absSignumId :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property+absSignumId _ = myForAllShrink True (const True)+  (\(a :: a) -> ["a = " ++ show a])+  "abs a * signum a"+  (\a -> abs a * signum a)+  "a"+  id
src/Test/QuickCheck/Classes/Storable.hs view
@@ -36,6 +36,7 @@ storableLaws p = Laws "Storable"   [ ("Set-Get (you get back what you put in)", storableSetGet p)   , ("Get-Set (putting back what you got out has no effect)", storableGetSet p)+  , ("Set-Set (if you set something twice, the first set is inconsequential", storableSetSet p)   , ("List Conversion Roundtrips", storableList p)   , ("peekElemOff a i ≡ peek (plusPtr a (i * sizeOf undefined))", storablePeekElem p)   , ("peekElemOff a i x ≡ poke (plusPtr a (i * sizeOf undefined)) x ≡ id ", storablePokeElem p)@@ -125,6 +126,18 @@     free ptrA     free ptrB     return res++storableSetSet :: forall a. (Storable a, Eq a, Arbitrary a, Show a) => Proxy a -> Property+storableSetSet _ = property $ \(x :: a) (y :: a) (as :: [a]) -> (not (L.null as)) ==> do+  let len = L.length as+  ix <- choose (0,len-1)+  return $ unsafePerformIO $ do+    ptr <- arrayArbitrary len+    pokeElemOff ptr ix x+    pokeElemOff ptr ix y+    atIx <- peekElemOff ptr ix+    free ptr+    return $ atIx == y  storableList :: forall a. (Storable a, Eq a, Arbitrary a, Show a) => Proxy a -> Property storableList _ = property $ \(as :: [a]) -> unsafePerformIO $ do