kudzu 0.1.0.0 → 0.1.1.0
raw patch · 4 files changed
+85/−48 lines, 4 filesdep ~QuickCheckdep ~basedep ~hedgehogPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: QuickCheck, base, hedgehog, hpc, leancheck
API changes (from Hackage documentation)
+ Kudzu: KFail :: Int -> KudzuResult a
+ Kudzu: KSuccess :: Int -> a -> KudzuResult a
+ Kudzu: data KudzuResult a
+ Kudzu: instance GHC.Classes.Eq a => GHC.Classes.Eq (Kudzu.KudzuResult a)
+ Kudzu: instance GHC.Classes.Ord a => GHC.Classes.Ord (Kudzu.KudzuResult a)
+ Kudzu: instance GHC.Show.Show a => GHC.Show.Show (Kudzu.KudzuResult a)
+ Kudzu: testUntilSameLCMany :: (Traversable t, Testable a) => Int -> t a -> IO (t (KudzuResult Integer))
- Kudzu: examineAndCount' :: Testable prop => prop -> IO Integer
+ Kudzu: examineAndCount' :: Testable prop => prop -> Int -> IO Integer
- Kudzu: grabUntilNSame :: (Monad m, Eq a) => Int -> Int -> Int -> [m a] -> a -> m (Int, Maybe a)
+ Kudzu: grabUntilNSame :: (Monad m, Eq a) => Int -> [m a] -> m (KudzuResult a)
- Kudzu: testUntilSameHH :: Int -> Property -> IO (Int, Maybe Integer)
+ Kudzu: testUntilSameHH :: Int -> Property -> IO (KudzuResult Integer)
- Kudzu: testUntilSameHHMany :: Traversable t => Int -> t Property -> IO (t (Int, Maybe Integer))
+ Kudzu: testUntilSameHHMany :: Traversable t => Int -> t Property -> IO (t (KudzuResult Integer))
- Kudzu: testUntilSameLC :: Testable a => Int -> a -> IO (Int, Maybe Integer)
+ Kudzu: testUntilSameLC :: Testable a => Int -> a -> IO (KudzuResult Integer)
- Kudzu: testUntilSameQC :: Testable a => Int -> a -> IO (Int, Maybe Integer)
+ Kudzu: testUntilSameQC :: Testable a => Int -> a -> IO (KudzuResult Integer)
- Kudzu: testUntilSameQCMany :: (Traversable t, Testable a) => Int -> t a -> IO (t (Int, Maybe Integer))
+ Kudzu: testUntilSameQCMany :: (Traversable t, Testable a) => Int -> t a -> IO (t (KudzuResult Integer))
Files
- CHANGELOG.md +6/−0
- README.md +15/−1
- kudzu.cabal +9/−9
- src/Kudzu.hs +55/−38
CHANGELOG.md view
@@ -4,3 +4,9 @@ * First version. Released on an unsuspecting world. Good Luck World. Kinda does the thing, yay?+++## 0.1.1.0 -- 2024-04-27++* refactored grabUntilNSame+* updated dependencies
README.md view
@@ -20,7 +20,13 @@ # HOW DO I MAKE IT GO? -add kudzu to your test-suite depends,+1. add kudzu to your test-suite depends,+2. import the [`Kudzu`] module+3. call the testUntil function of your choice+ 1. [`testUntilSameQCMany`] or [`testUntilSameQC`]+ 2. [`testUntilSameHHMany`] or [`testUntilSameHH`]+ 3. [`testUntilSameLCMany`] or [`testUntilsameLC`]+4. run with `cabal test --enable-coverage` # TELL ME MORE @@ -36,3 +42,11 @@ # EXAMPLE You can see kudzu in use in the [tests](https://github.com/shapr/takedouble/blob/main/test/Main.hs) for [takedouble](https://github.com/shapr/takedouble/)++[`Kudzu`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html+[`testUntilSameQC`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameQC+[`testUntilSameQCMany`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameQCMany+[`testUntilSameHH`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameHH+[`testUntilSameHHMany`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameHHMany+[`testUntilSameLC`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameLC+[`testUntilSameLCMany`]: https://hackage.haskell.org/package/kudzu/docs/Kudzu.html#v:testUntilSameLCMany
kudzu.cabal view
@@ -14,7 +14,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.1.0.0+version: 0.1.1.0 -- A short (one-line) description of the package. synopsis: coverage driven random testing framework@@ -45,9 +45,9 @@ category: Testing -- Extra files to be distributed with the package, such as examples or a README.-extra-source-files: CHANGELOG.md- README.md+extra-source-files: README.md LICENSE+extra-doc-files: CHANGELOG.md description: Kudzu is a coverage driven random testing framework source-repository head type: git@@ -65,11 +65,11 @@ -- other-extensions: -- Other library packages from which modules are imported.- build-depends: base- , QuickCheck- , hedgehog- , hpc- , leancheck+ build-depends: base >=4.14 && < 4.20+ , QuickCheck >= 2.12 && < 2.16+ , hedgehog >=1.2 && < 1.5+ , hpc >= 0.6.0 && < 0.8.0+ , leancheck >= 1.0.0 && < 1.2 -- Directories containing source files.@@ -91,7 +91,7 @@ -- Other library packages from which modules are imported. build-depends:- base >=4.14 && < 4.17,+ base >=4.14 && < 4.20, kudzu -- Directories containing source files.
src/Kudzu.hs view
@@ -6,67 +6,84 @@ import qualified Hedgehog as HH import qualified Test.LeanCheck as LC import qualified Test.QuickCheck as QC+import qualified Test.QuickCheck.Random as QC++-- import Trace.Hpc.Mix import Trace.Hpc.Reflect (examineTix) import Trace.Hpc.Tix (Tix (..), TixModule (..)) -testUntilSameQCMany :: (Traversable t, QC.Testable a) => Int -> t a -> IO (t (Int, Maybe Integer))+testUntilSameQCMany :: (Traversable t, QC.Testable a) => Int -> t a -> IO (t (KudzuResult Integer)) testUntilSameQCMany howMany ts = do- mapM (testUntilSameQC howMany) ts+ mapM (testUntilSameQC howMany) ts -- | QuickCheck-testUntilSameQC :: QC.Testable a => Int -> a -> IO (Int, Maybe Integer)+testUntilSameQC :: (QC.Testable a) => Int -> a -> IO (KudzuResult Integer) testUntilSameQC n testable = do- let rs = examineAndCount' <$> repeat testable- r1 <- head rs- grabUntilNSame 0 n n (tail rs) r1+ let rs = map (examineAndCount' testable) [0 .. n]+ grabUntilNSame n rs -examineAndCount' :: QC.Testable prop => prop -> IO Integer-examineAndCount' v = do- -- poor QC, you got problems- -- quickCheckWith (stdArgs {maxSize = 400, maxSuccess = 1}) v- QC.quickCheck (QC.withMaxSuccess 1 v)- tixModuleCount <$> examineTix+examineAndCount' :: (QC.Testable prop) => prop -> Int -> IO Integer+examineAndCount' v size = do+ qcg <- QC.newQCGen+ QC.quickCheckWith (QC.stdArgs{QC.replay = Just (qcg, size)}) (QC.withMaxSuccess 1 v)+ tixModuleCount <$> examineTix -- | Hedgehog-testUntilSameHHMany :: Traversable t => Int -> t HH.Property -> IO (t (Int, Maybe Integer))+testUntilSameHHMany :: (Traversable t) => Int -> t HH.Property -> IO (t (KudzuResult Integer)) testUntilSameHHMany howMany ps = do- mapM (testUntilSameHH howMany) ps+ mapM (testUntilSameHH howMany) ps -testUntilSameHH :: Int -> HH.Property -> IO (Int, Maybe Integer)-testUntilSameHH n prop = do- let rs = examineAndCountHH <$> repeat prop- r1 <- head rs- grabUntilNSame 0 n n (tail rs) r1+testUntilSameHH :: Int -> HH.Property -> IO (KudzuResult Integer)+testUntilSameHH n prop = grabUntilNSame n $ examineAndCountHH <$> repeat prop examineAndCountHH :: HH.Property -> IO Integer examineAndCountHH prop = do- passed <- HH.check prop- unless passed $ error "property failed"- tixModuleCount <$> examineTix+ passed <- HH.check . HH.withTests 1 $ prop+ unless passed $ error "property failed"+ tixModuleCount <$> examineTix -- | LeanCheck-testUntilSameLC :: LC.Testable a => Int -> a -> IO (Int, Maybe Integer)-testUntilSameLC n testable = do- let rs = examineAndCount <$> LC.results testable- r1 <- head rs- grabUntilNSame 0 n n (tail rs) r1+testUntilSameLCMany :: (Traversable t, LC.Testable a) => Int -> t a -> IO (t (KudzuResult Integer))+testUntilSameLCMany howMany ts = do+ mapM (testUntilSameLC howMany) ts +testUntilSameLC :: (LC.Testable a) => Int -> a -> IO (KudzuResult Integer)+testUntilSameLC n testable = grabUntilNSame n $ examineAndCount <$> LC.results testable+ examineAndCount :: ([String], Bool) -> IO Integer-examineAndCount v = unless (snd v) (error "your code is broken") >> tixModuleCount <$> examineTix+examineAndCount v = unless (snd v) (error $ unwords ("test failed with:" : fst v)) >> tixModuleCount <$> examineTix -grabUntilNSame :: (Monad m, Eq a) => Int -> Int -> Int -> [m a] -> a -> m (Int, Maybe a)-grabUntilNSame c _ 0 _ z = pure (c, Just z)-grabUntilNSame c _ _ [] _ = pure (c, Nothing)-grabUntilNSame c orig n (a : as) z = do- a' <- a- if a' == z- then grabUntilNSame (c + 1) orig (n - 1) as z- else grabUntilNSame (c + 1) orig orig as a'+data KudzuResult a = KFail Int | KSuccess Int a deriving (Show, Eq, Ord) --- How many regions were executed at least once for this module?+-- | Keep running property tests until the "amount" of code coverage is the same for N iterations of one test.+grabUntilNSame ::+ (Monad m, Eq a) =>+ -- | How many iterations must be the same?+ Int ->+ -- | a lazy list of iterations+ [m a] ->+ m (KudzuResult a)+grabUntilNSame _ [] = pure $ KFail 0+grabUntilNSame orig (a : as) = do+ a' <- a -- run the first iteration of the test+ go 0 orig as a'+ where+ go c 0 _ z = pure $ KSuccess c z -- we reached the desired window size+ go c _ [] _ = pure $ KFail c -- if we run out of list elements for test results, we're done+ go c n (b : bs) z = do+ a' <- b+ if a' == z+ then go (c + 1) (n - 1) bs z+ else go (c + 1) orig as a'++-- | How many regions were executed at least once for this module? tixCount :: TixModule -> Integer tixCount (TixModule _ _ _ regions) = sum $ 1 <$ filter (> 0) regions --- How many regions were executed at least once for all these modules?+-- | How many regions were executed at least once for all these modules? tixModuleCount :: Tix -> Integer tixModuleCount (Tix ms) = sum $ map tixCount ms++-- foo = Mix "src/Data/Array/Accelerate/Trafo/Config.hs" 2024 - 04 - 22 14 : 30 : 08.311359928 UTC 3070486 8 [(41 : 18 - 41 : 32, ExpBox False), (42 : 3 - 42 : 8, ExpBox False), (42 : 15 - 42 : 20, ExpBox False), (42 : 25 - 42 : 34, ExpBox False), (42 : 24 - 42 : 39, ExpBox False), (42 : 14 - 42 : 40, ExpBox False), (42 : 3 - 42 : 40, ExpBox False), (42 : 51 - 42 : 68, ExpBox False), (42 : 46 - 42 : 68, ExpBox False), (42 : 3 - 42 : 68, ExpBox False), (43 : 15 - 43 : 26, ExpBox False), (43 : 43 - 43 : 67, ExpBox False), (43 : 32 - 43 : 67, ExpBox False), (43 : 14 - 43 : 68, ExpBox False), (42 : 3 - 43 : 68, ExpBox False), (44 : 15 - 44 : 26, ExpBox False), (44 : 43 - 44 : 69, ExpBox False), (44 : 32 - 44 : 69, ExpBox False), (44 : 14 - 44 : 70, ExpBox False), (42 : 3 - 44 : 70, ExpBox False), (41 : 18 - 44 : 70, ExpBox False), (41 : 1 - 44 : 70, TopLevelBox ["defaultOptions"]), (33 : 5 - 33 : 11, ExpBox False), (33 : 5 - 33 : 11, TopLevelBox ["options"]), (34 : 5 - 34 : 27, ExpBox False), (34 : 5 - 34 : 27, TopLevelBox ["unfolding_use_threshold"]), (35 : 5 - 35 : 29, ExpBox False), (35 : 5 - 35 : 29, TopLevelBox ["max_simplifier_iterations"]), (37 : 12 - 37 : 15, TopLevelBox ["showsPrec"]), (37 : 12 - 37 : 15, TopLevelBox ["show"]), (37 : 12 - 37 : 15, TopLevelBox ["showList"])]++-- bar = Mix "src/Data/Array/Accelerate/Classes/ToFloating.hs" 2024 - 04 - 22 14 : 30 : 08.304359842 UTC 1185370804 8 [(47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"]), (47 : 2 - 79 : 2, ExpBox False), (47 : 2 - 79 : 2, TopLevelBox ["toFloating"])]