genvalidity 0.7.0.2 → 0.8.0.0
raw patch · 4 files changed
+46/−24 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.GenValidity: instance (Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b) => Data.GenValidity.GenInvalid (a, b)
- Data.GenValidity: instance (Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c) => Data.GenValidity.GenInvalid (a, b, c)
- Data.GenValidity: instance (Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c, Data.GenValidity.GenInvalid d) => Data.GenValidity.GenInvalid (a, b, c, d)
- Data.GenValidity: instance (Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c, Data.GenValidity.GenInvalid d, Data.GenValidity.GenInvalid e) => Data.GenValidity.GenInvalid (a, b, c, d, e)
- Data.GenValidity: instance (GHC.Real.Integral a, GHC.Num.Num a, GHC.Classes.Ord a, Data.GenValidity.GenValid a) => Data.GenValidity.GenInvalid (GHC.Real.Ratio a)
- Data.GenValidity: instance Data.GenValidity.GenInvalid a => Data.GenValidity.GenInvalid (GHC.Base.NonEmpty a)
- Data.GenValidity: instance Data.GenValidity.GenInvalid a => Data.GenValidity.GenInvalid [a]
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenInvalid a) => Data.GenValidity.GenInvalid (GHC.Base.NonEmpty a)
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenInvalid a) => Data.GenValidity.GenInvalid [a]
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenInvalid a, Data.GenValidity.GenUnchecked b, Data.GenValidity.GenInvalid b) => Data.GenValidity.GenInvalid (a, b)
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenUnchecked b, Data.GenValidity.GenUnchecked c, Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c) => Data.GenValidity.GenInvalid (a, b, c)
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenUnchecked b, Data.GenValidity.GenUnchecked c, Data.GenValidity.GenUnchecked d, Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c, Data.GenValidity.GenInvalid d) => Data.GenValidity.GenInvalid (a, b, c, d)
+ Data.GenValidity: instance (Data.GenValidity.GenUnchecked a, Data.GenValidity.GenUnchecked b, Data.GenValidity.GenUnchecked c, Data.GenValidity.GenUnchecked d, Data.GenValidity.GenUnchecked e, Data.GenValidity.GenInvalid a, Data.GenValidity.GenInvalid b, Data.GenValidity.GenInvalid c, Data.GenValidity.GenInvalid d, Data.GenValidity.GenInvalid e) => Data.GenValidity.GenInvalid (a, b, c, d, e)
+ Data.GenValidity: instance (GHC.Real.Integral a, GHC.Num.Num a, GHC.Classes.Ord a, Data.Validity.Validity a, Data.GenValidity.GenUnchecked a) => Data.GenValidity.GenInvalid (GHC.Real.Ratio a)
+ Data.GenValidity: shrinkTuple :: (a -> [a]) -> (b -> [b]) -> (a, b) -> [(a, b)]
- Data.GenValidity: class (Validity a, GenUnchecked a) => GenInvalid a
+ Data.GenValidity: class Validity a => GenInvalid a
- Data.GenValidity: class (Validity a, GenUnchecked a) => GenValid a
+ Data.GenValidity: class Validity a => GenValid a
- Data.GenValidity: genInvalid :: GenInvalid a => Gen a
+ Data.GenValidity: genInvalid :: (GenInvalid a, GenUnchecked a) => Gen a
- Data.GenValidity: genValid :: GenValid a => Gen a
+ Data.GenValidity: genValid :: (GenValid a, GenUnchecked a) => Gen a
- Data.GenValidity: shrinkInvalid :: GenInvalid a => a -> [a]
+ Data.GenValidity: shrinkInvalid :: (GenInvalid a, GenUnchecked a) => a -> [a]
- Data.GenValidity: shrinkValid :: GenValid a => a -> [a]
+ Data.GenValidity: shrinkValid :: (GenValid a, GenUnchecked a) => a -> [a]
Files
- genvalidity.cabal +3/−3
- src/Data/GenValidity.hs +31/−16
- src/Data/GenValidity/Utils.hs +7/−0
- test/Data/InstanceSpec.hs +5/−5
genvalidity.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 13e57f7aafc2a2db6d022ffcae38acf8fe9e764b697a451f92daca9e03535e1a+-- hash: f83f379725515d102f66767260af87efc94d6cf4d8a6f2e3a4a0b8dc4437f8b9 name: genvalidity-version: 0.7.0.2+version: 0.8.0.0 synopsis: Testing utilities for the validity library description: Note: There are companion instance packages for this library: .@@ -36,7 +36,7 @@ author: Tom Sydney Kerckhove maintainer: syd.kerckhove@gmail.com, nick.van.den.broeck666@gmail.com-copyright: Copyright: (c) 2016-2018 Tom Sydney Kerckhove+copyright: Copyright: (c) 2016-2019 Tom Sydney Kerckhove license: MIT license-file: LICENSE build-type: Simple
src/Data/GenValidity.hs view
@@ -41,6 +41,9 @@ > case myFunction input of > Nothing -> return () -- Can happen > Just output -> output `shouldSatisfy` isValid++ Definitely also look at the genvalidity-property and genvalidity-hspec packages+ for more info on how to use this package. -} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-}@@ -144,6 +147,9 @@ -- > instance GenUnchecked MyType where -- > genUnchecked = MyType <$> genUnchecked <*> genUnchecked --+-- If this is not possible because there is no 'GenUnchecked' instance available for one of the+-- sub-parts of your type, __then do not instantiate 'GenUnchecked' for your type__.+-- Just continue with 'GenValid' instead. -- -- __Step 2__: If an instatiation via 'Generic' is not possible, then you should emulate what -- 'genericGenUnchecked' does.@@ -153,11 +159,11 @@ -- -- === Warning: Invalid values can be funky ----- Some types have serious validity constraints. See 'Text' or 'ByteString' for example.+-- Some types have serious validity constraints. See 'Rational' for example. -- These can behave very strangely when they are not valid. -- In that case, __do not override 'GenUnchecked' such that 'genUnchecked' only generates valid values__. -- In that case, do not override 'genUnchecked' at all.--- Instead, use 'genValid' from 'GenValid' (see below) instead.+-- Instead, use 'genValid' from 'GenValid' (see below) instead and consider not instantiating 'GenUnchecked' at all. class GenUnchecked a where genUnchecked :: Gen a default genUnchecked :: (Generic a, GGenUnchecked (Rep a)) =>@@ -175,6 +181,8 @@ -- === How to instantiate 'GenValid' -- -- __Step 1__: Try to instantiate 'GenValid' without overriding any functions.+-- This is only possible if your type has a 'GenUnchecked' instance.+-- If it doesn't, go to step 2. -- It is possible that, if few values are valid or if validity -- checking is expensive, that the resulting generator is too slow. -- In that case, go to Step 2.@@ -196,8 +204,7 @@ -- -- > arbitrary = genValid -- > shrink = shrinkValid-class (Validity a, GenUnchecked a) =>- GenValid a where+class Validity a => GenValid a where -- | Generate a valid datum, this should cover all possible valid values in -- the type --@@ -209,6 +216,7 @@ -- If you do, make sure that it is possible to generate all possible valid -- data, otherwise your testing may not cover all cases. genValid :: Gen a+ default genValid :: GenUnchecked a => Gen a genValid = genUnchecked `suchThat` isValid -- | Shrink a valid value.@@ -222,6 +230,7 @@ -- might fail for a different reason than for the reason that it originally failed. -- This would lead to very confusing error messages. shrinkValid :: a -> [a]+ default shrinkValid :: GenUnchecked a => a -> [a] shrinkValid = filter isValid . shrinkUnchecked -- | A class of types for which invalid values can be generated.@@ -237,8 +246,7 @@ -- for parametric values. -- -- __Step 2__: Instantiate 'GenInvalid' without overriding any functions.-class (Validity a, GenUnchecked a) =>- GenInvalid a where+class Validity a => GenInvalid a where genInvalid :: Gen a -- | Generate an invalid datum, this should cover all possible invalid -- values@@ -248,9 +256,11 @@ -- To speed up testing, it may be a good idea to implement this yourself. -- If you do, make sure that it is possible to generate all possible -- invalid data, otherwise your testing may not cover all cases.+ default genInvalid :: GenUnchecked a => Gen a genInvalid = genUnchecked `suchThat` isInvalid shrinkInvalid :: a -> [a]+ default shrinkInvalid :: GenUnchecked a => a -> [a] shrinkInvalid = filter isInvalid . shrinkUnchecked instance (GenUnchecked a, GenUnchecked b) => GenUnchecked (a, b) where@@ -271,11 +281,9 @@ a <- resize r genValid b <- resize s genValid return (a, b)- shrinkValid (a, b) = ((,) <$> shrinkValid a <*> shrinkValid b)- ++ [ (a', b) | a' <- shrinkValid a ]- ++ [ (a, b') | b' <- shrinkValid b ]+ shrinkValid = shrinkTuple shrinkValid shrinkValid -instance (GenInvalid a, GenInvalid b) => GenInvalid (a, b) where+instance (GenUnchecked a, GenInvalid a, GenUnchecked b, GenInvalid b) => GenInvalid (a, b) where genInvalid = sized $ \n -> do (r, s) <- genSplit n@@ -301,6 +309,8 @@ -- | This instance ensures that the generated tupse contains at least one invalid element. The other element is unchecked. instance (GenInvalid a, GenInvalid b) => GenInvalid (Either a b) where genInvalid = oneof [Left <$> genInvalid, Right <$> genInvalid]+ shrinkInvalid (Left v) = Left <$> shrinkInvalid v+ shrinkInvalid (Right v) = Right <$> shrinkInvalid v instance (GenUnchecked a, GenUnchecked b, GenUnchecked c) => GenUnchecked (a, b, c) where@@ -330,7 +340,8 @@ ] -- | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked.-instance (GenInvalid a, GenInvalid b, GenInvalid c) =>+instance ( GenUnchecked a, GenUnchecked b, GenUnchecked c+ , GenInvalid a, GenInvalid b, GenInvalid c) => GenInvalid (a, b, c) where genInvalid = sized $ \n -> do@@ -381,7 +392,8 @@ ] -- | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked.-instance (GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d) =>+instance ( GenUnchecked a, GenUnchecked b, GenUnchecked c, GenUnchecked d+ , GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d) => GenInvalid (a, b, c, d) where genInvalid = sized $ \n -> do@@ -442,7 +454,8 @@ ] -- | This instance ensures that the generated triple contains at least one invalid element. The other two are unchecked.-instance (GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d, GenInvalid e) =>+instance ( GenUnchecked a, GenUnchecked b, GenUnchecked c, GenUnchecked d, GenUnchecked e+ , GenInvalid a, GenInvalid b, GenInvalid c, GenInvalid d, GenInvalid e) => GenInvalid (a, b, c, d, e) where genInvalid = sized $ \n -> do@@ -493,6 +506,8 @@ instance GenInvalid a => GenInvalid (Maybe a) where genInvalid = Just <$> genInvalid+ shrinkInvalid Nothing = [] -- Should not happen+ shrinkInvalid (Just a) = Just <$> shrinkInvalid a #if MIN_VERSION_base(4,9,0) instance GenUnchecked a => GenUnchecked (NonEmpty a) where@@ -511,7 +526,7 @@ Just ne -> pure ne shrinkValid (v :| vs) = [ e :| es | (e, es) <- shrinkValid (v, vs)] -instance GenInvalid a => GenInvalid (NonEmpty a) where+instance (GenUnchecked a, GenInvalid a) => GenInvalid (NonEmpty a) where genInvalid = do l <- genInvalid case NE.nonEmpty l of@@ -531,7 +546,7 @@ -- | This instance ensures that the generated list contains at least one element -- that satisfies 'isInvalid'. The rest is unchecked.-instance GenInvalid a => GenInvalid [a] where+instance (GenUnchecked a, GenInvalid a) => GenInvalid [a] where genInvalid = sized $ \n -> do (x, y, z) <- genSplit3 n@@ -679,7 +694,7 @@ genValid = (%) <$> genValid <*> (genValid `suchThat` (> 0)) shrinkValid (n :% d) = [n' % d' | (n', d') <- shrinkValid (n, d), d' > 0] -instance (Integral a, Num a, Ord a, GenValid a) => GenInvalid (Ratio a)+instance (Integral a, Num a, Ord a, Validity a, GenUnchecked a) => GenInvalid (Ratio a) instance HasResolution a => GenUnchecked (Fixed a) where genUnchecked = MkFixed <$> genUnchecked
src/Data/GenValidity/Utils.hs view
@@ -25,6 +25,7 @@ , shuffle , genListOf -- ** Helper functions for implementing shrinking functions+ , shrinkTuple , shrinkT2 , shrinkT3 , shrinkT4@@ -113,6 +114,12 @@ size <- upTo n pars <- arbPartition size forM pars $ \i -> resize i func++shrinkTuple :: (a -> [a]) -> (b -> [b]) -> (a, b) -> [(a, b)]+shrinkTuple sa sb (a, b) =+ ((,) <$> sa a <*> sb b)+ ++ [ (a', b) | a' <- sa a ]+ ++ [ (a, b') | b' <- sb b ] -- | Turn a shrinking function into a function that shrinks tuples. shrinkT2 :: (a -> [a]) -> (a, a) -> [(a, a)]
test/Data/InstanceSpec.hs view
@@ -88,7 +88,7 @@ threeTests (Proxy :: Proxy (NonEmpty Rational)) #endif twoTupleTests ::- forall a. (Show a, Eq a, Typeable a, GenValid a)+ forall a. (Show a, Eq a, Typeable a, GenUnchecked a, GenValid a) => Proxy a -> Spec twoTupleTests proxy = do@@ -104,7 +104,7 @@ twoTests $ (,,,,) <$> proxy <*> proxy <*> proxy <*> proxy <*> proxy threeTupleTests ::- forall a. (Show a, Eq a, Typeable a, GenValid a, GenInvalid a)+ forall a. (Show a, Eq a, Typeable a, GenUnchecked a, GenValid a, GenInvalid a) => Proxy a -> Spec threeTupleTests proxy = do@@ -121,7 +121,7 @@ threeTests $ (,,,,) <$> proxy <*> proxy <*> proxy <*> proxy <*> proxy twoTests ::- forall a. (Show a, Eq a, Typeable a, GenValid a)+ forall a. (Show a, Eq a, Typeable a, GenUnchecked a, GenValid a) => Proxy a -> Spec twoTests proxy =@@ -130,7 +130,7 @@ genValidTest proxy threeTests ::- forall a. (Show a, Eq a, Typeable a, GenValid a, GenInvalid a)+ forall a. (Show a, Eq a, Typeable a, GenUnchecked a, GenValid a, GenInvalid a) => Proxy a -> Spec threeTests proxy =@@ -140,7 +140,7 @@ genInvalidTest proxy genUncheckedTest ::- forall a. (Show a, Eq a, Typeable a, GenValid a)+ forall a. (Show a, Eq a, Typeable a, GenUnchecked a, GenValid a) => Proxy a -> Spec genUncheckedTest proxy = do