leancheck 0.6.4 → 0.6.5
raw patch · 14 files changed
+213/−194 lines, 14 filesdep +leancheck
Dependencies added: leancheck
Files
- TODO.md +2/−23
- leancheck.cabal +20/−15
- src/Test/LeanCheck/Core.hs +8/−4
- src/Test/LeanCheck/IO.hs +1/−1
- src/Test/LeanCheck/Invariants.hs +0/−148
- src/Test/LeanCheck/Utils/TypeBinding.hs +4/−0
- src/Test/LeanCheck/Utils/Types.hs +18/−0
- tests/Test.hs +148/−0
- tests/test-derive.hs +2/−1
- tests/test-error.hs +2/−0
- tests/test-operators.hs +2/−0
- tests/test-tiers.hs +2/−1
- tests/test-types.hs +1/−0
- tests/test.hs +3/−1
TODO.md view
@@ -16,42 +16,21 @@ * add diff test for IO functions (diff w/ model output and exit status) -* (?) on leancheck.cabal, add upper bound for template-haskell package -* Show when test cases are exhausted after testing:-- > check $ \p -> p == (p :: Bool)- +++ OK, passed 2 tests (test cases exhausted).-- Instead of just:-- > check $ \p -> p == (p :: Bool)- +++ OK, passed 2 tests.-- documentation ------------- -* add eg folder with some examples of testing using LeanCheck;- * on tutorial.md, write about how to create test programs; * on data-invariant.md, write missing section; -v0.6.5+v0.6.6 ------ -* Document `X` and `Xs` on `Utils.Types`.- * On `bench/tiers`, print if the enumeration has repetitions (import `Function.Eq` for that) -* Add `names` function to the ShowFunction typeclass that lists templates of- names for variables of the type.- Sadly, there is no way to do this without introducing a typeclass restriction- on function arguments. Make a separate `Argument` typeclass to do that?- * add `classify` function to measure distribution of data: something like: @@ -81,7 +60,7 @@ so that the user gets an enumeration of functions with repetitions, but using a mixed strategy for generation of values. -v0.6.6+v0.6.7 ------ * implement stub `Test.LeanCheck.Function.*` modules;
leancheck.cabal view
@@ -11,7 +11,7 @@ -- this cabal file too complicated. -- Rudy name: leancheck-version: 0.6.4+version: 0.6.5 synopsis: Cholesterol-free property-based testing description: LeanCheck is a simple enumerative property-based testing library.@@ -50,7 +50,7 @@ source-repository this type: git location: https://github.com/rudymatela/leancheck- tag: v0.6.4+ tag: v0.6.5 library exposed-modules: Test.LeanCheck@@ -72,7 +72,6 @@ , Test.LeanCheck.Function.Periodic , Test.LeanCheck.Function.Show , Test.LeanCheck.Function.ShowFunction- other-modules: Test.LeanCheck.Invariants hs-source-dirs: src build-depends: base >= 4 && < 5, template-haskell default-language: Haskell2010@@ -80,41 +79,47 @@ test-suite test type: exitcode-stdio-1.0 main-is: test.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010 test-suite types type: exitcode-stdio-1.0 main-is: test-types.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010 test-suite tiers type: exitcode-stdio-1.0 main-is: test-tiers.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010 test-suite operators type: exitcode-stdio-1.0 main-is: test-operators.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010 test-suite derive type: exitcode-stdio-1.0 main-is: test-derive.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010 test-suite error type: exitcode-stdio-1.0 main-is: test-error.hs- hs-source-dirs: src, tests- build-depends: base >= 4 && < 5, template-haskell+ other-modules: Test+ hs-source-dirs: tests+ build-depends: base >= 4 && < 5, leancheck default-language: Haskell2010
src/Test/LeanCheck/Core.hs view
@@ -158,7 +158,7 @@ instance Listable Bool where tiers = cons0 False \/ cons0 True --- | > tiers :: [[Maybe Int]] = [[Nothing], [Just 0], [Just 1], [Just -1], ...]+-- | > tiers :: [[Maybe Int]] = [[Nothing], [Just 0], [Just 1], ...] -- > tiers :: [[Maybe Bool]] = [[Nothing], [Just False, Just True]] instance Listable a => Listable (Maybe a) where tiers = cons0 Nothing \/ cons1 Just@@ -167,8 +167,12 @@ tiers = reset (cons1 Left) \\// reset (cons1 Right) --- | > tiers :: [[(Int,Int)]] = [ [(0,0)], [(0,1),(1,0)], [(0,-1),(1,1),(-1,0)], ...]--- > list :: [(Int,Int)] = [ (0,0), (0,1), (1,0), (0,-1), (1,1), (-1,0), ...]+-- | > tiers :: [[(Int,Int)]] =+-- > [ [(0,0)]+-- > , [(0,1),(1,0)]+-- > , [(0,-1),(1,1),(-1,0)]+-- > , ...]+-- > list :: [(Int,Int)] = [ (0,0), (0,1), (1,0), (0,-1), (1,1), ...] instance (Listable a, Listable b) => Listable (a,b) where tiers = tiers >< tiers @@ -191,7 +195,7 @@ -- > , [ [0,0], [1] ] -- > , [ [0,0,0], [0,1], [1,0], [-1] ] -- > , ... ]--- > list :: [ [Int] ] = [ [], [0], [0,0], [1], [0,0,0], [0,1], [1,0], [-1], ... ]+-- > list :: [ [Int] ] = [ [], [0], [0,0], [1], [0,0,0], ... ] instance (Listable a) => Listable [a] where tiers = cons0 [] \/ cons2 (:)
src/Test/LeanCheck/IO.hs view
@@ -46,7 +46,7 @@ -- returning 'True' on success. -- -- There is no option to silence this function:--- for silence, you should use 'TestLean.Check.holds'.+-- for silence, you should use 'Test.LeanCheck.holds'. checkResult :: Testable a => a -> IO Bool checkResult p = checkResultFor 200 p
− src/Test/LeanCheck/Invariants.hs
@@ -1,148 +0,0 @@--- |--- Module : Test.LeanCheck.Invariants--- Copyright : (c) 2015-2017 Rudy Matela--- License : 3-Clause BSD (see the file LICENSE)--- Maintainer : Rudy Matela <rudy@matela.com.br>------ This module is part of LeanCheck,--- a simple enumerative property-based testing library.------ Some invariants about Test.LeanCheck functions.------ You should be importing this ONLY to test "Test.LeanCheck" itself.-module Test.LeanCheck.Invariants- ( tNatPairOrd- , tNatTripleOrd- , tNatQuadrupleOrd- , tNatQuintupleOrd- , tNatSixtupleOrd- , tNatListOrd- , tListsOfNatOrd- , tPairEqParams- , tTripleEqParams- , tProductsIsFilterByLength-- , ordered- , orderedBy- , orderedOn- , strictlyOrdered- , strictlyOrderedBy- , strictlyOrderedOn- )-where--import Test.LeanCheck-import Data.List-import Data.Ord-import Test.LeanCheck.Utils.Types (Nat(..))---- | check if a list is ordered-ordered :: Ord a => [a] -> Bool-ordered = orderedBy compare--- ordered [] = True--- ordered [_] = True--- ordered (x:y:xs) = x <= y && ordered (y:xs)--strictlyOrdered :: Ord a => [a] -> Bool-strictlyOrdered = strictlyOrderedBy compare---- | check if a list is ordered by a given ordering function-orderedBy :: (a -> a -> Ordering) -> [a] -> Bool-orderedBy _ [] = True-orderedBy _ [_] = True-orderedBy cmp (x:y:xs) = case x `cmp` y of- GT -> False- _ -> orderedBy cmp (y:xs)--orderedOn :: Ord b => (a -> b) -> [a] -> Bool-orderedOn f = orderedBy (comparing f)---- | check if a list is strictly ordered by a given ordering function-strictlyOrderedBy :: (a -> a -> Ordering) -> [a] -> Bool-strictlyOrderedBy _ [] = True-strictlyOrderedBy _ [_] = True-strictlyOrderedBy cmp (x:y:xs) = case x `cmp` y of- LT -> strictlyOrderedBy cmp (y:xs)- _ -> False--strictlyOrderedOn :: Ord b => (a -> b) -> [a] -> Bool-strictlyOrderedOn f = strictlyOrderedBy (comparing f)--ifNotEq :: Ordering -> Ordering -> Ordering--- Could be implemented as: ifNotEq = mappend-ifNotEq EQ p = p-ifNotEq o _ = o--thn :: (a->a->Ordering) -> (a->a->Ordering) -> a -> a -> Ordering-thn cmp1 cmp2 x y = (x `cmp1` y) `ifNotEq` (x `cmp2` y)-infixr 9 `thn`----- | checks if the first 'n' elements on tiers are ordered by 'cmp'.------ > (n `seriesOrderedBy`) comparing (id :: Type)-tOrderedBy :: Listable a => Int -> (a -> a -> Ordering) -> Bool-tOrderedBy n cmp = orderedBy cmp $ take n list-infixr 9 `tOrderedBy`--tStrictlyOrderedBy :: Listable a => Int -> (a -> a -> Ordering) -> Bool-tStrictlyOrderedBy n cmp = strictlyOrderedBy cmp $ take n list-infixr 9 `tStrictlyOrderedBy`--tNatPairOrd :: Int -> Bool-tNatPairOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' (x,y) = x+y :: Nat--tNatTripleOrd :: Int -> Bool-tNatTripleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' (x,y,z) = x+y+z :: Nat--tNatQuadrupleOrd :: Int -> Bool-tNatQuadrupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' (x,y,z,w) = x+y+z+w :: Nat--tNatQuintupleOrd :: Int -> Bool-tNatQuintupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' (x,y,z,w,v) = x+y+z+w+v :: Nat--tNatSixtupleOrd :: Int -> Bool-tNatSixtupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' (x,y,z,w,v,u) = x+y+z+w+v+u :: Nat--tNatListOrd :: Int -> Bool-tNatListOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare- where sum' = sum . map (+1) :: [Nat] -> Nat--tListsOfStrictlyOrderedBy :: Int- -> (a -> a -> Ordering)- -> [[a]]- -> Bool-tListsOfStrictlyOrderedBy n cmp = strictlyOrderedBy cmp . take n . concat-infixr 9 `tListsOfStrictlyOrderedBy`--tListsOfNatOrd :: Int -> Bool-tListsOfNatOrd n = tListsOfStrictlyOrderedBy n (comparing sum' `thn` compare) tiers- where sum' = sum . map (+1) :: [Nat] -> Nat--tPairEqParams :: Int -> Bool-tPairEqParams n = ces == srs- where- ces = map (map read) $ counterExamples n fail- srs = map pairToList $ take n list- pairToList (x,y) = [x,y :: Nat]- fail :: Nat -> Nat -> Bool- fail x y = False--tTripleEqParams :: Int -> Bool-tTripleEqParams n = ces == srs- where- ces = map (map read) $ counterExamples n fail- srs = map tripleToList $ take n list- tripleToList (x,y,z) = [x,y,z :: Nat]- fail :: Nat -> Nat -> Nat -> Bool- fail x y z = False--tProductsIsFilterByLength :: Eq a => [[a]] -> Int -> Int -> Bool-tProductsIsFilterByLength values m n = concat (take m byProduct) `isPrefixOf` concat byFilter- where byProduct = products $ replicate n values- byFilter = ((==n) . length) `filterT` listsOf values
src/Test/LeanCheck/Utils/TypeBinding.hs view
@@ -92,6 +92,7 @@ , int, integer , float, double , char, string+ , ordering , mayb, eith -- ** Testing types , nat@@ -289,6 +290,9 @@ string :: String string = undefinedOf "string"++ordering :: Ordering+ordering = undefinedOf "ordering" -- | It might be better to just use 'Just' mayb :: a -> Maybe a
src/Test/LeanCheck/Utils/Types.hs view
@@ -465,9 +465,26 @@ instance Listable a => Listable (Bag a) where tiers = bagCons Bag instance Listable a => Listable (Set a) where tiers = setCons Set +-- | 'X' type to be wrapped around integer types for an e-'X'-treme integer+-- enumeration. See the 'Listable' instance for 'X'. Use 'X' when+-- testing properties about overflows and the like:+--+-- > > check $ \x -> x + 1 > (x :: Int)+-- > +++ OK, passed 200 tests.+--+-- > > check $ \(X x) -> x + 1 > (x :: Int)+-- > +++ Failed! Falsifiable (after 4 tests):+-- > 9223372036854775807 newtype X a = X {unX :: a} deriving (Eq, Ord) instance Show a => Show (X a) where show (X x) = show x instance (Integral a, Bounded a) => Listable (X a) where list = map X listXIntegral+-- ^ Extremily large integers are intercalated with small integers.+--+-- > list :: [X Int] = map X+-- > [ 0, 1, -1, maxBound, minBound+-- > , 2, -2, maxBound-1, minBound+1+-- > , 3, -3, maxBound-2, minBound+2+-- > , ... ] -- FIXME: make this work for Int2 / Word2 types -- by checking then using normal enumeration@@ -516,3 +533,4 @@ instance Show a => Show (Xs a) where show (Xs xs) = show xs instance (Integral a, Bounded a) => Listable (Xs a) where tiers = cons1 (Xs . map unX)+-- ^ Lists with elements of the 'X' type.
+ tests/Test.hs view
@@ -0,0 +1,148 @@+-- |+-- Module : Test+-- Copyright : (c) 2015-2017 Rudy Matela+-- License : 3-Clause BSD (see the file LICENSE)+-- Maintainer : Rudy Matela <rudy@matela.com.br>+--+-- This module is part of LeanCheck,+-- a simple enumerative property-based testing library.+--+-- Some helper functios to test LeanCheck itself.+module Test+ ( module Test.LeanCheck++ , tNatPairOrd+ , tNatTripleOrd+ , tNatQuadrupleOrd+ , tNatQuintupleOrd+ , tNatSixtupleOrd+ , tNatListOrd+ , tListsOfNatOrd+ , tPairEqParams+ , tTripleEqParams+ , tProductsIsFilterByLength++ , ordered+ , orderedBy+ , orderedOn+ , strictlyOrdered+ , strictlyOrderedBy+ , strictlyOrderedOn+ )+where++import Test.LeanCheck+import Data.List+import Data.Ord+import Test.LeanCheck.Utils.Types (Nat(..))++-- | check if a list is ordered+ordered :: Ord a => [a] -> Bool+ordered = orderedBy compare+-- ordered [] = True+-- ordered [_] = True+-- ordered (x:y:xs) = x <= y && ordered (y:xs)++strictlyOrdered :: Ord a => [a] -> Bool+strictlyOrdered = strictlyOrderedBy compare++-- | check if a list is ordered by a given ordering function+orderedBy :: (a -> a -> Ordering) -> [a] -> Bool+orderedBy _ [] = True+orderedBy _ [_] = True+orderedBy cmp (x:y:xs) = case x `cmp` y of+ GT -> False+ _ -> orderedBy cmp (y:xs)++orderedOn :: Ord b => (a -> b) -> [a] -> Bool+orderedOn f = orderedBy (comparing f)++-- | check if a list is strictly ordered by a given ordering function+strictlyOrderedBy :: (a -> a -> Ordering) -> [a] -> Bool+strictlyOrderedBy _ [] = True+strictlyOrderedBy _ [_] = True+strictlyOrderedBy cmp (x:y:xs) = case x `cmp` y of+ LT -> strictlyOrderedBy cmp (y:xs)+ _ -> False++strictlyOrderedOn :: Ord b => (a -> b) -> [a] -> Bool+strictlyOrderedOn f = strictlyOrderedBy (comparing f)++ifNotEq :: Ordering -> Ordering -> Ordering+-- Could be implemented as: ifNotEq = mappend+ifNotEq EQ p = p+ifNotEq o _ = o++thn :: (a->a->Ordering) -> (a->a->Ordering) -> a -> a -> Ordering+thn cmp1 cmp2 x y = (x `cmp1` y) `ifNotEq` (x `cmp2` y)+infixr 9 `thn`+++-- | checks if the first 'n' elements on tiers are ordered by 'cmp'.+--+-- > (n `seriesOrderedBy`) comparing (id :: Type)+tOrderedBy :: Listable a => Int -> (a -> a -> Ordering) -> Bool+tOrderedBy n cmp = orderedBy cmp $ take n list+infixr 9 `tOrderedBy`++tStrictlyOrderedBy :: Listable a => Int -> (a -> a -> Ordering) -> Bool+tStrictlyOrderedBy n cmp = strictlyOrderedBy cmp $ take n list+infixr 9 `tStrictlyOrderedBy`++tNatPairOrd :: Int -> Bool+tNatPairOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' (x,y) = x+y :: Nat++tNatTripleOrd :: Int -> Bool+tNatTripleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' (x,y,z) = x+y+z :: Nat++tNatQuadrupleOrd :: Int -> Bool+tNatQuadrupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' (x,y,z,w) = x+y+z+w :: Nat++tNatQuintupleOrd :: Int -> Bool+tNatQuintupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' (x,y,z,w,v) = x+y+z+w+v :: Nat++tNatSixtupleOrd :: Int -> Bool+tNatSixtupleOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' (x,y,z,w,v,u) = x+y+z+w+v+u :: Nat++tNatListOrd :: Int -> Bool+tNatListOrd n = n `tStrictlyOrderedBy` comparing sum' `thn` compare+ where sum' = sum . map (+1) :: [Nat] -> Nat++tListsOfStrictlyOrderedBy :: Int+ -> (a -> a -> Ordering)+ -> [[a]]+ -> Bool+tListsOfStrictlyOrderedBy n cmp = strictlyOrderedBy cmp . take n . concat+infixr 9 `tListsOfStrictlyOrderedBy`++tListsOfNatOrd :: Int -> Bool+tListsOfNatOrd n = tListsOfStrictlyOrderedBy n (comparing sum' `thn` compare) tiers+ where sum' = sum . map (+1) :: [Nat] -> Nat++tPairEqParams :: Int -> Bool+tPairEqParams n = ces == srs+ where+ ces = map (map read) $ counterExamples n fail+ srs = map pairToList $ take n list+ pairToList (x,y) = [x,y :: Nat]+ fail :: Nat -> Nat -> Bool+ fail x y = False++tTripleEqParams :: Int -> Bool+tTripleEqParams n = ces == srs+ where+ ces = map (map read) $ counterExamples n fail+ srs = map tripleToList $ take n list+ tripleToList (x,y,z) = [x,y,z :: Nat]+ fail :: Nat -> Nat -> Nat -> Bool+ fail x y z = False++tProductsIsFilterByLength :: Eq a => [[a]] -> Int -> Int -> Bool+tProductsIsFilterByLength values m n = concat (take m byProduct) `isPrefixOf` concat byFilter+ where byProduct = products $ replicate n values+ byFilter = ((==n) . length) `filterT` listsOf values
tests/test-derive.hs view
@@ -1,8 +1,9 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE). {-# LANGUAGE TemplateHaskell, CPP #-}-import Test.LeanCheck.Derive+import Test import Test.LeanCheck+import Test.LeanCheck.Derive import System.Exit (exitFailure) import Data.List (elemIndices) import Test.LeanCheck.Utils.Operators
tests/test-error.hs view
@@ -1,5 +1,7 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test ()+ import System.Exit (exitFailure) import Data.List (elemIndices,sort)
tests/test-operators.hs view
@@ -1,5 +1,7 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+ import System.Exit (exitFailure) import Data.List (elemIndices,sort) import Test.LeanCheck
tests/test-tiers.hs view
@@ -1,10 +1,11 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+ import System.Exit (exitFailure) import Data.List (elemIndices, sort, nub, delete) import Test.LeanCheck-import Test.LeanCheck.Invariants import Test.LeanCheck.Utils import Test.LeanCheck.Tiers
tests/test-types.hs view
@@ -1,5 +1,6 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test import System.Exit (exitFailure) import Data.List (elemIndices,delete,isPrefixOf) import Test.LeanCheck.Utils.Types
tests/test.hs view
@@ -1,10 +1,11 @@ -- Copyright (c) 2015-2017 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE).+import Test+ import System.Exit (exitFailure) import Data.List (elemIndices) import Test.LeanCheck-import Test.LeanCheck.Invariants import Test.LeanCheck.Utils import Data.Ratio@@ -17,6 +18,7 @@ is -> do putStrLn ("Failed tests:" ++ show is) exitFailure +tests :: [Bool] tests = [ True