smallcheck 1.1.5 → 1.1.6
raw patch · 9 files changed
+228/−105 lines, 9 filesnew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Test.SmallCheck.Series: instance Test.SmallCheck.Series.CoSerial m a => Test.SmallCheck.Series.CoSerial m (GHC.Base.Maybe a)
- Test.SmallCheck.Series: instance Test.SmallCheck.Series.Serial m a => Test.SmallCheck.Series.Serial m (GHC.Base.Maybe a)
+ Test.SmallCheck.Series: instance Test.SmallCheck.Series.CoSerial m a => Test.SmallCheck.Series.CoSerial m (GHC.Maybe.Maybe a)
+ Test.SmallCheck.Series: instance Test.SmallCheck.Series.Serial m a => Test.SmallCheck.Series.Serial m (GHC.Maybe.Maybe a)
- Test.SmallCheck.Drivers: PropertyFalse :: (Maybe Reason) -> PropertyFailure
+ Test.SmallCheck.Drivers: PropertyFalse :: Maybe Reason -> PropertyFailure
- Test.SmallCheck.Drivers: PropertyTrue :: (Maybe Reason) -> PropertySuccess
+ Test.SmallCheck.Drivers: PropertyTrue :: Maybe Reason -> PropertySuccess
- Test.SmallCheck.Series: (>>-) :: MonadLogic m => m a -> a -> m b -> m b
+ Test.SmallCheck.Series: (>>-) :: MonadLogic m => m a -> (a -> m b) -> m b
Files
- CHANGELOG.md +5/−0
- README.md +5/−13
- Test/SmallCheck.hs +3/−1
- Test/SmallCheck/Drivers.hs +8/−6
- Test/SmallCheck/Property.hs +18/−10
- Test/SmallCheck/Property/Result.hs +6/−5
- Test/SmallCheck/Series.hs +109/−21
- Test/SmallCheck/SeriesMonad.hs +30/−16
- smallcheck.cabal +44/−33
CHANGELOG.md view
@@ -1,6 +1,11 @@ Changes ======= +Version 1.1.6+-------------++* Mark modules as `Safe`, not just `Trustworthy`.+ Version 1.1.5 -------------
README.md view
@@ -14,25 +14,17 @@ * Read the [documentation][haddock] * If you have experience with QuickCheck, [read the comparison of QuickCheck and SmallCheck][comparison]-* Install it and give it a try! +* Install it and give it a try! `cabal update; cabal install smallcheck` * Read the [paper][paper] or [other materials][oldpage] from the original authors of SmallCheck (note that that information might be somewhat outdated) * If you see something that can be improved, please [submit an issue][issues] * Check out [the source code][github] at GitHub -[haddock]: http://hackage.haskell.org/packages/archive/smallcheck/latest/doc/html/Test-SmallCheck.html+[haddock]: http://hackage.haskell.org/package/smallcheck/docs/Test-SmallCheck.html [hackage]: http://hackage.haskell.org/package/smallcheck [paper]: http://www.cs.york.ac.uk/fp/smallcheck/smallcheck.pdf [oldpage]: http://www.cs.york.ac.uk/fp/smallcheck/-[comparison]: https://github.com/feuerbach/smallcheck/wiki/Comparison-with-QuickCheck-[github]: https://github.com/feuerbach/smallcheck-[issues]: https://github.com/feuerbach/smallcheck/issues--Maintainers--------------[Roman Cheplyaka](https://github.com/feuerbach) is the primary maintainer.--[Oliver Charles](https://github.com/ocharles) is the backup maintainer. Please-get in touch with him if the primary maintainer cannot be reached.+[comparison]: https://github.com/Bodigrim/smallcheck/wiki/Comparison-with-QuickCheck+[github]: https://github.com/Bodigrim/smallcheck+[issues]: https://github.com/Bodigrim/smallcheck/issues
Test/SmallCheck.hs view
@@ -12,9 +12,11 @@ -- -- For pointers to other sources of information about SmallCheck, please refer -- to the README at--- <https://github.com/feuerbach/smallcheck/blob/master/README.md>+-- <https://github.com/Bodigrim/smallcheck/blob/master/README.md> --------------------------------------------------------------------+ {-# LANGUAGE Safe #-}+ module Test.SmallCheck ( -- * Constructing tests
Test/SmallCheck/Drivers.hs view
@@ -8,8 +8,10 @@ -- You should only need this module if you wish to create your own way to -- run SmallCheck tests --------------------------------------------------------------------+ {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE Safe #-}+{-# LANGUAGE Safe #-}+ module Test.SmallCheck.Drivers ( smallCheck, smallCheckM, smallCheckWithHook, test,@@ -20,7 +22,7 @@ import Control.Monad (when) import Test.SmallCheck.Property import Test.SmallCheck.Property.Result-import Text.Printf+import Text.Printf (printf) import Data.IORef (readIORef, writeIORef, IORef, newIORef) -- NB: explicit import list to avoid name clash with modifyIORef' -- | A simple driver that runs the test in the 'IO' monad and prints the@@ -31,11 +33,11 @@ let testsRun = good + bad case mbEx of Nothing -> do- printf "Completed %d tests without failure.\n" $ testsRun+ printf "Completed %d tests without failure.\n" testsRun when (bad > 0) $- printf "But %d did not meet ==> condition.\n" $ bad+ printf "But %d did not meet ==> condition.\n" bad Just x -> do- printf "Failed test no. %d.\n" $ testsRun+ printf "Failed test no. %d.\n" testsRun putStrLn $ ppFailure x runTestWithStats :: Testable IO a => Depth -> a -> IO ((Integer, Integer), Maybe PropertyFailure)@@ -69,7 +71,7 @@ -- -- * You need to analyse the results rather than just print them smallCheckM :: Testable m a => Depth -> a -> m (Maybe PropertyFailure)-smallCheckM d a = smallCheckWithHook d (const $ return ()) a+smallCheckM d = smallCheckWithHook d (const $ return ()) -- | Like `smallCheckM`, but allows to specify a monadic hook that gets -- executed after each test is run.
Test/SmallCheck/Property.hs view
@@ -9,11 +9,13 @@ -- -- Properties and tools to construct them. ---------------------------------------------------------------------{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeFamilies,- ScopedTypeVariables, DeriveDataTypeable #-} --- CPP is for Typeable1 vs Typeable-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} -- Are we using new, polykinded and derivable Typeable yet? #define NEWTYPEABLE MIN_VERSION_base(4,7,0)@@ -24,6 +26,7 @@ -- Trustworthy is needed because of the hand-written Typeable instance {-# LANGUAGE Trustworthy #-} #endif+ module Test.SmallCheck.Property ( -- * Constructors forAll, exists, existsUnique, over, (==>), monadic, changeDepth, changeDepth1,@@ -37,12 +40,17 @@ import Test.SmallCheck.Series import Test.SmallCheck.SeriesMonad import Test.SmallCheck.Property.Result-import Control.Monad-import Control.Monad.Logic-import Control.Monad.Reader-import Control.Applicative-import Data.Typeable+import Control.Arrow (first)+import Control.Monad (liftM, mzero)+import Control.Monad.Logic (MonadLogic, runLogicT, ifte, once, msplit, lnot)+import Control.Monad.Reader (Reader, runReader, lift, ask, local, reader)+import Control.Applicative (pure, (<$>), (<$))+import Data.Typeable (Typeable(..)) +#if !NEWTYPEABLE+import Data.Typeable (Typeable1, mkTyConApp, mkTyCon3, typeOf)+#endif+ ------------------------------ -- Property-related types ------------------------------@@ -354,7 +362,7 @@ PropertySeries (localDepth modifyDepth ss) (localDepth modifyDepth sf)- ((\(prop, args) -> (changeDepth modifyDepth prop, args)) <$>+ (first (changeDepth modifyDepth) <$> localDepth modifyDepth sc) -- | Quantify the function's argument over its 'series', but adjust the
Test/SmallCheck/Property/Result.hs view
@@ -1,5 +1,6 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, DefaultSignatures #-}-{-# LANGUAGE Safe #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE Safe #-}+ module Test.SmallCheck.Property.Result ( PropertySuccess(..) , PropertyFailure(..)@@ -8,7 +9,7 @@ , Argument ) where -import Text.PrettyPrint+import Text.PrettyPrint (Doc, empty, hsep, nest, render, text, (<+>), ($+$), ($$)) type Argument = String @@ -40,13 +41,13 @@ text "arguments satisfying the property:" $$ formatExample args1 s1 $$ formatExample args2 s2 where- formatExample args s = nest ind $ text "for" <+> prettyArgs args </> (pretty s)+ formatExample args s = nest ind $ text "for" <+> prettyArgs args </> pretty s pretty (CounterExample args f) = text "there" <+> text (plural args "exists" "exist") <+> prettyArgs args <+> text "such that"- </> (pretty f)+ </> pretty f pretty (PropertyFalse Nothing) = text "condition is false" pretty (PropertyFalse (Just s)) = text s
Test/SmallCheck/Series.hs view
@@ -23,12 +23,15 @@ -- the instances by hand. -------------------------------------------------------------------- -{-# LANGUAGE CPP, RankNTypes, MultiParamTypeClasses, FlexibleInstances,- GeneralizedNewtypeDeriving, FlexibleContexts, ScopedTypeVariables #-}--- The following is needed for generic instances-{-# LANGUAGE DefaultSignatures, FlexibleContexts, TypeOperators,- TypeSynonymInstances, FlexibleInstances, OverlappingInstances #-}-{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE Safe #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-} module Test.SmallCheck.Series ( -- {{{@@ -188,17 +191,18 @@ -- }}} ) where -import Control.Monad.Logic-import Control.Monad.Reader-import Control.Applicative-import Control.Monad.Identity+import Control.Monad (liftM, guard, mzero, mplus, msum)+import Control.Monad.Logic (MonadLogic, (>>-), interleave, msplit, observeAllT)+import Control.Monad.Reader (ask, local)+import Control.Applicative (empty, pure, (<$>))+import Control.Monad.Identity (Identity(..)) import Data.Int (Int, Int8, Int16, Int32, Int64)-import Data.List-import Data.Ratio+import Data.List (intercalate)+import Data.Ratio (Ratio, numerator, denominator, (%)) import Data.Word (Word, Word8, Word16, Word32, Word64) import Numeric.Natural (Natural) import Test.SmallCheck.SeriesMonad-import GHC.Generics+import GHC.Generics (Generic, (:+:)(..), (:*:)(..), C1, K1(..), M1(..), U1(..), Rep, to, from) ------------------------------ -- Main types and classes@@ -519,8 +523,29 @@ -- | 'N' is a wrapper for 'Integral' types that causes only non-negative values -- to be generated. Generated functions of type @N a -> b@ do not distinguish -- different negative values of @a@.-newtype N a = N { unN :: a } deriving (Eq, Ord, Real, Enum, Num, Integral)+newtype N a = N { unN :: a } deriving (Eq, Ord) +instance Real a => Real (N a) where+ toRational (N x) = toRational x++instance Enum a => Enum (N a) where+ toEnum x = N (toEnum x)+ fromEnum (N x) = fromEnum x++instance Num a => Num (N a) where+ N x + N y = N (x + y)+ N x * N y = N (x * y)+ negate (N x) = N (negate x)+ abs (N x) = N (abs x)+ signum (N x) = N (signum x)+ fromInteger x = N (fromInteger x)++instance Integral a => Integral (N a) where+ quotRem (N x) (N y) = (N q, N r)+ where+ (q, r) = x `quotRem` y+ toInteger (N x) = toInteger x+ instance (Num a, Enum a, Serial m a) => Serial m (N a) where series = generate $ \d -> take (d+1) [0..] @@ -539,8 +564,29 @@ else z -- | 'M' is a helper type to generate values of a signed type of increasing magnitude.-newtype M a = M { unM :: a } deriving (Eq, Ord, Real, Enum, Num, Integral)+newtype M a = M { unM :: a } deriving (Eq, Ord) +instance Real a => Real (M a) where+ toRational (M x) = toRational x++instance Enum a => Enum (M a) where+ toEnum x = M (toEnum x)+ fromEnum (M x) = fromEnum x++instance Num a => Num (M a) where+ M x + M y = M (x + y)+ M x * M y = M (x * y)+ negate (M x) = M (negate x)+ abs (M x) = M (abs x)+ signum (M x) = M (signum x)+ fromInteger x = M (fromInteger x)++instance Integral a => Integral (M a) where+ quotRem (M x) (M y) = (M q, M r)+ where+ (q, r) = x `quotRem` y+ toInteger (M x) = toInteger x+ instance (Num a, Enum a, Monad m) => Serial m (M a) where series = others `interleave` positives where positives = generate $ \d -> take d [1..]@@ -655,13 +701,13 @@ -- show the extension of a function (in part, bounded both by -- the number and depth of arguments)-instance (Serial Identity a, Show a, Show b) => Show (a->b) where+instance (Serial Identity a, Show a, Show b) => Show (a -> b) where show f = if maxarheight == 1 && sumarwidth + length ars * length "->;" < widthLimit then- "{"++(- concat $ intersperse ";" $ [a++"->"++r | (a,r) <- ars]- )++"}"+ "{"+++ intercalate ";" [a++"->"++r | (a,r) <- ars]+ ++"}" else concat $ [a++"->\n"++indent r | (a,r) <- ars] where@@ -685,8 +731,29 @@ -------------------------------------------------------------------------- -- | @Positive x@: guarantees that @x \> 0@. newtype Positive a = Positive { getPositive :: a }- deriving (Eq, Ord, Num, Integral, Real, Enum)+ deriving (Eq, Ord) +instance Real a => Real (Positive a) where+ toRational (Positive x) = toRational x++instance Enum a => Enum (Positive a) where+ toEnum x = Positive (toEnum x)+ fromEnum (Positive x) = fromEnum x++instance Num a => Num (Positive a) where+ Positive x + Positive y = Positive (x + y)+ Positive x * Positive y = Positive (x * y)+ negate (Positive x) = Positive (negate x)+ abs (Positive x) = Positive (abs x)+ signum (Positive x) = Positive (signum x)+ fromInteger x = Positive (fromInteger x)++instance Integral a => Integral (Positive a) where+ quotRem (Positive x) (Positive y) = (Positive q, Positive r)+ where+ (q, r) = x `quotRem` y+ toInteger (Positive x) = toInteger x+ instance (Num a, Ord a, Serial m a) => Serial m (Positive a) where series = Positive <$> series `suchThat` (> 0) @@ -695,7 +762,28 @@ -- | @NonNegative x@: guarantees that @x \>= 0@. newtype NonNegative a = NonNegative { getNonNegative :: a }- deriving (Eq, Ord, Num, Integral, Real, Enum)+ deriving (Eq, Ord)++instance Real a => Real (NonNegative a) where+ toRational (NonNegative x) = toRational x++instance Enum a => Enum (NonNegative a) where+ toEnum x = NonNegative (toEnum x)+ fromEnum (NonNegative x) = fromEnum x++instance Num a => Num (NonNegative a) where+ NonNegative x + NonNegative y = NonNegative (x + y)+ NonNegative x * NonNegative y = NonNegative (x * y)+ negate (NonNegative x) = NonNegative (negate x)+ abs (NonNegative x) = NonNegative (abs x)+ signum (NonNegative x) = NonNegative (signum x)+ fromInteger x = NonNegative (fromInteger x)++instance Integral a => Integral (NonNegative a) where+ quotRem (NonNegative x) (NonNegative y) = (NonNegative q, NonNegative r)+ where+ (q, r) = x `quotRem` y+ toInteger (NonNegative x) = toInteger x instance (Num a, Ord a, Serial m a) => Serial m (NonNegative a) where series = NonNegative <$> series `suchThat` (>= 0)
Test/SmallCheck/SeriesMonad.hs view
@@ -1,12 +1,12 @@-{-# LANGUAGE Trustworthy #-} -- GeneralizedNewtypeDeriving-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE Safe #-}+ module Test.SmallCheck.SeriesMonad where -import Control.Applicative-import Control.Monad-import Control.Monad.Logic-import Control.Monad.Reader-import Control.Arrow+import Control.Applicative (Applicative(..), Alternative(..), (<$>))+import Control.Monad (MonadPlus(..))+import Control.Monad.Logic (MonadLogic(..), LogicT)+import Control.Monad.Reader (MonadTrans(..), ReaderT, runReaderT)+import Control.Arrow (second) -- | Maximum depth of generated test values. --@@ -33,17 +33,31 @@ -- It is also desirable that values of smaller depth come before the values -- of greater depth. newtype Series m a = Series (ReaderT Depth (LogicT m) a)- deriving- ( Functor- , Monad- , Applicative- , MonadPlus- , Alternative- ) --- This instance is written manually. Using the GND for it is not safe. +instance Functor (Series m) where+ fmap f (Series x) = Series (fmap f x)++instance Monad (Series m) where+ Series x >>= f = Series (x >>= unSeries . f)+ where+ unSeries (Series y) = y+ return = pure++instance Applicative (Series m) where+ pure = Series . pure+ Series x <*> Series y = Series (x <*> y)++instance MonadPlus (Series m) where+ mzero = empty+ mplus = (<|>)++instance Alternative (Series m) where+ empty = Series empty+ Series x <|> Series y = Series (x <|> y)++-- This instance is written manually. Using the GND for it is not safe. instance Monad m => MonadLogic (Series m) where- msplit (Series a) = Series $ fmap (fmap $ second Series) $ msplit a+ msplit (Series a) = Series (fmap (second Series) <$> msplit a) instance MonadTrans Series where lift a = Series $ lift . lift $ a
smallcheck.cabal view
@@ -1,41 +1,52 @@-Name: smallcheck-Version: 1.1.5-Cabal-Version: >= 1.6-License: BSD3-License-File: LICENSE-Author: Colin Runciman, Roman Cheplyaka-Maintainer: Roman Cheplyaka <roma@ro-che.info>-Homepage: https://github.com/feuerbach/smallcheck-Bug-reports: https://github.com/feuerbach/smallcheck/issues--Stability: Beta-Category: Testing-Synopsis: A property-based testing library-Description: SmallCheck is a testing library that allows to verify properties- for all test cases up to some depth. The test cases are generated- automatically by SmallCheck.-Build-Type: Simple--Extra-source-files: README.md, CREDITS.md, CHANGELOG.md+name: smallcheck+version: 1.1.6+license: BSD3+license-file: LICENSE+maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+author: Colin Runciman, Roman Cheplyaka+cabal-version: >=1.10+tested-with:+ ghc ==8.10.1 ghc ==8.8.3 ghc ==8.6.5 ghc ==8.4.4 ghc ==8.2.2+ ghc ==8.0.2 ghc ==7.10.3 ghc ==7.8.4 ghc ==7.6.3 ghc ==7.4.2 +homepage: https://github.com/Bodigrim/smallcheck+bug-reports: https://github.com/Bodigrim/smallcheck/issues+synopsis: A property-based testing library+description:+ SmallCheck is a testing library that allows to verify properties+ for all test cases up to some depth. The test cases are generated+ automatically by SmallCheck. +category: Testing+build-type: Simple+extra-source-files:+ README.md+ CREDITS.md+ CHANGELOG.md -Source-repository head+source-repository head type: git- location: git://github.com/feuerbach/smallcheck.git+ location: git://github.com/Bodigrim/smallcheck.git -Library+library+ default-language: Haskell2010 - Build-Depends: base >= 4.5 && < 5, mtl, logict, ghc-prim >= 0.2, pretty+ exposed-modules:+ Test.SmallCheck+ Test.SmallCheck.Drivers+ Test.SmallCheck.Series - if impl(ghc < 7.10)- build-depends: nats+ other-modules:+ Test.SmallCheck.Property+ Test.SmallCheck.SeriesMonad+ Test.SmallCheck.Property.Result - Exposed-modules:- Test.SmallCheck- Test.SmallCheck.Drivers- Test.SmallCheck.Series- Other-modules:- Test.SmallCheck.Property- Test.SmallCheck.SeriesMonad- Test.SmallCheck.Property.Result+ build-depends:+ base >=4.5 && <5,+ mtl,+ logict,+ ghc-prim >=0.2,+ pretty++ if impl(ghc <7.10)+ build-depends: nats