packages feed

antigen 0.3.0.0 → 0.3.1.0

raw patch · 5 files changed

+42/−20 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Test.AntiGen: tryZapAntiGen :: Int -> AntiGen a -> Gen (Maybe a)
+ Test.AntiGen.Internal: tryZapAntiGen :: Int -> AntiGen a -> Gen (Maybe a)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for antigen +## 0.3.1.0++* Add `tryZapAntiGen`+ ## 0.3.0.0  * Rename `fickle*` to `faulty*`
antigen.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               antigen-version:            0.3.0.0+version:            0.3.1.0 synopsis:           Fault injection for QuickCheck description:   AntiGen extends QuickCheck to allow injecting random faults into QuickCheck @@ -33,7 +33,7 @@       Test.AntiGen.Internal     build-depends:           base >=4.18 && <5,-      QuickCheck >= 2.16.0 && < 2.18,+      QuickCheck >= 2.15.0 && < 2.18,       free >= 5.2 && < 5.3,       mtl >= 2.3.1 && < 2.4,       random >= 1.2 && < 1.4,
src/Test/AntiGen.hs view
@@ -15,6 +15,7 @@   (||!),   runAntiGen,   zapAntiGen,+  tryZapAntiGen,    -- * AntiGen combinators   faultyNum,@@ -43,7 +44,7 @@   NonZero (..),   Positive (..),  )-import Test.QuickCheck.GenT (MonadGen (..), elements, frequency, listOf1, suchThat)+import Test.QuickCheck.GenT (MonadGen (..), elements, listOf1, oneof, suchThat)  -- | Returns the provided number. -- Negative: returns a value that is not equal to the provided number.@@ -57,21 +58,13 @@  -- | Generates a value from the first range. -- Negative: Generates a value from the second range excluding the first range.------ Note: The second range must not be a subset of the first range! antiChoose :: (Integral a, Random a) => (a, a) -> (a, a) -> AntiGen a-antiChoose rng@(lo, hi) (boundLo, boundHi) =-  choose rng-    |! frequency-      ( mconcat-          [ [ (fromIntegral $ lo - boundLo, choose rngLo)-            | lo > boundLo-            ]-          , [ (fromIntegral $ boundHi - hi, choose rngHi)-            | boundHi > hi-            ]-          ]-      )+antiChoose rng@(lo, hi) (boundLo, boundHi)+  | lo > boundLo || boundHi > hi =+      choose rng+        |! oneof+          ([choose rngLo | lo > boundLo] <> [choose rngHi | boundHi > hi])+  | otherwise = choose rng   where     rngLo = (boundLo, pred lo)     rngHi = (succ hi, boundHi)
src/Test/AntiGen/Internal.hs view
@@ -14,6 +14,7 @@   AntiGen,   (|!),   zapAntiGen,+  tryZapAntiGen,   runAntiGen,   evalToPartial,   evalPartial,@@ -24,7 +25,7 @@ import Control.Monad ((<=<)) import Control.Monad.Free.Church (F (..), MonadFree (..)) import Control.Monad.Free.Class (wrapT)-import Control.Monad.State.Strict (MonadState (..), StateT (..), evalStateT, modify)+import Control.Monad.State.Strict (MonadState (..), StateT (..), evalStateT, modify') import Control.Monad.Trans (MonadTrans (..)) import Test.QuickCheck (Gen, getSize) import Test.QuickCheck.GenT (GenT (..), MonadGen (..), runGenT)@@ -95,7 +96,7 @@     case dpNegativeGen of       Just neg -> do         d <- get-        modify pred+        modify' pred         if d == 0           then do             -- Negate the generator@@ -127,6 +128,15 @@ -- than `n`. zapAntiGen :: Int -> AntiGen a -> Gen a zapAntiGen n = fmap evalPartial <$> zapNTimes n <=< evalToPartial++-- | Create a negative generator from an `AntiGen` by introducing at most+-- `n` mistakes. If there are no decision points, it will return `Nothing`.+tryZapAntiGen :: Int -> AntiGen a -> Gen (Maybe a)+tryZapAntiGen n ag = do+  p <- evalToPartial ag+  if countDecisionPoints p > 0+    then Just . evalPartial <$> zapNTimes n p+    else pure Nothing  -- | Create a positive generator from the provided `AntiGen`. runAntiGen :: AntiGen a -> Gen a
test/Main.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -5,8 +7,10 @@  import Control.Monad (replicateM) import Data.Data (Proxy (..))+import Data.Word (Word32, Word64) import Test.AntiGen (   AntiGen,+  antiChooseBounded,   antiNegative,   antiNonNegative,   antiNonPositive,@@ -20,7 +24,7 @@   (||!),  ) import Test.AntiGen.Internal (countDecisionPoints, evalToPartial)-import Test.Hspec (Spec, describe, hspec, shouldBe)+import Test.Hspec (Spec, describe, hspec, shouldBe, shouldSatisfy) import Test.Hspec.QuickCheck (prop) import Test.QuickCheck (   Arbitrary (..),@@ -45,6 +49,7 @@   (===),  ) import Test.QuickCheck.GenT (MonadGen (..), listOf1, oneof)+import Type.Reflection (Typeable, typeRep)  antiGenPositive :: AntiGen Int antiGenPositive = (getPositive @Int <$> arbitrary) |! (getNonPositive <$> arbitrary)@@ -159,6 +164,12 @@             )           ] +chooseBoundedIntegralTest :: forall a. Typeable a => Spec+chooseBoundedIntegralTest =+  prop (show (typeRep @a) <> " (0, n)") $ \(Positive (n :: Word64)) -> do+    res <- zapAntiGen 1 (antiChooseBounded (0, n))+    pure $ res `shouldSatisfy` (> n)+ utilsSpec :: Spec utilsSpec =   describe "utils" $ do@@ -209,6 +220,10 @@             [ ("null", null res)             , ("nonpositive", length (filter (<= 0) res) == 1)             ]+    describe "chooseBoundedIntegral" $ do+      chooseBoundedIntegralTest @Word64+      chooseBoundedIntegralTest @Word32+      chooseBoundedIntegralTest @Int  main :: IO () main = hspec $ do