summaryrefslogtreecommitdiff
path: root/testsuite/tests/lib/Data.ByteString/bytestring001.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/lib/Data.ByteString/bytestring001.hs')
-rw-r--r--testsuite/tests/lib/Data.ByteString/bytestring001.hs948
1 files changed, 948 insertions, 0 deletions
diff --git a/testsuite/tests/lib/Data.ByteString/bytestring001.hs b/testsuite/tests/lib/Data.ByteString/bytestring001.hs
new file mode 100644
index 0000000000..00cfcb3763
--- /dev/null
+++ b/testsuite/tests/lib/Data.ByteString/bytestring001.hs
@@ -0,0 +1,948 @@
+#!/usr/bin/env runhaskell
+--
+-- Uses multi-param type classes
+--
+
+import Test.QuickCheck.Batch
+import Test.QuickCheck
+import Text.Show.Functions
+
+import Data.Char
+import Data.Int
+import Data.List
+import Data.Maybe
+import Data.Word
+
+import System.IO
+import System.Environment
+import System.IO.Unsafe
+import System.Random
+
+import Control.Monad ( liftM2 )
+import Control.Monad.Instances ()
+
+import Text.Printf
+import Debug.Trace
+
+import Foreign.Ptr
+
+import Data.ByteString.Lazy (ByteString(..), pack , unpack)
+import qualified Data.ByteString.Lazy as L
+
+import Data.ByteString.Fusion
+import qualified Data.ByteString as P
+import qualified Data.ByteString.Lazy as L
+import qualified Data.ByteString.Lazy.Internal as L
+
+import qualified Data.ByteString.Char8 as PC
+import qualified Data.ByteString.Lazy.Char8 as LC
+import qualified Data.ByteString as P
+import qualified Data.ByteString.Internal as P
+import qualified Data.ByteString.Char8 as C
+import qualified Data.ByteString.Lazy.Char8 as D
+import Data.ByteString.Fusion
+
+import Prelude hiding (abs)
+
+-- Enable this to get verbose test output. Including the actual tests.
+debug = False
+
+mytest :: Testable a => a -> Int -> IO ()
+mytest a n = mycheck defaultConfig
+ { configMaxTest=n
+ , configEvery= \n args -> if debug then show n ++ ":\n" ++ unlines args else [] } a
+
+mycheck :: Testable a => Config -> a -> IO ()
+mycheck config a =
+ do let rnd = mkStdGen 99
+ mytests config (evaluate a) rnd 0 0 []
+
+mytests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO ()
+mytests config gen rnd0 ntest nfail stamps
+ | ntest == configMaxTest config = do done "OK," ntest stamps
+ | nfail == configMaxFail config = do done "Arguments exhausted after" ntest stamps
+ | otherwise =
+ do putStr (configEvery config ntest (arguments result)) >> hFlush stdout
+ case ok result of
+ Nothing ->
+ mytests config gen rnd1 ntest (nfail+1) stamps
+ Just True ->
+ mytests config gen rnd1 (ntest+1) nfail (stamp result:stamps)
+ Just False ->
+ putStr ( "Falsifiable after "
+ ++ show ntest
+ ++ " tests:\n"
+ ++ unlines (arguments result)
+ ) >> hFlush stdout
+ where
+ result = generate (configSize config ntest) rnd2 gen
+ (rnd1,rnd2) = split rnd0
+
+done :: String -> Int -> [[String]] -> IO ()
+done mesg ntest stamps =
+ do putStr ( mesg ++ " " ++ show ntest ++ " tests" ++ table )
+ where
+ table = display
+ . map entry
+ . reverse
+ . sort
+ . map pairLength
+ . group
+ . sort
+ . filter (not . null)
+ $ stamps
+
+ display [] = ".\n"
+ display [x] = " (" ++ x ++ ").\n"
+ display xs = ".\n" ++ unlines (map (++ ".") xs)
+
+ pairLength xss@(xs:_) = (length xss, xs)
+ entry (n, xs) = percentage n ntest
+ ++ " "
+ ++ concat (intersperse ", " xs)
+
+ percentage n m = show ((100 * n) `div` m) ++ "%"
+
+------------------------------------------------------------------------
+
+instance Arbitrary Char where
+ arbitrary = choose ('a', 'i')
+ coarbitrary c = variant (ord c `rem` 4)
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (PairS a b) where
+ arbitrary = liftM2 (:*:) arbitrary arbitrary
+ coarbitrary (a :*: b) = coarbitrary a . coarbitrary b
+
+instance Arbitrary Word8 where
+ arbitrary = choose (97, 105)
+ coarbitrary c = variant (fromIntegral ((fromIntegral c) `rem` 4))
+
+instance Arbitrary Int64 where
+ arbitrary = sized $ \n -> choose (-fromIntegral n,fromIntegral n)
+ coarbitrary n = variant (fromIntegral (if n >= 0 then 2*n else 2*(-n) + 1))
+
+instance Arbitrary a => Arbitrary (MaybeS a) where
+ arbitrary = do a <- arbitrary ; elements [NothingS, JustS a]
+ coarbitrary NothingS = variant 0
+ coarbitrary _ = variant 1 -- ok?
+
+{-
+instance Arbitrary Char where
+ arbitrary = choose ('\0', '\255') -- since we have to test words, unlines too
+ coarbitrary c = variant (ord c `rem` 16)
+
+instance Arbitrary Word8 where
+ arbitrary = choose (minBound, maxBound)
+ coarbitrary c = variant (fromIntegral ((fromIntegral c) `rem` 16))
+-}
+
+instance Random Word8 where
+ randomR = integralRandomR
+ random = randomR (minBound,maxBound)
+
+instance Random Int64 where
+ randomR = integralRandomR
+ random = randomR (minBound,maxBound)
+
+integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
+integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
+ fromIntegral b :: Integer) g of
+ (x,g) -> (fromIntegral x, g)
+
+instance Arbitrary L.ByteString where
+ arbitrary = arbitrary >>= return . L.fromChunks . filter (not. P.null) -- maintain the invariant.
+ coarbitrary s = coarbitrary (L.unpack s)
+
+instance Arbitrary P.ByteString where
+ arbitrary = P.pack `fmap` arbitrary
+ coarbitrary s = coarbitrary (P.unpack s)
+
+------------------------------------------------------------------------
+--
+-- We're doing two forms of testing here. Firstly, model based testing.
+-- For our Lazy and strict bytestring types, we have model types:
+--
+-- i.e. Lazy == Byte
+-- \\ //
+-- List
+--
+-- That is, the Lazy type can be modeled by functions in both the Byte
+-- and List type. For each of the 3 models, we have a set of tests that
+-- check those types match.
+--
+-- The Model class connects a type and its model type, via a conversion
+-- function.
+--
+--
+class Model a b where
+ model :: a -> b -- get the abstract vale from a concrete value
+
+--
+-- Connecting our Lazy and Strict types to their models. We also check
+-- the data invariant on Lazy types.
+--
+-- These instances represent the arrows in the above diagram
+--
+instance Model B P where model = abstr . checkInvariant
+instance Model P [W] where model = P.unpack
+instance Model P [Char] where model = PC.unpack
+instance Model B [W] where model = L.unpack . checkInvariant
+instance Model B [Char] where model = LC.unpack . checkInvariant
+
+-- Types are trivially modeled by themselves
+instance Model Bool Bool where model = id
+instance Model Int Int where model = id
+instance Model Int64 Int64 where model = id
+instance Model Int64 Int where model = fromIntegral
+instance Model Word8 Word8 where model = id
+instance Model Ordering Ordering where model = id
+
+-- More structured types are modeled recursively, using the NatTrans class from Gofer.
+class (Functor f, Functor g) => NatTrans f g where
+ eta :: f a -> g a
+
+-- The transformation of the same type is identity
+instance NatTrans [] [] where eta = id
+instance NatTrans Maybe Maybe where eta = id
+instance NatTrans ((->) X) ((->) X) where eta = id
+instance NatTrans ((->) W) ((->) W) where eta = id
+
+-- We have a transformation of pairs, if the pairs are in Model
+instance Model f g => NatTrans ((,) f) ((,) g) where eta (f,a) = (model f, a)
+
+-- And finally, we can take any (m a) to (n b), if we can Model m n, and a b
+instance (NatTrans m n, Model a b) => Model (m a) (n b) where model x = fmap model (eta x)
+
+------------------------------------------------------------------------
+
+-- In a form more useful for QC testing (and it's lazy)
+checkInvariant :: L.ByteString -> L.ByteString
+checkInvariant cs0 = check cs0
+ where check L.Empty = L.Empty
+ check (L.Chunk c cs)
+ | P.null c = error ("invariant violation: " ++ show cs0)
+ | otherwise = L.Chunk c (check cs)
+
+abstr :: L.ByteString -> P.ByteString
+abstr = P.concat . L.toChunks
+
+
+-- Some short hand.
+type X = Int
+type W = Word8
+type P = P.ByteString
+type B = L.ByteString
+
+------------------------------------------------------------------------
+--
+-- These comparison functions handle wrapping and equality.
+--
+-- A single class for these would be nice, but note that they differe in
+-- the number of arguments, and those argument types, so we'd need HList
+-- tricks. See here: http://okmij.org/ftp/Haskell/vararg-fn.lhs
+--
+
+eq1 f g = \a ->
+ model (f a) == g (model a)
+eq2 f g = \a b ->
+ model (f a b) == g (model a) (model b)
+eq3 f g = \a b c ->
+ model (f a b c) == g (model a) (model b) (model c)
+eq4 f g = \a b c d ->
+ model (f a b c d) == g (model a) (model b) (model c) (model d)
+eq5 f g = \a b c d e ->
+ model (f a b c d e) == g (model a) (model b) (model c) (model d) (model e)
+
+--
+-- And for functions that take non-null input
+--
+eqnotnull1 f g = \x -> (not (isNull x)) ==> eq1 f g x
+eqnotnull2 f g = \x y -> (not (isNull y)) ==> eq2 f g x y
+eqnotnull3 f g = \x y z -> (not (isNull z)) ==> eq3 f g x y z
+
+class IsNull t where isNull :: t -> Bool
+instance IsNull L.ByteString where isNull = L.null
+instance IsNull P.ByteString where isNull = P.null
+
+------------------------------------------------------------------------
+
+
+--
+-- ByteString.Lazy <=> ByteString
+--
+
+prop_concatBP = L.concat `eq1` P.concat
+prop_nullBP = L.null `eq1` P.null
+prop_reverseBP = L.reverse `eq1` P.reverse
+prop_transposeBP = L.transpose `eq1` P.transpose
+prop_groupBP = L.group `eq1` P.group
+prop_initsBP = L.inits `eq1` P.inits
+prop_tailsBP = L.tails `eq1` P.tails
+prop_allBP = L.all `eq2` P.all
+prop_anyBP = L.any `eq2` P.any
+prop_appendBP = L.append `eq2` P.append
+prop_breakBP = L.break `eq2` P.break
+-- prop_concatMapBP = L.concatMap `eq2` P.concatMap
+prop_consBP = L.cons `eq2` P.cons
+prop_countBP = L.count `eq2` P.count
+prop_dropBP = L.drop `eq2` P.drop
+prop_dropWhileBP = L.dropWhile `eq2` P.dropWhile
+prop_filterBP = L.filter `eq2` P.filter
+prop_findBP = L.find `eq2` P.find
+prop_findIndexBP = L.findIndex `eq2` P.findIndex
+prop_findIndicesBP = L.findIndices `eq2` P.findIndices
+prop_isPrefixOfBP = L.isPrefixOf `eq2` P.isPrefixOf
+prop_mapBP = L.map `eq2` P.map
+prop_replicateBP = L.replicate `eq2` P.replicate
+prop_snocBP = L.snoc `eq2` P.snoc
+prop_spanBP = L.span `eq2` P.span
+prop_splitBP = L.split `eq2` P.split
+prop_splitAtBP = L.splitAt `eq2` P.splitAt
+prop_takeBP = L.take `eq2` P.take
+prop_takeWhileBP = L.takeWhile `eq2` P.takeWhile
+prop_elemBP = L.elem `eq2` P.elem
+prop_notElemBP = L.notElem `eq2` P.notElem
+prop_elemIndexBP = L.elemIndex `eq2` P.elemIndex
+prop_elemIndicesBP = L.elemIndices `eq2` P.elemIndices
+prop_lengthBP = L.length `eq1` (fromIntegral . P.length :: P.ByteString -> Int64)
+prop_readIntBP = D.readInt `eq1` C.readInt
+prop_linesBP = D.lines `eq1` C.lines
+
+prop_headBP = L.head `eqnotnull1` P.head
+prop_initBP = L.init `eqnotnull1` P.init
+prop_lastBP = L.last `eqnotnull1` P.last
+prop_maximumBP = L.maximum `eqnotnull1` P.maximum
+prop_minimumBP = L.minimum `eqnotnull1` P.minimum
+prop_tailBP = L.tail `eqnotnull1` P.tail
+prop_foldl1BP = L.foldl1 `eqnotnull2` P.foldl1
+prop_foldl1BP' = L.foldl1' `eqnotnull2` P.foldl1'
+prop_foldr1BP = L.foldr1 `eqnotnull2` P.foldr1
+prop_scanlBP = L.scanl `eqnotnull3` P.scanl
+
+prop_eqBP = eq2
+ ((==) :: B -> B -> Bool)
+ ((==) :: P -> P -> Bool)
+prop_compareBP = eq2
+ ((compare) :: B -> B -> Ordering)
+ ((compare) :: P -> P -> Ordering)
+prop_foldlBP = eq3
+ (L.foldl :: (X -> W -> X) -> X -> B -> X)
+ (P.foldl :: (X -> W -> X) -> X -> P -> X)
+prop_foldlBP' = eq3
+ (L.foldl' :: (X -> W -> X) -> X -> B -> X)
+ (P.foldl' :: (X -> W -> X) -> X -> P -> X)
+prop_foldrBP = eq3
+ (L.foldr :: (W -> X -> X) -> X -> B -> X)
+ (P.foldr :: (W -> X -> X) -> X -> P -> X)
+prop_mapAccumLBP = eq3
+ (L.mapAccumL :: (X -> W -> (X,W)) -> X -> B -> (X, B))
+ (P.mapAccumL :: (X -> W -> (X,W)) -> X -> P -> (X, P))
+
+prop_unfoldrBP = eq3
+ ((\n f a -> L.take (fromIntegral n) $
+ L.unfoldr f a) :: Int -> (X -> Maybe (W,X)) -> X -> B)
+ ((\n f a -> fst $
+ P.unfoldrN n f a) :: Int -> (X -> Maybe (W,X)) -> X -> P)
+
+--
+-- properties comparing ByteString.Lazy `eq1` List
+--
+
+prop_concatBL = L.concat `eq1` (concat :: [[W]] -> [W])
+prop_lengthBL = L.length `eq1` (length :: [W] -> Int)
+prop_nullBL = L.null `eq1` (null :: [W] -> Bool)
+prop_reverseBL = L.reverse `eq1` (reverse :: [W] -> [W])
+prop_transposeBL = L.transpose `eq1` (transpose :: [[W]] -> [[W]])
+prop_groupBL = L.group `eq1` (group :: [W] -> [[W]])
+prop_initsBL = L.inits `eq1` (inits :: [W] -> [[W]])
+prop_tailsBL = L.tails `eq1` (tails :: [W] -> [[W]])
+prop_allBL = L.all `eq2` (all :: (W -> Bool) -> [W] -> Bool)
+prop_anyBL = L.any `eq2` (any :: (W -> Bool) -> [W] -> Bool)
+prop_appendBL = L.append `eq2` ((++) :: [W] -> [W] -> [W])
+prop_breakBL = L.break `eq2` (break :: (W -> Bool) -> [W] -> ([W],[W]))
+-- prop_concatMapBL = L.concatMap `eq2` (concatMap :: (W -> [W]) -> [W] -> [W])
+prop_consBL = L.cons `eq2` ((:) :: W -> [W] -> [W])
+prop_dropBL = L.drop `eq2` (drop :: Int -> [W] -> [W])
+prop_dropWhileBL = L.dropWhile `eq2` (dropWhile :: (W -> Bool) -> [W] -> [W])
+prop_filterBL = L.filter `eq2` (filter :: (W -> Bool ) -> [W] -> [W])
+prop_findBL = L.find `eq2` (find :: (W -> Bool) -> [W] -> Maybe W)
+prop_findIndicesBL = L.findIndices `eq2` (findIndices:: (W -> Bool) -> [W] -> [Int])
+prop_findIndexBL = L.findIndex `eq2` (findIndex :: (W -> Bool) -> [W] -> Maybe Int)
+prop_isPrefixOfBL = L.isPrefixOf `eq2` (isPrefixOf:: [W] -> [W] -> Bool)
+prop_mapBL = L.map `eq2` (map :: (W -> W) -> [W] -> [W])
+prop_replicateBL = L.replicate `eq2` (replicate :: Int -> W -> [W])
+prop_snocBL = L.snoc `eq2` ((\xs x -> xs ++ [x]) :: [W] -> W -> [W])
+prop_spanBL = L.span `eq2` (span :: (W -> Bool) -> [W] -> ([W],[W]))
+prop_splitAtBL = L.splitAt `eq2` (splitAt :: Int -> [W] -> ([W],[W]))
+prop_takeBL = L.take `eq2` (take :: Int -> [W] -> [W])
+prop_takeWhileBL = L.takeWhile `eq2` (takeWhile :: (W -> Bool) -> [W] -> [W])
+prop_elemBL = L.elem `eq2` (elem :: W -> [W] -> Bool)
+prop_notElemBL = L.notElem `eq2` (notElem :: W -> [W] -> Bool)
+prop_elemIndexBL = L.elemIndex `eq2` (elemIndex :: W -> [W] -> Maybe Int)
+prop_elemIndicesBL = L.elemIndices `eq2` (elemIndices:: W -> [W] -> [Int])
+prop_linesBL = D.lines `eq1` (lines :: String -> [String])
+
+prop_foldl1BL = L.foldl1 `eqnotnull2` (foldl1 :: (W -> W -> W) -> [W] -> W)
+prop_foldl1BL' = L.foldl1' `eqnotnull2` (foldl1' :: (W -> W -> W) -> [W] -> W)
+prop_foldr1BL = L.foldr1 `eqnotnull2` (foldr1 :: (W -> W -> W) -> [W] -> W)
+prop_headBL = L.head `eqnotnull1` (head :: [W] -> W)
+prop_initBL = L.init `eqnotnull1` (init :: [W] -> [W])
+prop_lastBL = L.last `eqnotnull1` (last :: [W] -> W)
+prop_maximumBL = L.maximum `eqnotnull1` (maximum :: [W] -> W)
+prop_minimumBL = L.minimum `eqnotnull1` (minimum :: [W] -> W)
+prop_tailBL = L.tail `eqnotnull1` (tail :: [W] -> [W])
+
+prop_eqBL = eq2
+ ((==) :: B -> B -> Bool)
+ ((==) :: [W] -> [W] -> Bool)
+prop_compareBL = eq2
+ ((compare) :: B -> B -> Ordering)
+ ((compare) :: [W] -> [W] -> Ordering)
+prop_foldlBL = eq3
+ (L.foldl :: (X -> W -> X) -> X -> B -> X)
+ ( foldl :: (X -> W -> X) -> X -> [W] -> X)
+prop_foldlBL' = eq3
+ (L.foldl' :: (X -> W -> X) -> X -> B -> X)
+ ( foldl' :: (X -> W -> X) -> X -> [W] -> X)
+prop_foldrBL = eq3
+ (L.foldr :: (W -> X -> X) -> X -> B -> X)
+ ( foldr :: (W -> X -> X) -> X -> [W] -> X)
+prop_mapAccumLBL = eq3
+ (L.mapAccumL :: (X -> W -> (X,W)) -> X -> B -> (X, B))
+ ( mapAccumL :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W]))
+prop_unfoldrBL = eq3
+ ((\n f a -> L.take (fromIntegral n) $
+ L.unfoldr f a) :: Int -> (X -> Maybe (W,X)) -> X -> B)
+ ((\n f a -> take n $
+ unfoldr f a) :: Int -> (X -> Maybe (W,X)) -> X -> [W])
+
+--
+-- And finally, check correspondance between Data.ByteString and List
+--
+
+prop_lengthPL = (fromIntegral.P.length :: P -> Int) `eq1` (length :: [W] -> Int)
+prop_nullPL = P.null `eq1` (null :: [W] -> Bool)
+prop_reversePL = P.reverse `eq1` (reverse :: [W] -> [W])
+prop_transposePL = P.transpose `eq1` (transpose :: [[W]] -> [[W]])
+prop_groupPL = P.group `eq1` (group :: [W] -> [[W]])
+prop_initsPL = P.inits `eq1` (inits :: [W] -> [[W]])
+prop_tailsPL = P.tails `eq1` (tails :: [W] -> [[W]])
+prop_concatPL = P.concat `eq1` (concat :: [[W]] -> [W])
+prop_allPL = P.all `eq2` (all :: (W -> Bool) -> [W] -> Bool)
+prop_anyPL = P.any `eq2` (any :: (W -> Bool) -> [W] -> Bool)
+prop_appendPL = P.append `eq2` ((++) :: [W] -> [W] -> [W])
+prop_breakPL = P.break `eq2` (break :: (W -> Bool) -> [W] -> ([W],[W]))
+-- prop_concatMapPL = P.concatMap `eq2` (concatMap :: (W -> [W]) -> [W] -> [W])
+prop_consPL = P.cons `eq2` ((:) :: W -> [W] -> [W])
+prop_dropPL = P.drop `eq2` (drop :: Int -> [W] -> [W])
+prop_dropWhilePL = P.dropWhile `eq2` (dropWhile :: (W -> Bool) -> [W] -> [W])
+prop_filterPL = P.filter `eq2` (filter :: (W -> Bool ) -> [W] -> [W])
+prop_findPL = P.find `eq2` (find :: (W -> Bool) -> [W] -> Maybe W)
+prop_findIndexPL = P.findIndex `eq2` (findIndex :: (W -> Bool) -> [W] -> Maybe Int)
+prop_isPrefixOfPL = P.isPrefixOf`eq2` (isPrefixOf:: [W] -> [W] -> Bool)
+prop_mapPL = P.map `eq2` (map :: (W -> W) -> [W] -> [W])
+prop_replicatePL = P.replicate `eq2` (replicate :: Int -> W -> [W])
+prop_snocPL = P.snoc `eq2` ((\xs x -> xs ++ [x]) :: [W] -> W -> [W])
+prop_spanPL = P.span `eq2` (span :: (W -> Bool) -> [W] -> ([W],[W]))
+prop_splitAtPL = P.splitAt `eq2` (splitAt :: Int -> [W] -> ([W],[W]))
+prop_takePL = P.take `eq2` (take :: Int -> [W] -> [W])
+prop_takeWhilePL = P.takeWhile `eq2` (takeWhile :: (W -> Bool) -> [W] -> [W])
+prop_elemPL = P.elem `eq2` (elem :: W -> [W] -> Bool)
+prop_notElemPL = P.notElem `eq2` (notElem :: W -> [W] -> Bool)
+prop_elemIndexPL = P.elemIndex `eq2` (elemIndex :: W -> [W] -> Maybe Int)
+prop_linesPL = C.lines `eq1` (lines :: String -> [String])
+prop_findIndicesPL= P.findIndices`eq2` (findIndices:: (W -> Bool) -> [W] -> [Int])
+prop_elemIndicesPL= P.elemIndices`eq2` (elemIndices:: W -> [W] -> [Int])
+
+prop_foldl1PL = P.foldl1 `eqnotnull2` (foldl1 :: (W -> W -> W) -> [W] -> W)
+prop_foldl1PL' = P.foldl1' `eqnotnull2` (foldl1' :: (W -> W -> W) -> [W] -> W)
+prop_foldr1PL = P.foldr1 `eqnotnull2` (foldr1 :: (W -> W -> W) -> [W] -> W)
+prop_scanlPL = P.scanl `eqnotnull3` (scanl :: (W -> W -> W) -> W -> [W] -> [W])
+prop_scanl1PL = P.scanl1 `eqnotnull2` (scanl1 :: (W -> W -> W) -> [W] -> [W])
+prop_scanrPL = P.scanr `eqnotnull3` (scanr :: (W -> W -> W) -> W -> [W] -> [W])
+prop_scanr1PL = P.scanr1 `eqnotnull2` (scanr1 :: (W -> W -> W) -> [W] -> [W])
+prop_headPL = P.head `eqnotnull1` (head :: [W] -> W)
+prop_initPL = P.init `eqnotnull1` (init :: [W] -> [W])
+prop_lastPL = P.last `eqnotnull1` (last :: [W] -> W)
+prop_maximumPL = P.maximum `eqnotnull1` (maximum :: [W] -> W)
+prop_minimumPL = P.minimum `eqnotnull1` (minimum :: [W] -> W)
+prop_tailPL = P.tail `eqnotnull1` (tail :: [W] -> [W])
+
+prop_eqPL = eq2
+ ((==) :: P -> P -> Bool)
+ ((==) :: [W] -> [W] -> Bool)
+prop_comparePL = eq2
+ ((compare) :: P -> P -> Ordering)
+ ((compare) :: [W] -> [W] -> Ordering)
+prop_foldlPL = eq3
+ (P.foldl :: (X -> W -> X) -> X -> P -> X)
+ ( foldl :: (X -> W -> X) -> X -> [W] -> X)
+prop_foldlPL' = eq3
+ (P.foldl' :: (X -> W -> X) -> X -> P -> X)
+ ( foldl' :: (X -> W -> X) -> X -> [W] -> X)
+prop_foldrPL = eq3
+ (P.foldr :: (W -> X -> X) -> X -> P -> X)
+ ( foldr :: (W -> X -> X) -> X -> [W] -> X)
+prop_mapAccumLPL= eq3
+ (P.mapAccumL :: (X -> W -> (X,W)) -> X -> P -> (X, P))
+ ( mapAccumL :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W]))
+prop_mapAccumRPL= eq3
+ (P.mapAccumR :: (X -> W -> (X,W)) -> X -> P -> (X, P))
+ ( mapAccumR :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W]))
+prop_unfoldrPL = eq3
+ ((\n f a -> fst $
+ P.unfoldrN n f a) :: Int -> (X -> Maybe (W,X)) -> X -> P)
+ ((\n f a -> take n $
+ unfoldr f a) :: Int -> (X -> Maybe (W,X)) -> X -> [W])
+
+------------------------------------------------------------------------
+--
+-- And check fusion RULES.
+--
+
+prop_lazylooploop em1 em2 start1 start2 arr =
+ loopL em2 start2 (loopArr (loopL em1 start1 arr)) ==
+ loopSndAcc (loopL (em1 `fuseEFL` em2) (start1 :*: start2) arr)
+ where
+ _ = start1 :: Int
+ _ = start2 :: Int
+
+prop_looploop em1 em2 start1 start2 arr =
+ loopU em2 start2 (loopArr (loopU em1 start1 arr)) ==
+ loopSndAcc (loopU (em1 `fuseEFL` em2) (start1 :*: start2) arr)
+ where
+ _ = start1 :: Int
+ _ = start2 :: Int
+
+------------------------------------------------------------------------
+
+-- check associativity of sequence loops
+prop_sequenceloops_assoc n m o x y z a1 a2 a3 xs =
+
+ k ((f * g) * h) == k (f * (g * h)) -- associativity
+
+ where
+ (*) = sequenceLoops
+ f = (sel n) x a1
+ g = (sel m) y a2
+ h = (sel o) z a3
+
+ _ = a1 :: Int; _ = a2 :: Int; _ = a3 :: Int
+ k g = loopArr (loopWrapper g xs)
+
+-- check wrapper elimination
+prop_loop_loop_wrapper_elimination n m x y a1 a2 xs =
+ loopWrapper g (loopArr (loopWrapper f xs)) ==
+ loopSndAcc (loopWrapper (sequenceLoops f g) xs)
+ where
+ f = (sel n) x a1
+ g = (sel m) y a2
+ _ = a1 :: Int; _ = a2 :: Int
+
+sel :: Bool
+ -> (acc -> Word8 -> PairS acc (MaybeS Word8))
+ -> acc
+ -> Ptr Word8
+ -> Ptr Word8
+ -> Int
+ -> IO (PairS (PairS acc Int) Int)
+sel False = doDownLoop
+sel True = doUpLoop
+
+------------------------------------------------------------------------
+--
+-- Test fusion forms
+--
+
+prop_up_up_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doUpLoop f1 acc1) (doUpLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int; k g = loopWrapper g xs
+
+prop_down_down_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doDownLoop f1 acc1) (doDownLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseAccAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int ; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_noAcc_noAcc_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doNoAccLoop f1 acc1) (doNoAccLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseNoAccNoAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int ; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_noAcc_up_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doNoAccLoop f1 acc1) (doUpLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int; k g = loopWrapper g xs
+
+prop_up_noAcc_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doUpLoop f1 acc1) (doNoAccLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int; k g = loopWrapper g xs
+
+prop_noAcc_down_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doNoAccLoop f1 acc1) (doDownLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseNoAccAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_down_noAcc_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doDownLoop f1 acc1) (doNoAccLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseAccNoAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int; k g = loopWrapper g xs
+
+prop_map_map_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doMapLoop f1 acc1) (doMapLoop f2 acc2)) ==
+ k (doMapLoop (f1 `fuseMapMapEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_filter_filter_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doFilterLoop f1 acc1) (doFilterLoop f2 acc2)) ==
+ k (doFilterLoop (f1 `fuseFilterFilterEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_map_filter_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doMapLoop f1 acc1) (doFilterLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseMapFilterEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_filter_map_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doFilterLoop f1 acc1) (doMapLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseFilterMapEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_map_noAcc_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doMapLoop f1 acc1) (doNoAccLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseMapNoAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_noAcc_map_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doNoAccLoop f1 acc1) (doMapLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseNoAccMapEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_map_up_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doMapLoop f1 acc1) (doUpLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_up_map_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doUpLoop f1 acc1) (doMapLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_map_down_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doMapLoop f1 acc1) (doDownLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseMapAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_down_map_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doDownLoop f1 acc1) (doMapLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseAccMapEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_filter_noAcc_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doFilterLoop f1 acc1) (doNoAccLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseFilterNoAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_noAcc_filter_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doNoAccLoop f1 acc1) (doFilterLoop f2 acc2)) ==
+ k (doNoAccLoop (f1 `fuseNoAccFilterEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_filter_up_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doFilterLoop f1 acc1) (doUpLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_up_filter_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doUpLoop f1 acc1) (doFilterLoop f2 acc2)) ==
+ k (doUpLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_filter_down_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doFilterLoop f1 acc1) (doDownLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseFilterAccEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+prop_down_filter_loop_fusion f1 f2 acc1 acc2 xs =
+ k (sequenceLoops (doDownLoop f1 acc1) (doFilterLoop f2 acc2)) ==
+ k (doDownLoop (f1 `fuseAccFilterEFL` f2) (acc1 :*: acc2))
+ where _ = acc1 :: Int; _ = acc2 :: Int ; k g = loopWrapper g xs
+
+------------------------------------------------------------------------
+
+prop_length_loop_fusion_1 f1 acc1 xs =
+ P.length (loopArr (loopWrapper (doUpLoop f1 acc1) xs)) ==
+ P.foldl' (const . (+1)) 0 (loopArr (loopWrapper (doUpLoop f1 acc1) xs))
+ where _ = acc1 :: Int
+
+prop_length_loop_fusion_2 f1 acc1 xs =
+ P.length (loopArr (loopWrapper (doDownLoop f1 acc1) xs)) ==
+ P.foldl' (const . (+1)) 0 (loopArr (loopWrapper (doDownLoop f1 acc1) xs))
+ where _ = acc1 :: Int
+
+prop_length_loop_fusion_3 f1 acc1 xs =
+ P.length (loopArr (loopWrapper (doMapLoop f1 acc1) xs)) ==
+ P.foldl' (const . (+1)) 0 (loopArr (loopWrapper (doMapLoop f1 acc1) xs))
+ where _ = acc1 :: Int
+
+prop_length_loop_fusion_4 f1 acc1 xs =
+ P.length (loopArr (loopWrapper (doFilterLoop f1 acc1) xs)) ==
+ P.foldl' (const . (+1)) 0 (loopArr (loopWrapper (doFilterLoop f1 acc1) xs))
+ where _ = acc1 :: Int
+
+------------------------------------------------------------------------
+-- The entry point
+
+main :: IO ()
+main = myrun tests
+
+myrun :: [(String, Int -> IO ())] -> IO ()
+myrun tests = do
+ x <- getArgs
+ let n = if null x then 100 else read . head $ x
+ mapM_ (\(s,a) -> printf "%-25s: " s >> a n) tests
+
+--
+-- And now a list of all the properties to test.
+--
+
+tests = misc_tests
+ ++ bl_tests
+ ++ bp_tests
+ ++ pl_tests
+ ++ fusion_tests
+
+misc_tests =
+ [("invariant", mytest prop_invariant)]
+
+------------------------------------------------------------------------
+-- ByteString.Lazy <=> List
+
+bl_tests =
+ [("all", mytest prop_allBL)
+ ,("any", mytest prop_anyBL)
+ ,("append", mytest prop_appendBL)
+ ,("compare", mytest prop_compareBL)
+ ,("concat", mytest prop_concatBL)
+ ,("cons", mytest prop_consBL)
+ ,("eq", mytest prop_eqBL)
+ ,("filter", mytest prop_filterBL)
+ ,("find", mytest prop_findBL)
+ ,("findIndex", mytest prop_findIndexBL)
+ ,("findIndices", mytest prop_findIndicesBL)
+ ,("foldl", mytest prop_foldlBL)
+ ,("foldl'", mytest prop_foldlBL')
+ ,("foldl1", mytest prop_foldl1BL)
+ ,("foldl1'", mytest prop_foldl1BL')
+ ,("foldr", mytest prop_foldrBL)
+ ,("foldr1", mytest prop_foldr1BL)
+ ,("mapAccumL", mytest prop_mapAccumLBL)
+ ,("unfoldr", mytest prop_unfoldrBL)
+ ,("head", mytest prop_headBL)
+ ,("init", mytest prop_initBL)
+ ,("isPrefixOf", mytest prop_isPrefixOfBL)
+ ,("last", mytest prop_lastBL)
+ ,("length", mytest prop_lengthBL)
+ ,("map", mytest prop_mapBL)
+ ,("maximum", mytest prop_maximumBL)
+ ,("minimum", mytest prop_minimumBL)
+ ,("null", mytest prop_nullBL)
+ ,("reverse", mytest prop_reverseBL)
+ ,("snoc", mytest prop_snocBL)
+ ,("tail", mytest prop_tailBL)
+ ,("transpose", mytest prop_transposeBL)
+ ,("replicate", mytest prop_replicateBL)
+ ,("take", mytest prop_takeBL)
+ ,("drop", mytest prop_dropBL)
+ ,("splitAt", mytest prop_splitAtBL)
+ ,("takeWhile", mytest prop_takeWhileBL)
+ ,("dropWhile", mytest prop_dropWhileBL)
+ ,("break", mytest prop_breakBL)
+ ,("span", mytest prop_spanBL)
+ ,("group", mytest prop_groupBL)
+ ,("inits", mytest prop_initsBL)
+ ,("tails", mytest prop_tailsBL)
+ ,("elem", mytest prop_elemBL)
+ ,("notElem", mytest prop_notElemBL)
+ ,("lines", mytest prop_linesBL)
+ ,("elemIndex", mytest prop_elemIndexBL)
+ ,("elemIndices", mytest prop_elemIndicesBL)
+-- ,("concatMap", mytest prop_concatMapBL)
+ ]
+
+------------------------------------------------------------------------
+-- ByteString.Lazy <=> ByteString
+
+bp_tests =
+ [("all", mytest prop_allBP)
+ ,("any", mytest prop_anyBP)
+ ,("append", mytest prop_appendBP)
+ ,("compare", mytest prop_compareBP)
+ ,("concat", mytest prop_concatBP)
+ ,("cons", mytest prop_consBP)
+ ,("eq", mytest prop_eqBP)
+ ,("filter", mytest prop_filterBP)
+ ,("find", mytest prop_findBP)
+ ,("findIndex", mytest prop_findIndexBP)
+ ,("findIndices", mytest prop_findIndicesBP)
+ ,("foldl", mytest prop_foldlBP)
+ ,("foldl'", mytest prop_foldlBP')
+ ,("foldl1", mytest prop_foldl1BP)
+ ,("foldl1'", mytest prop_foldl1BP')
+ ,("foldr", mytest prop_foldrBP)
+ ,("foldr1", mytest prop_foldr1BP)
+ ,("mapAccumL", mytest prop_mapAccumLBP)
+ ,("unfoldr", mytest prop_unfoldrBP)
+ ,("head", mytest prop_headBP)
+ ,("init", mytest prop_initBP)
+ ,("isPrefixOf", mytest prop_isPrefixOfBP)
+ ,("last", mytest prop_lastBP)
+ ,("length", mytest prop_lengthBP)
+ ,("readInt", mytest prop_readIntBP)
+ ,("lines", mytest prop_linesBP)
+ ,("map", mytest prop_mapBP)
+ ,("maximum ", mytest prop_maximumBP)
+ ,("minimum" , mytest prop_minimumBP)
+ ,("null", mytest prop_nullBP)
+ ,("reverse", mytest prop_reverseBP)
+ ,("snoc", mytest prop_snocBP)
+ ,("tail", mytest prop_tailBP)
+ ,("scanl", mytest prop_scanlBP)
+ ,("transpose", mytest prop_transposeBP)
+ ,("replicate", mytest prop_replicateBP)
+ ,("take", mytest prop_takeBP)
+ ,("drop", mytest prop_dropBP)
+ ,("splitAt", mytest prop_splitAtBP)
+ ,("takeWhile", mytest prop_takeWhileBP)
+ ,("dropWhile", mytest prop_dropWhileBP)
+ ,("break", mytest prop_breakBP)
+ ,("span", mytest prop_spanBP)
+ ,("split", mytest prop_splitBP)
+ ,("count", mytest prop_countBP)
+ ,("group", mytest prop_groupBP)
+ ,("inits", mytest prop_initsBP)
+ ,("tails", mytest prop_tailsBP)
+ ,("elem", mytest prop_elemBP)
+ ,("notElem", mytest prop_notElemBP)
+ ,("elemIndex", mytest prop_elemIndexBP)
+ ,("elemIndices", mytest prop_elemIndicesBP)
+-- ,("concatMap", mytest prop_concatMapBP)
+ ]
+
+------------------------------------------------------------------------
+-- ByteString <=> List
+
+pl_tests =
+ [("all", mytest prop_allPL)
+ ,("any", mytest prop_anyPL)
+ ,("append", mytest prop_appendPL)
+ ,("compare", mytest prop_comparePL)
+ ,("concat", mytest prop_concatPL)
+ ,("cons", mytest prop_consPL)
+ ,("eq", mytest prop_eqPL)
+ ,("filter", mytest prop_filterPL)
+ ,("find", mytest prop_findPL)
+ ,("findIndex", mytest prop_findIndexPL)
+ ,("findIndices", mytest prop_findIndicesPL)
+ ,("foldl", mytest prop_foldlPL)
+ ,("foldl'", mytest prop_foldlPL')
+ ,("foldl1", mytest prop_foldl1PL)
+ ,("foldl1'", mytest prop_foldl1PL')
+ ,("foldr1", mytest prop_foldr1PL)
+ ,("foldr", mytest prop_foldrPL)
+ ,("mapAccumL", mytest prop_mapAccumLPL)
+ ,("mapAccumR", mytest prop_mapAccumRPL)
+ ,("unfoldr", mytest prop_unfoldrPL)
+ ,("scanl", mytest prop_scanlPL)
+ ,("scanl1", mytest prop_scanl1PL)
+ ,("scanr", mytest prop_scanrPL)
+ ,("scanr1", mytest prop_scanr1PL)
+ ,("head", mytest prop_headPL)
+ ,("init", mytest prop_initPL)
+ ,("last", mytest prop_lastPL)
+ ,("maximum", mytest prop_maximumPL)
+ ,("minimum", mytest prop_minimumPL)
+ ,("tail", mytest prop_tailPL)
+ ,("isPrefixOf", mytest prop_isPrefixOfPL)
+ ,("length", mytest prop_lengthPL)
+ ,("map", mytest prop_mapPL)
+ ,("null", mytest prop_nullPL)
+ ,("reverse", mytest prop_reversePL)
+ ,("snoc", mytest prop_snocPL)
+ ,("transpose", mytest prop_transposePL)
+ ,("replicate", mytest prop_replicatePL)
+ ,("take", mytest prop_takePL)
+ ,("drop", mytest prop_dropPL)
+ ,("splitAt", mytest prop_splitAtPL)
+ ,("takeWhile", mytest prop_takeWhilePL)
+ ,("dropWhile", mytest prop_dropWhilePL)
+ ,("break", mytest prop_breakPL)
+ ,("span", mytest prop_spanPL)
+ ,("group", mytest prop_groupPL)
+ ,("inits", mytest prop_initsPL)
+ ,("tails", mytest prop_tailsPL)
+ ,("elem", mytest prop_elemPL)
+ ,("notElem", mytest prop_notElemPL)
+ ,("lines", mytest prop_linesBL)
+ ,("elemIndex", mytest prop_elemIndexPL)
+ ,("elemIndices", mytest prop_elemIndicesPL)
+-- ,("concatMap", mytest prop_concatMapPL)
+ ]
+
+------------------------------------------------------------------------
+-- Fusion rules
+
+fusion_tests =
+-- v1 fusion
+ [ ("lazy loop/loop fusion", mytest prop_lazylooploop)
+ , ("loop/loop fusion", mytest prop_looploop)
+
+-- v2 fusion
+ ,("loop/loop wrapper elim", mytest prop_loop_loop_wrapper_elimination)
+ ,("sequence association", mytest prop_sequenceloops_assoc)
+
+ ,("up/up loop fusion", mytest prop_up_up_loop_fusion)
+ ,("down/down loop fusion", mytest prop_down_down_loop_fusion)
+ ,("noAcc/noAcc loop fusion", mytest prop_noAcc_noAcc_loop_fusion)
+ ,("noAcc/up loop fusion", mytest prop_noAcc_up_loop_fusion)
+ ,("up/noAcc loop fusion", mytest prop_up_noAcc_loop_fusion)
+ ,("noAcc/down loop fusion", mytest prop_noAcc_down_loop_fusion)
+ ,("down/noAcc loop fusion", mytest prop_down_noAcc_loop_fusion)
+ ,("map/map loop fusion", mytest prop_map_map_loop_fusion)
+ ,("filter/filter loop fusion", mytest prop_filter_filter_loop_fusion)
+ ,("map/filter loop fusion", mytest prop_map_filter_loop_fusion)
+ ,("filter/map loop fusion", mytest prop_filter_map_loop_fusion)
+ ,("map/noAcc loop fusion", mytest prop_map_noAcc_loop_fusion)
+ ,("noAcc/map loop fusion", mytest prop_noAcc_map_loop_fusion)
+ ,("map/up loop fusion", mytest prop_map_up_loop_fusion)
+ ,("up/map loop fusion", mytest prop_up_map_loop_fusion)
+ ,("map/down loop fusion", mytest prop_map_down_fusion)
+ ,("down/map loop fusion", mytest prop_down_map_loop_fusion)
+ ,("filter/noAcc loop fusion", mytest prop_filter_noAcc_loop_fusion)
+ ,("noAcc/filter loop fusion", mytest prop_noAcc_filter_loop_fusion)
+ ,("filter/up loop fusion", mytest prop_filter_up_loop_fusion)
+ ,("up/filter loop fusion", mytest prop_up_filter_loop_fusion)
+ ,("filter/down loop fusion", mytest prop_filter_down_fusion)
+ ,("down/filter loop fusion", mytest prop_down_filter_loop_fusion)
+
+ ,("length/loop fusion", mytest prop_length_loop_fusion_1)
+ ,("length/loop fusion", mytest prop_length_loop_fusion_2)
+ ,("length/loop fusion", mytest prop_length_loop_fusion_3)
+ ,("length/loop fusion", mytest prop_length_loop_fusion_4)
+ ]
+
+
+------------------------------------------------------------------------
+--
+-- These are miscellaneous tests left over. Or else they test some
+-- property internal to a type (i.e. head . sort == minimum), without
+-- reference to a model type.
+--
+
+invariant :: L.ByteString -> Bool
+invariant L.Empty = True
+invariant (L.Chunk c cs) = not (P.null c) && invariant cs
+
+prop_invariant = invariant
+