2{-# LANGUAGE OverloadedLists #-}
3{-# LANGUAGE TypeFamilies #-}
5module Main (main) where
7import Control.Applicative (ZipList(..))
8import Control.Concurrent (MVar, takeMVar, putMVar, newEmptyMVar)
9import Control.Exception
10 (BlockedIndefinitelyOnMVar(..), catches,
11 BlockedIndefinitelyOnSTM(..), Handler(..))
12import Control.Monad (when, forM_, replicateM, replicateM_)
13import Control.Monad.IO.Class (MonadIO(..))
14import Data.Function ((&))
15import Data.IORef (readIORef, modifyIORef, newIORef, modifyIORef', IORef)
17 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
18 elemIndex, find, insertBy, intersperse, foldl1', (\\),
19 maximumBy, minimumBy, deleteBy, isPrefixOf, isSubsequenceOf,
20 stripPrefix, intercalate)
21import Data.Maybe (mapMaybe)
22import GHC.Word (Word8)
24import Test.Hspec.QuickCheck
26 (counterexample, Property, withMaxSuccess, forAll, choose, Gen,
27 arbitrary, elements, frequency, listOf) --, listOf1, vectorOf, suchThat)
28import Test.QuickCheck.Monadic (run, monadicIO, monitor, assert, PropertyM)
33import Streamly.Prelude ((.:), nil)
34import qualified Streamly.Prelude as S
35import qualified Streamly.Data.Fold as FL
37-- Coverage build takes too long with default number of tests
45singleton :: IsStream t => a -> t m a
48sortEq :: Ord a => [a] -> [a] -> Bool
49sortEq a b = sort a == sort b
53 => (a -> a -> Bool) -> a -> a -> PropertyM m ()
54equals eq stream list = do
55 when (not $ stream `eq` list) $
58 "stream " <> show stream
59 <> "\nlist " <> show list
61 assert (stream `eq` list)
64 :: (Show a, Eq a, MonadIO m)
65 => ([a] -> [a] -> Bool) -> [a] -> [a] -> PropertyM m ()
66listEquals eq stream list = do
67 when (not $ stream `eq` list) $ liftIO $ putStrLn $
68 "stream " <> show stream
69 <> "\nlist " <> show list
70 <> "\nstream \\\\ list " <> show (stream \\ list)
71 <> "\nlist \\\\ stream " <> show (list \\ stream)
72 when (not $ stream `eq` list) $
75 "stream " <> show stream
76 <> "\nlist " <> show list
77 <> "\nstream \\\\ list " <> show (stream \\ list)
78 <> "\nlist \\\\ stream " <> show (list \\ stream)
80 assert (stream `eq` list)
82-------------------------------------------------------------------------------
83-- Construction operations
84-------------------------------------------------------------------------------
90 -> (t IO a -> SerialT IO a)
93constructWithLen mkStream mkList op len = withMaxSuccess maxTestCount $
95 stream <- run $ (S.toList . op) (mkStream (fromIntegral len))
96 let list = mkList (fromIntegral len)
97 listEquals (==) stream list
102 -> (t IO Int -> SerialT IO Int)
105constructWithLenM mkStream mkList op len = withMaxSuccess maxTestCount $
107 stream <- run $ (S.toList . op) (mkStream (fromIntegral len))
108 list <- run $ mkList (fromIntegral len)
109 listEquals (==) stream list
111constructWithReplicate, constructWithReplicateM, constructWithIntFromThenTo
113 => (t IO Int -> SerialT IO Int)
117constructWithReplicateM = constructWithLenM stream list
118 where list = flip replicateM (return 1 :: IO Int)
119 stream = flip S.replicateM (return 1 :: IO Int)
121constructWithReplicate = constructWithLen stream list
122 where list = flip replicate (1 :: Int)
123 stream = flip S.replicate (1 :: Int)
125constructWithIntFromThenTo op l =
126 forAll (choose (minBound, maxBound)) $ \from ->
127 forAll (choose (minBound, maxBound)) $ \next ->
128 forAll (choose (minBound, maxBound)) $ \to ->
129 let list len = take len [from,next..to]
130 stream len = S.take len $ S.enumerateFromThenTo from next to
131 in constructWithLen stream list op l
133#if __GLASGOW_HASKELL__ >= 806
134-- XXX try very small steps close to 0
135constructWithDoubleFromThenTo
137 => (t IO Double -> SerialT IO Double)
140constructWithDoubleFromThenTo op l =
141 forAll (choose (-9007199254740999,9007199254740999)) $ \from ->
142 forAll (choose (-9007199254740999,9007199254740999)) $ \next ->
143 forAll (choose (-9007199254740999,9007199254740999)) $ \to ->
144 let list len = take len [from,next..to]
145 stream len = S.take len $ S.enumerateFromThenTo from next to
146 in constructWithLen stream list op l
149constructWithIterate ::
150 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
151constructWithIterate op len =
152 withMaxSuccess maxTestCount $
156 (S.toList . op . S.take (fromIntegral len))
157 (S.iterate (+ 1) (0 :: Int))
158 let list = take (fromIntegral len) (iterate (+ 1) 0)
159 listEquals (==) stream list
161constructWithIterateM ::
162 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
163constructWithIterateM op len =
164 withMaxSuccess maxTestCount $
166 mvl <- run (newIORef [] :: IO (IORef [Int]))
167 let addM mv x y = modifyIORef' mv (++ [y + x]) >> return (y + x)
168 list = take (fromIntegral len) (iterate (+ 1) 0)
171 S.take (fromIntegral len) $
172 S.iterateM (addM mvl 1) (addM mvl 0 0 :: IO Int)
173 streamEffect <- run $ readIORef mvl
174 listEquals (==) streamEffect list
176constructWithFromIndices ::
177 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
178constructWithFromIndices op len =
179 withMaxSuccess maxTestCount $
182 run $ (S.toList . op . S.take (fromIntegral len)) (S.fromIndices id)
183 let list = take (fromIntegral len) (iterate (+ 1) 0)
184 listEquals (==) stream list
186constructWithFromIndicesM ::
187 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
188constructWithFromIndicesM op len =
189 withMaxSuccess maxTestCount $
191 mvl <- run (newIORef [] :: IO (IORef [Int]))
192 let addIndex mv i = modifyIORef' mv (++ [i]) >> return i
193 list = take (fromIntegral len) (iterate (+ 1) 0)
196 S.take (fromIntegral len) $ S.fromIndicesM (addIndex mvl)
197 streamEffect <- run $ readIORef mvl
198 listEquals (==) streamEffect list
200-------------------------------------------------------------------------------
201-- Concurrent generation
202-------------------------------------------------------------------------------
204mvarExcHandler :: String -> BlockedIndefinitelyOnMVar -> IO ()
205mvarExcHandler label BlockedIndefinitelyOnMVar =
206 error $ label <> " " <> "BlockedIndefinitelyOnMVar\n"
208stmExcHandler :: String -> BlockedIndefinitelyOnSTM -> IO ()
209stmExcHandler label BlockedIndefinitelyOnSTM =
210 error $ label <> " " <> "BlockedIndefinitelyOnSTM\n"
212dbgMVar :: String -> IO () -> IO ()
213dbgMVar label action =
214 action `catches` [ Handler (mvarExcHandler label)
215 , Handler (stmExcHandler label)
218-- | first n actions takeMVar and the last action performs putMVar n times
219mvarSequenceOp :: MVar () -> Word8 -> Word8 -> IO Word8
220mvarSequenceOp mv n x = do
221 let msg = show x <> "/" <> show n
223 then dbgMVar ("take mvarSequenceOp " <> msg) (takeMVar mv) >> return x
224 else dbgMVar ("put mvarSequenceOp" <> msg)
225 (replicateM_ (fromIntegral n) (putMVar mv ())) >> return x
228 :: ([Word8] -> t IO Word8)
229 -> ([Word8] -> [Word8] -> Bool)
230 -> (Word8 -> MVar () -> t IO Word8 -> SerialT IO Word8)
233concurrentMapM constr eq op n =
237 mv <- newEmptyMVar :: IO (MVar ())
238 (S.toList . op n mv) (constr list)
239 listEquals eq stream list
241concurrentFromFoldable
243 => ([Word8] -> [Word8] -> Bool)
244 -> (t IO Word8 -> SerialT IO Word8)
247concurrentFromFoldable eq op n =
251 mv <- newEmptyMVar :: IO (MVar ())
252 (S.toList . op) (S.fromFoldableM (fmap (mvarSequenceOp mv n) list))
253 listEquals eq stream list
255sourceUnfoldrM :: IsStream t => MVar () -> Word8 -> t IO Word8
256sourceUnfoldrM mv n = S.unfoldrM step 0
258 -- argument must be integer to avoid overflow of word8 at 255
259 step :: Int -> IO (Maybe (Word8, Int))
261 let msg = show cnt <> "/" <> show n
262 if cnt > fromIntegral n
265 dbgMVar ("put sourceUnfoldrM " <> msg) (putMVar mv ())
266 return (Just (fromIntegral cnt, cnt + 1))
268-- Note that this test is not guaranteed to succeed, because there is no
269-- guarantee of parallelism in case of Async/Ahead streams.
272 => ([Word8] -> [Word8] -> Bool)
273 -> (t IO Word8 -> SerialT IO Word8)
276concurrentUnfoldrM eq op n =
278 -- XXX we should test empty list case as well
281 -- putStrLn $ "concurrentUnfoldrM: " <> show n
282 mv <- newEmptyMVar :: IO (MVar ())
284 -- since unfoldr happens in parallel with the stream processing we
285 -- can do two takeMVar in one iteration. If it is not parallel then
286 -- this will not work and the test will fail.
288 x <- op (sourceUnfoldrM mv n)
289 -- results may not be yielded in order, in case of
290 -- Async/WAsync/Parallel. So we use an increasing count
292 i <- S.yieldM $ readIORef cnt
293 S.yieldM $ modifyIORef cnt (+1)
294 let msg = show i <> "/" <> show n
297 dbgMVar ("first take concurrentUnfoldrM " <> msg)
300 dbgMVar ("second take concurrentUnfoldrM " <> msg)
303 listEquals eq stream list
307 => ([Word8] -> t IO Word8)
309 -> ([Word8] -> [Word8] -> Bool)
310 -> (t IO Word8 -> SerialT IO Word8)
312concurrentOps constr desc eq t = do
313 let prop1 d p = prop d $ withMaxSuccess maxTestCount p
315 prop1 (desc <> " fromFoldableM") $ concurrentFromFoldable eq t
316 prop1 (desc <> " unfoldrM") $ concurrentUnfoldrM eq t
317 -- we pass it the length of the stream n and an mvar mv.
318 -- The stream is [0..n]. The threads communicate in such a way that the
319 -- actions coming first in the stream are dependent on the last action. So
320 -- if the stream is not processed concurrently it will block forever.
321 -- Note that if the size of the stream is bigger than the thread limit
322 -- then it will block even if it is concurrent.
323 prop1 (desc <> " mapM") $
324 concurrentMapM constr eq $ \n mv stream ->
325 t $ S.mapM (mvarSequenceOp mv n) stream
327-------------------------------------------------------------------------------
328-- Concurrent Application
329-------------------------------------------------------------------------------
331concurrentApplication :: IsStream t
332 => ([Word8] -> [Word8] -> Bool)
333 -> (t IO Word8 -> SerialT IO Word8)
336concurrentApplication eq t n = withMaxSuccess maxTestCount $
338 -- XXX we should test empty list case as well
341 -- putStrLn $ "concurrentApplication: " <> show n
342 mv <- newEmptyMVar :: IO (MVar ())
343 -- since unfoldr happens in parallel with the stream processing we
344 -- can do two takeMVar in one iteration. If it is not parallel then
345 -- this will not work and the test will fail.
347 sourceUnfoldrM mv n |&
349 let msg = show x <> "/" <> show n
351 dbgMVar ("first take concurrentApp " <> msg)
354 dbgMVar ("second take concurrentApp " <> msg)
357 listEquals eq stream list
359sourceUnfoldrM1 :: IsStream t => Word8 -> t IO Word8
360sourceUnfoldrM1 n = S.unfoldrM step 0
362 -- argument must be integer to avoid overflow of word8 at 255
363 step :: Int -> IO (Maybe (Word8, Int))
365 if cnt > fromIntegral n
367 else return (Just (fromIntegral cnt, cnt + 1))
369concurrentFoldlApplication :: Word8 -> Property
370concurrentFoldlApplication n =
372 -- XXX we should test empty list case as well
375 sourceUnfoldrM1 n |&. S.foldlM' (\xs x -> return (x : xs)) []
376 listEquals (==) (reverse stream) list
378concurrentFoldrApplication :: Word8 -> Property
379concurrentFoldrApplication n =
381 -- XXX we should test empty list case as well
384 sourceUnfoldrM1 n |&. S.foldrM (\x xs -> xs >>= return . (x :))
386 listEquals (==) stream list
388-------------------------------------------------------------------------------
389-- Transformation operations
390-------------------------------------------------------------------------------
392transformCombineFromList
393 :: Semigroup (t IO Int)
394 => ([Int] -> t IO Int)
395 -> ([Int] -> [Int] -> Bool)
397 -> (t IO Int -> SerialT IO Int)
398 -> (t IO Int -> t IO Int)
403transformCombineFromList constr eq listOp t op a b c =
404 withMaxSuccess maxTestCount $
406 stream <- run ((S.toList . t) $
407 constr a <> op (constr b <> constr c))
408 let list = a <> listOp (b <> c)
409 listEquals eq stream list
411-- XXX add tests for MonadReader and MonadError etc. In case an SVar is
412-- accidentally passed through them.
414-- This tests transform ops along with detecting illegal sharing of SVar across
415-- conurrent streams. These tests work for all stream types whereas
416-- transformCombineOpsOrdered work only for ordered stream types i.e. excluding
418transformCombineOpsCommon
419 :: (IsStream t, Semigroup (t IO Int))
420 => ([Int] -> t IO Int)
422 -> ([Int] -> [Int] -> Bool)
423 -> (t IO Int -> SerialT IO Int)
425transformCombineOpsCommon constr desc eq t = do
426 let transform = transformCombineFromList constr eq
429 prop (desc <> " filter False") $
430 transform (filter (const False)) t (S.filter (const False))
431 prop (desc <> " filter True") $
432 transform (filter (const True)) t (S.filter (const True))
433 prop (desc <> " filter even") $
434 transform (filter even) t (S.filter even)
436 prop (desc <> " filterM False") $
437 transform (filter (const False)) t (S.filterM (const $ return False))
438 prop (desc <> " filterM True") $
439 transform (filter (const True)) t (S.filterM (const $ return True))
440 prop (desc <> " filterM even") $
441 transform (filter even) t (S.filterM (return . even))
443 prop (desc <> " take maxBound") $
444 transform (take maxBound) t (S.take maxBound)
445 prop (desc <> " take 0") $ transform (take 0) t (S.take 0)
447 prop (desc <> " takeWhile True") $
448 transform (takeWhile (const True)) t (S.takeWhile (const True))
449 prop (desc <> " takeWhile False") $
450 transform (takeWhile (const False)) t (S.takeWhile (const False))
452 prop (desc <> " takeWhileM True") $
453 transform (takeWhile (const True)) t (S.takeWhileM (const $ return True))
454 prop (desc <> " takeWhileM False") $
455 transform (takeWhile (const False)) t (S.takeWhileM (const $ return False))
457 prop (desc <> " drop maxBound") $
458 transform (drop maxBound) t (S.drop maxBound)
459 prop (desc <> " drop 0") $ transform (drop 0) t (S.drop 0)
461 prop (desc <> " dropWhile True") $
462 transform (dropWhile (const True)) t (S.dropWhile (const True))
463 prop (desc <> " dropWhile False") $
464 transform (dropWhile (const False)) t (S.dropWhile (const False))
466 prop (desc <> " dropWhileM True") $
467 transform (dropWhile (const True)) t (S.dropWhileM (const $ return True))
468 prop (desc <> " dropWhileM False") $
469 transform (dropWhile (const False)) t (S.dropWhileM (const $ return False))
471 prop (desc <> " deleteBy (<=) maxBound") $
472 transform (deleteBy (<=) maxBound) t (S.deleteBy (<=) maxBound)
473 prop (desc <> " deleteBy (==) 4") $
474 transform (deleteBy (==) 4) t (S.deleteBy (==) 4)
477 prop (desc <> " mapM (+1)") $
478 transform (fmap (+1)) t (S.mapM (\x -> return (x + 1)))
480 prop (desc <> " scanl'") $ transform (scanl' (flip const) 0) t
481 (S.scanl' (flip const) 0)
482 prop (desc <> " scanlM'") $ transform (scanl' (flip const) 0) t
483 (S.scanlM' (\_ a -> return a) 0)
484 prop (desc <> " scanl") $ transform (scanl' (flip const) 0) t
485 (S.scanl' (flip const) 0)
486 prop (desc <> " scanl1'") $ transform (scanl1 (flip const)) t
487 (S.scanl1' (flip const))
488 prop (desc <> " scanl1M'") $ transform (scanl1 (flip const)) t
489 (S.scanl1M' (\_ a -> return a))
491 let f x = if odd x then Just (x + 100) else Nothing
492 prop (desc <> " mapMaybe") $ transform (mapMaybe f) t (S.mapMaybe f)
495 prop (desc <> " reverse") $ transform reverse t S.reverse
496 -- prop (desc <> " reverse'") $ transform reverse t S.reverse'
499 prop (desc <> " intersperseM") $
500 forAll (choose (minBound, maxBound)) $ \n ->
501 transform (intersperse n) t (S.intersperseM $ return n)
502 prop (desc <> " insertBy 0") $
503 forAll (choose (minBound, maxBound)) $ \n ->
504 transform (insertBy compare n) t (S.insertBy compare n)
507 prop (desc <> " concatMap") $
508 forAll (choose (0, 100)) $ \n ->
509 transform (concatMap (const [1..n]))
510 t (S.concatMap (const (S.fromList [1..n])))
512toListFL :: Monad m => FL.Fold m a [a]
515groupSplitOps :: String -> Spec
516groupSplitOps desc = do
518 -- XXX add tests with multichar separators too
521 prop (desc <> " intercalate . splitOnSeq == id (nil separator)") $
522 forAll listWithZeroes $ \xs -> do
523 withMaxSuccess maxTestCount $
525 ys <- S.toList $ FL.splitOnSeq [] toListFL (S.fromList xs)
526 listEquals (==) (intercalate [] ys) xs
528 prop (desc <> " intercalate . splitOnSeq == id (single element separator)") $
529 forAll listWithZeroes $ \xs -> do
530 withMaxSuccess maxTestCount $
532 ys <- S.toList $ FL.splitOnSeq [0] toListFL (S.fromList xs)
533 listEquals (==) (intercalate [0] ys) xs
535 prop (desc <> " concat . splitOnSeq . intercalate == concat (nil separator/possibly empty list)") $
536 forAll listsWithoutZeroes $ \xss -> do
537 withMaxSuccess maxTestCount $
539 let xs = intercalate [] xss
540 ys <- S.toList $ FL.splitOnSeq [0] toListFL (S.fromList xs)
541 listEquals (==) (concat ys) (concat xss)
543 prop (desc <> " concat . splitOnSeq . intercalate == concat (non-nil separator/possibly empty list)") $
544 forAll listsWithoutZeroes $ \xss -> do
545 withMaxSuccess maxTestCount $
547 let xs = intercalate [0] xss
548 ys <- S.toList $ FL.splitOnSeq [0] toListFL (S.fromList xs)
549 listEquals (==) (concat ys) (concat xss)
551 prop (desc <> " splitOnSeq . intercalate == id (exclusive separator/non-empty list)") $
552 forAll listsWithoutZeroes1 $ \xss -> do
553 withMaxSuccess maxTestCount $
555 let xs = intercalate [0] xss
556 ys <- S.toList $ FL.splitOnSeq [0] toListFL (S.fromList xs)
557 listEquals (==) ys xss
560 prop (desc <> " intercalate [x] . splitOn (== x) == id") $
561 forAll listWithZeroes $ \xs -> do
562 withMaxSuccess maxTestCount $
564 ys <- S.toList $ S.splitOn (== 0) toListFL (S.fromList xs)
565 listEquals (==) (intercalate [0] ys) xs
569 listWithZeroes :: Gen [Int]
570 listWithZeroes = listOf $ frequency [(3, arbitrary), (1, elements [0])]
573 listWithoutZeroes = vectorOf 4 $ suchThat arbitrary (/= 0)
575 listsWithoutZeroes :: Gen [[Int]]
576 listsWithoutZeroes = listOf listWithoutZeroes
578 listsWithoutZeroes1 :: Gen [[Int]]
579 listsWithoutZeroes1 = listOf1 listWithoutZeroes
582-- transformation tests that can only work reliably for ordered streams i.e.
583-- Serial, Ahead and Zip. For example if we use "take 1" on an async stream, it
584-- might yield a different result every time.
585transformCombineOpsOrdered
586 :: (IsStream t, Semigroup (t IO Int))
587 => ([Int] -> t IO Int)
589 -> ([Int] -> [Int] -> Bool)
590 -> (t IO Int -> SerialT IO Int)
592transformCombineOpsOrdered constr desc eq t = do
593 let transform = transformCombineFromList constr eq
596 prop (desc <> " take 1") $ transform (take 1) t (S.take 1)
598 prop (desc <> " take 2") $ transform (take 2) t (S.take 2)
599 prop (desc <> " take 3") $ transform (take 3) t (S.take 3)
600 prop (desc <> " take 4") $ transform (take 4) t (S.take 4)
601 prop (desc <> " take 5") $ transform (take 5) t (S.take 5)
603 prop (desc <> " take 10") $ transform (take 10) t (S.take 10)
605 prop (desc <> " takeWhile > 0") $
606 transform (takeWhile (> 0)) t (S.takeWhile (> 0))
608 prop (desc <> " drop 1") $ transform (drop 1) t (S.drop 1)
609 prop (desc <> " drop 10") $ transform (drop 10) t (S.drop 10)
611 prop (desc <> " dropWhile > 0") $
612 transform (dropWhile (> 0)) t (S.dropWhile (> 0))
613 prop (desc <> " scan") $ transform (scanl' (+) 0) t (S.scanl' (+) 0)
615 prop (desc <> " uniq") $ transform referenceUniq t S.uniq
617 prop (desc <> " deleteBy (<=) 0") $
618 transform (deleteBy (<=) 0) t (S.deleteBy (<=) 0)
620 prop (desc <> " findIndices") $
621 transform (findIndices odd) t (S.findIndices odd)
622 prop (desc <> " elemIndices") $
623 transform (elemIndices 0) t (S.elemIndices 0)
625 -- XXX this does not fail when the SVar is shared, need to fix.
626 prop (desc <> " concurrent application") $
627 transform (& fmap (+1)) t (|& S.map (+1))
629-------------------------------------------------------------------------------
630-- Elimination operations
631-------------------------------------------------------------------------------
640eliminateOp constr listOp op a =
642 stream <- run $ op (constr a)
644 equals (==) stream list
646wrapMaybe :: ([a1] -> a2) -> [a1] -> Maybe a2
647wrapMaybe f x = if null x then Nothing else Just (f x)
649wrapOutOfBounds :: ([a1] -> Int -> a2) -> Int -> [a1] -> Maybe a2
650wrapOutOfBounds f i x | null x = Nothing
651 | i >= length x = Nothing
652 | otherwise = Just (f x i)
654wrapThe :: Eq a => [a] -> Maybe a
656 | all (x ==) xs = Just x
657 | otherwise = Nothing
660-- This is the reference uniq implementation to compare uniq against,
661-- we can use uniq from vector package, but for now this should
663referenceUniq :: Eq a => [a] -> [a]
669 | x == y = go (x : xs)
670 | otherwise = x : go (y : xs)
673 :: ([Int] -> t IO Int)
675 -> (t IO Int -> SerialT IO Int)
677eliminationOps constr desc t = do
679 prop (desc <> " null") $ eliminateOp constr null $ S.null . t
680 prop (desc <> " foldl'") $
681 eliminateOp constr (foldl' (+) 0) $ S.foldl' (+) 0 . t
682 prop (desc <> " foldl1'") $
683 eliminateOp constr (wrapMaybe $ foldl1' (+)) $ S.foldl1' (+) . t
685 prop (desc <> " foldr1") $
686 eliminateOp constr (wrapMaybe $ foldr1 (+)) $ S.foldr1 (+) . t
688 prop (desc <> " all") $ eliminateOp constr (all even) $ S.all even . t
689 prop (desc <> " any") $ eliminateOp constr (any even) $ S.any even . t
690 prop (desc <> " and") $ eliminateOp constr (and . fmap (> 0)) $
691 (S.and . S.map (> 0)) . t
692 prop (desc <> " or") $ eliminateOp constr (or . fmap (> 0)) $
693 (S.or . S.map (> 0)) . t
694 prop (desc <> " length") $ eliminateOp constr length $ S.length . t
695 prop (desc <> " sum") $ eliminateOp constr sum $ S.sum . t
696 prop (desc <> " product") $ eliminateOp constr product $ S.product . t
698 prop (desc <> " maximum") $
699 eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
700 prop (desc <> " minimum") $
701 eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
703 prop (desc <> " maximumBy compare") $
704 eliminateOp constr (wrapMaybe $ maximumBy compare) $
705 S.maximumBy compare . t
706 prop (desc <> " maximumBy flip compare") $
707 eliminateOp constr (wrapMaybe $ maximumBy $ flip compare) $
708 S.maximumBy (flip compare) . t
709 prop (desc <> " minimumBy compare") $
710 eliminateOp constr (wrapMaybe $ minimumBy compare) $
711 S.minimumBy compare . t
712 prop (desc <> " minimumBy flip compare") $
713 eliminateOp constr (wrapMaybe $ minimumBy $ flip compare) $
714 S.minimumBy (flip compare) . t
716 prop (desc <> " findIndex") $
717 eliminateOp constr (findIndex odd) $ S.findIndex odd . t
718 prop (desc <> " elemIndex") $
719 eliminateOp constr (elemIndex 3) $ S.elemIndex 3 . t
721 prop (desc <> " !! 5") $
722 eliminateOp constr (wrapOutOfBounds (!!) 5) $ (S.!! 5) . t
723 prop (desc <> " !! 4") $
724 eliminateOp constr (wrapOutOfBounds (!!) 0) $ (S.!! 0) . t
726 prop (desc <> " find") $ eliminateOp constr (find even) $ S.find even . t
727 prop (desc <> " lookup") $
728 eliminateOp constr (lookup 3 . flip zip [1..]) $
729 S.lookup 3 . S.zipWith (\a b -> (b, a)) (S.fromList [(1::Int)..]) . t
730 prop (desc <> " the") $ eliminateOp constr wrapThe $ S.the . t
732 -- Multi-stream eliminations
734 -- XXX Write better tests for substreams.
735 prop (desc <> " isPrefixOf 10") $ eliminateOp constr (isPrefixOf [1..10]) $
736 S.isPrefixOf (S.fromList [(1::Int)..10]) . t
737 prop (desc <> " isSubsequenceOf 10") $
738 eliminateOp constr (isSubsequenceOf $ filter even [1..10]) $
739 S.isSubsequenceOf (S.fromList $ filter even [(1::Int)..10]) . t
740 prop (desc <> " stripPrefix 10") $ eliminateOp constr (stripPrefix [1..10]) $
741 (\s -> s >>= maybe (return Nothing) (fmap Just . S.toList)) .
742 S.stripPrefix (S.fromList [(1::Int)..10]) . t
744-- head/tail/last may depend on the order in case of parallel streams
745-- so we test these only for serial streams.
747 :: ([Int] -> t IO Int)
749 -> (t IO Int -> SerialT IO Int)
751eliminationOpsOrdered constr desc t = do
752 prop (desc <> " head") $ eliminateOp constr (wrapMaybe head) $ S.head . t
753 prop (desc <> " tail") $ eliminateOp constr (wrapMaybe tail) $ \x -> do
756 Nothing -> return Nothing
757 Just s -> Just <$> S.toList s
758 prop (desc <> " last") $ eliminateOp constr (wrapMaybe last) $ S.last . t
759 prop (desc <> " init") $ eliminateOp constr (wrapMaybe init) $ \x -> do
762 Nothing -> return Nothing
763 Just s -> Just <$> S.toList s
766 :: ([Word8] -> t IO Word8)
767 -> (t IO Word8 -> SerialT IO Word8)
768 -> (Word8 -> SerialT IO Word8 -> IO Bool)
769 -> (Word8 -> [Word8] -> Bool)
772elemOp constr op streamOp listOp (x, xs) =
774 stream <- run $ (streamOp x . op) (constr xs)
775 let list = listOp x xs
776 equals (==) stream list
779 :: ([Word8] -> t IO Word8)
781 -> (t IO Word8 -> SerialT IO Word8)
783eliminationOpsWord8 constr desc t = do
784 prop (desc <> " elem") $ elemOp constr t S.elem elem
785 prop (desc <> " notElem") $ elemOp constr t S.notElem notElem
787-------------------------------------------------------------------------------
788-- Semigroup operations
789-------------------------------------------------------------------------------
794 -> ([b] -> [b] -> Bool)
796 -> (t IO a -> SerialT IO b)
799transformFromList constr eq listOp op a =
801 stream <- run ((S.toList . op) (constr a))
803 listEquals eq stream list
806 :: ([Int] -> t IO Int)
807 -> (t IO Int -> SerialT IO Int)
808 -> ([Int] -> [Int] -> Bool)
811foldFromList constr op eq = transformFromList constr eq id op
813-- XXX concatenate streams of multiple elements rather than single elements
817#if __GLASGOW_HASKELL__ < 804
818 , Semigroup (t IO Int)
822 -> ([Int] -> [Int] -> Bool)
823 -> (t IO Int -> SerialT IO Int)
825semigroupOps desc eq t = do
826 prop (desc <> " <>") $ foldFromList (S.foldMapWith (<>) singleton) t eq
827 prop (desc <> " mappend") $ foldFromList (S.foldMapWith mappend singleton) t eq
829-------------------------------------------------------------------------------
831-------------------------------------------------------------------------------
835 => ([Int] -> t IO Int)
837 -> ([Int] -> [Int] -> Bool)
838 -> (t IO Int -> SerialT IO Int)
840functorOps constr desc eq t = do
841 prop (desc <> " id") $ transformFromList constr eq id t
842 prop (desc <> " fmap (+1)") $ transformFromList constr eq (fmap (+1)) $ t . fmap (+1)
844-------------------------------------------------------------------------------
845-- Applicative operations
846-------------------------------------------------------------------------------
849 :: Applicative (t IO)
850 => ([Int] -> t IO Int)
851 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
852 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
855applicativeOps constr eq t (a, b) = withMaxSuccess maxTestCount $
857 stream <- run ((S.toList . t) ((,) <$> constr a <*> constr b))
858 let list = (,) <$> a <*> b
859 listEquals eq stream list
861-------------------------------------------------------------------------------
863-------------------------------------------------------------------------------
866 :: (IsStream t, Applicative (t IO))
867 => ([Int] -> t IO Int)
868 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
869 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
872zipApplicative constr eq t (a, b) = withMaxSuccess maxTestCount $
874 stream1 <- run ((S.toList . t) ((,) <$> constr a <*> constr b))
875 stream2 <- run ((S.toList . t) (pure (,) <*> constr a <*> constr b))
876 stream3 <- run ((S.toList . t) (S.zipWith (,) (constr a) (constr b)))
877 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
878 listEquals eq stream1 list
879 listEquals eq stream2 list
880 listEquals eq stream3 list
884 => ([Int] -> t IO Int)
885 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
886 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
889zipMonadic constr eq t (a, b) = withMaxSuccess maxTestCount $
894 (S.zipWithM (curry return) (constr a) (constr b)))
895 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
896 listEquals eq stream1 list
900 => ([Int] -> t IO Int)
901 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
902 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
905zipAsyncMonadic constr eq t (a, b) = withMaxSuccess maxTestCount $
910 (S.zipWithM (curry return) (constr a) (constr b)))
914 (S.zipAsyncWithM (curry return) (constr a) (constr b)))
915 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
916 listEquals eq stream1 list
917 listEquals eq stream2 list
919-------------------------------------------------------------------------------
921-------------------------------------------------------------------------------
925 => ([Int] -> t IO Int)
926 -> ([Int] -> [Int] -> Bool)
927 -> (t IO Int -> SerialT IO Int)
930monadThen constr eq t (a, b) = withMaxSuccess maxTestCount $ monadicIO $ do
931 stream <- run ((S.toList . t) (constr a >> constr b))
933 listEquals eq stream list
937 => ([Int] -> t IO Int)
938 -> ([Int] -> [Int] -> Bool)
939 -> (t IO Int -> SerialT IO Int)
942monadBind constr eq t (a, b) = withMaxSuccess maxTestCount $
947 (constr a >>= \x -> (+ x) <$> constr b))
948 let list = a >>= \x -> (+ x) <$> b
949 listEquals eq stream list
955 $ modifyMaxSuccess (const 10)
958 let folded :: IsStream t => [a] -> t IO a
959 folded = serially . (\xs ->
961 [x] -> return x -- singleton stream case
962 _ -> S.foldMapWith (<>) return xs
965 let makeCommonOps :: IsStream t => (t m a -> c) -> [(String, t m a -> c)]
968#ifndef COVERAGE_BUILD
969 , ("rate AvgRate 10000", t . avgRate 10000)
970 , ("rate Nothing", t . rate Nothing)
971 , ("maxBuffer 0", t . maxBuffer 0)
972 , ("maxThreads 0", t . maxThreads 0)
973 , ("maxThreads 1", t . maxThreads 1)
974 , ("maxThreads -1", t . maxThreads (-1))
978 let makeOps :: IsStream t => (t m a -> c) -> [(String, t m a -> c)]
979 makeOps t = makeCommonOps t ++
981#ifndef COVERAGE_BUILD
982 ("maxBuffer 1", t . maxBuffer 1)
986 -- For concurrent application test we need a buffer of at least size 2 to
987 -- allow two threads to run.
988 let makeConcurrentAppOps :: IsStream t
989 => (t m a -> c) -> [(String, t m a -> c)]
990 makeConcurrentAppOps t = makeCommonOps t ++
992#ifndef COVERAGE_BUILD
993 ("maxBuffer 2", t . maxBuffer 2)
997 let mapOps spec = mapM_ (\(desc, f) -> describe desc $ spec f)
998 let serialOps :: IsStream t => ((SerialT IO a -> t IO a) -> Spec) -> Spec
999 serialOps spec = mapOps spec $ makeOps serially
1000#ifndef COVERAGE_BUILD
1001 <> [("rate AvgRate 0.00000001", serially . avgRate 0.00000001)]
1002 <> [("maxBuffer -1", serially . maxBuffer (-1))]
1004 let wSerialOps :: IsStream t => ((WSerialT IO a -> t IO a) -> Spec) -> Spec
1005 wSerialOps spec = mapOps spec $ makeOps wSerially
1006#ifndef COVERAGE_BUILD
1007 <> [("rate AvgRate 0.00000001", wSerially . avgRate 0.00000001)]
1008 <> [("maxBuffer (-1)", wSerially . maxBuffer (-1))]
1010 let asyncOps :: IsStream t => ((AsyncT IO a -> t IO a) -> Spec) -> Spec
1011 asyncOps spec = mapOps spec $ makeOps asyncly
1012#ifndef COVERAGE_BUILD
1013 <> [("maxBuffer (-1)", asyncly . maxBuffer (-1))]
1015 let wAsyncOps :: IsStream t => ((WAsyncT IO a -> t IO a) -> Spec) -> Spec
1016 wAsyncOps spec = mapOps spec $ makeOps wAsyncly
1017#ifndef COVERAGE_BUILD
1018 <> [("maxBuffer (-1)", wAsyncly . maxBuffer (-1))]
1020 let aheadOps :: IsStream t => ((AheadT IO a -> t IO a) -> Spec) -> Spec
1021 aheadOps spec = mapOps spec $ makeOps aheadly
1022#ifndef COVERAGE_BUILD
1023 <> [("maxBuffer (-1)", aheadly . maxBuffer (-1))]
1025 let parallelCommonOps :: IsStream t => [(String, ParallelT m a -> t m a)]
1026 parallelCommonOps = []
1027#ifndef COVERAGE_BUILD
1028 <> [("rate AvgRate 0.00000001", parallely . avgRate 0.00000001)]
1029 <> [("maxBuffer (-1)", parallely . maxBuffer (-1))]
1031 let parallelOps :: IsStream t
1032 => ((ParallelT IO a -> t IO a) -> Spec) -> Spec
1033 parallelOps spec = mapOps spec $ makeOps parallely <> parallelCommonOps
1035 let parallelConcurrentAppOps :: IsStream t
1036 => ((ParallelT IO a -> t IO a) -> Spec) -> Spec
1037 parallelConcurrentAppOps spec =
1038 mapOps spec $ makeConcurrentAppOps parallely <> parallelCommonOps
1040 let zipSerialOps :: IsStream t
1041 => ((ZipSerialM IO a -> t IO a) -> Spec) -> Spec
1042 zipSerialOps spec = mapOps spec $ makeOps zipSerially
1043#ifndef COVERAGE_BUILD
1044 <> [("rate AvgRate 0.00000001", zipSerially . avgRate 0.00000001)]
1045 <> [("maxBuffer (-1)", zipSerially . maxBuffer (-1))]
1047 -- Note, the "pure" of applicative Zip streams generates and infinite
1048 -- stream and therefore maxBuffer (-1) must not be used for that case.
1049 let zipAsyncOps :: IsStream t => ((ZipAsyncM IO a -> t IO a) -> Spec) -> Spec
1050 zipAsyncOps spec = mapOps spec $ makeOps zipAsyncly
1052 describe "Construction" $ do
1053 serialOps $ prop "serially replicate" . constructWithReplicate
1055 serialOps $ prop "serially replicateM" . constructWithReplicateM
1056 wSerialOps $ prop "wSerially replicateM" . constructWithReplicateM
1057 aheadOps $ prop "aheadly replicateM" . constructWithReplicateM
1058 asyncOps $ prop "asyncly replicateM" . constructWithReplicateM
1059 wAsyncOps $ prop "wAsyncly replicateM" . constructWithReplicateM
1060 parallelOps $ prop "parallely replicateM" . constructWithReplicateM
1062 serialOps $ prop "serially intFromThenTo" .
1063 constructWithIntFromThenTo
1064#if __GLASGOW_HASKELL__ >= 806
1065 serialOps $ prop "serially DoubleFromThenTo" .
1066 constructWithDoubleFromThenTo
1069 serialOps $ prop "serially iterate" . constructWithIterate
1071 -- XXX test for all types of streams
1072 serialOps $ prop "serially iterateM" . constructWithIterateM
1073 -- take doesn't work well on concurrent streams. Even though it
1074 -- seems like take only has a problem when used with parallely.
1075 -- wSerialOps $ prop "wSerially iterateM" wSerially . constructWithIterate
1076 -- aheadOps $ prop "aheadly iterateM" aheadly . onstructWithIterate
1077 -- asyncOps $ prop "asyncly iterateM" asyncly . constructWithIterate
1078 -- wAsyncOps $ prop "wAsyncly iterateM" wAsyncly . onstructWithIterate
1079 -- parallelOps $ prop "parallely iterateM" parallely . onstructWithIterate
1080 -- XXX add tests for fromIndices
1082 serialOps $ prop "serially fromIndices" . constructWithFromIndices
1084 serialOps $ prop "serially fromIndicesM" . constructWithFromIndicesM
1086 describe "Functor operations" $ do
1087 serialOps $ functorOps S.fromFoldable "serially" (==)
1088 serialOps $ functorOps folded "serially folded" (==)
1089 wSerialOps $ functorOps S.fromFoldable "wSerially" (==)
1090 wSerialOps $ functorOps folded "wSerially folded" (==)
1091 aheadOps $ functorOps S.fromFoldable "aheadly" (==)
1092 aheadOps $ functorOps folded "aheadly folded" (==)
1093 asyncOps $ functorOps S.fromFoldable "asyncly" sortEq
1094 asyncOps $ functorOps folded "asyncly folded" sortEq
1095 wAsyncOps $ functorOps S.fromFoldable "wAsyncly" sortEq
1096 wAsyncOps $ functorOps folded "wAsyncly folded" sortEq
1097 parallelOps $ functorOps S.fromFoldable "parallely" sortEq
1098 parallelOps $ functorOps folded "parallely folded" sortEq
1099 zipSerialOps $ functorOps S.fromFoldable "zipSerially" (==)
1100 zipSerialOps $ functorOps folded "zipSerially folded" (==)
1101 zipAsyncOps $ functorOps S.fromFoldable "zipAsyncly" (==)
1102 zipAsyncOps $ functorOps folded "zipAsyncly folded" (==)
1104 describe "Semigroup operations" $ do
1105 serialOps $ semigroupOps "serially" (==)
1106 wSerialOps $ semigroupOps "wSerially" (==)
1107 aheadOps $ semigroupOps "aheadly" (==)
1108 asyncOps $ semigroupOps "asyncly" sortEq
1109 wAsyncOps $ semigroupOps "wAsyncly" sortEq
1110 parallelOps $ semigroupOps "parallely" sortEq
1111 zipSerialOps $ semigroupOps "zipSerially" (==)
1112 zipAsyncOps $ semigroupOps "zipAsyncly" (==)
1114 describe "Applicative operations" $ do
1115 -- The tests using sorted equality are weaker tests
1116 -- We need to have stronger unit tests for all those
1117 -- XXX applicative with three arguments
1118 serialOps $ prop "serially applicative" . applicativeOps S.fromFoldable (==)
1119 serialOps $ prop "serially applicative folded" . applicativeOps folded (==)
1120 wSerialOps $ prop "wSerially applicative" . applicativeOps S.fromFoldable sortEq
1121 wSerialOps $ prop "wSerially applicative folded" . applicativeOps folded sortEq
1122 aheadOps $ prop "aheadly applicative" . applicativeOps S.fromFoldable (==)
1123 aheadOps $ prop "aheadly applicative folded" . applicativeOps folded (==)
1124 asyncOps $ prop "asyncly applicative" . applicativeOps S.fromFoldable sortEq
1125 asyncOps $ prop "asyncly applicative folded" . applicativeOps folded sortEq
1126 wAsyncOps $ prop "wAsyncly applicative" . applicativeOps S.fromFoldable sortEq
1127 wAsyncOps $ prop "wAsyncly applicative folded" . applicativeOps folded sortEq
1128 parallelOps $ prop "parallely applicative folded" . applicativeOps folded sortEq
1130 -- XXX add tests for indexed/indexedR
1131 describe "Zip operations" $ do
1132 zipSerialOps $ prop "zipSerially applicative" . zipApplicative S.fromFoldable (==)
1133 zipSerialOps $ prop "zipSerially applicative folded" . zipApplicative folded (==)
1134 zipAsyncOps $ prop "zipAsyncly applicative" . zipApplicative S.fromFoldable (==)
1135 zipAsyncOps $ prop "zipAsyncly applicative folded" . zipApplicative folded (==)
1137 -- We test only the serial zip with serial streams and the parallel
1138 -- stream, because the rate setting in these streams can slow down
1140 serialOps $ prop "zip monadic serially" . zipMonadic S.fromFoldable (==)
1141 serialOps $ prop "zip monadic serially folded" . zipMonadic folded (==)
1142 wSerialOps $ prop "zip monadic wSerially" . zipMonadic S.fromFoldable (==)
1143 wSerialOps $ prop "zip monadic wSerially folded" . zipMonadic folded (==)
1144 aheadOps $ prop "zip monadic aheadly" . zipAsyncMonadic S.fromFoldable (==)
1145 aheadOps $ prop "zip monadic aheadly folded" . zipAsyncMonadic folded (==)
1146 asyncOps $ prop "zip monadic asyncly" . zipAsyncMonadic S.fromFoldable (==)
1147 asyncOps $ prop "zip monadic asyncly folded" . zipAsyncMonadic folded (==)
1148 wAsyncOps $ prop "zip monadic wAsyncly" . zipAsyncMonadic S.fromFoldable (==)
1149 wAsyncOps $ prop "zip monadic wAsyncly folded" . zipAsyncMonadic folded (==)
1150 parallelOps $ prop "zip monadic parallely" . zipMonadic S.fromFoldable (==)
1151 parallelOps $ prop "zip monadic parallely folded" . zipMonadic folded (==)
1153 -- XXX add merge tests like zip tests
1154 -- for mergeBy, we can split a list randomly into two lists and
1155 -- then merge them, it should result in original list
1156 -- describe "Merge operations" $ do
1158 describe "Monad operations" $ do
1159 serialOps $ prop "serially monad then" . monadThen S.fromFoldable (==)
1160 wSerialOps $ prop "wSerially monad then" . monadThen S.fromFoldable sortEq
1161 aheadOps $ prop "aheadly monad then" . monadThen S.fromFoldable (==)
1162 asyncOps $ prop "asyncly monad then" . monadThen S.fromFoldable sortEq
1163 wAsyncOps $ prop "wAsyncly monad then" . monadThen S.fromFoldable sortEq
1164 parallelOps $ prop "parallely monad then" . monadThen S.fromFoldable sortEq
1166 serialOps $ prop "serially monad then folded" . monadThen folded (==)
1167 wSerialOps $ prop "wSerially monad then folded" . monadThen folded sortEq
1168 aheadOps $ prop "aheadly monad then folded" . monadThen folded (==)
1169 asyncOps $ prop "asyncly monad then folded" . monadThen folded sortEq
1170 wAsyncOps $ prop "wAsyncly monad then folded" . monadThen folded sortEq
1171 parallelOps $ prop "parallely monad then folded" . monadThen folded sortEq
1173 serialOps $ prop "serially monad bind" . monadBind S.fromFoldable (==)
1174 wSerialOps $ prop "wSerially monad bind" . monadBind S.fromFoldable sortEq
1175 aheadOps $ prop "aheadly monad bind" . monadBind S.fromFoldable (==)
1176 asyncOps $ prop "asyncly monad bind" . monadBind S.fromFoldable sortEq
1177 wAsyncOps $ prop "wAsyncly monad bind" . monadBind S.fromFoldable sortEq
1178 parallelOps $ prop "parallely monad bind" . monadBind S.fromFoldable sortEq
1180 serialOps $ prop "serially monad bind folded" . monadBind folded (==)
1181 wSerialOps $ prop "wSerially monad bind folded" . monadBind folded sortEq
1182 aheadOps $ prop "aheadly monad bind folded" . monadBind folded (==)
1183 asyncOps $ prop "asyncly monad bind folded" . monadBind folded sortEq
1184 wAsyncOps $ prop "wAsyncly monad bind folded" . monadBind folded sortEq
1185 parallelOps $ prop "parallely monad bind folded" . monadBind folded sortEq
1187 -- These tests won't work with maxBuffer or maxThreads set to 1, so we
1188 -- exclude those cases from these.
1189 let mkOps :: IsStream t => (t m a -> c) -> [(String, t m a -> c)]
1192#ifndef COVERAGE_BUILD
1193 , ("rate Nothing", t . rate Nothing)
1194 , ("maxBuffer 0", t . maxBuffer 0)
1195 , ("maxThreads 0", t . maxThreads 0)
1196 , ("maxThreads 0", t . maxThreads (-1))
1200 let forOps ops spec = forM_ ops (\(desc, f) -> describe desc $ spec f)
1201 describe "Stream concurrent operations" $ do
1202 forOps (mkOps aheadly) $ concurrentOps S.fromFoldable "aheadly" (==)
1203 forOps (mkOps asyncly) $ concurrentOps S.fromFoldable "asyncly" sortEq
1204 forOps (mkOps wAsyncly) $ concurrentOps S.fromFoldable "wAsyncly" sortEq
1205 forOps (mkOps parallely) $ concurrentOps S.fromFoldable "parallely" sortEq
1207 forOps (mkOps aheadly) $ concurrentOps folded "aheadly folded" (==)
1208 forOps (mkOps asyncly) $ concurrentOps folded "asyncly folded" sortEq
1209 forOps (mkOps wAsyncly) $ concurrentOps folded "wAsyncly folded" sortEq
1210 forOps (mkOps parallely) $ concurrentOps folded "parallely folded" sortEq
1212 describe "Concurrent application" $ do
1213 serialOps $ prop "serial" . concurrentApplication (==)
1214 asyncOps $ prop "async" . concurrentApplication sortEq
1215 aheadOps $ prop "ahead" . concurrentApplication (==)
1216 parallelConcurrentAppOps $
1217 prop "parallel" . concurrentApplication sortEq
1219 prop "concurrent foldr application" $ withMaxSuccess maxTestCount
1220 concurrentFoldrApplication
1221 prop "concurrent foldl application" $ withMaxSuccess maxTestCount
1222 concurrentFoldlApplication
1224 describe "Stream transform and combine operations" $ do
1225 serialOps $ transformCombineOpsCommon S.fromFoldable "serially" (==)
1226 wSerialOps $ transformCombineOpsCommon S.fromFoldable "wSerially" sortEq
1227 aheadOps $ transformCombineOpsCommon S.fromFoldable "aheadly" (==)
1228 asyncOps $ transformCombineOpsCommon S.fromFoldable "asyncly" sortEq
1229 wAsyncOps $ transformCombineOpsCommon S.fromFoldable "wAsyncly" sortEq
1230 parallelOps $ transformCombineOpsCommon S.fromFoldable "parallely" sortEq
1231 zipSerialOps $ transformCombineOpsCommon S.fromFoldable "zipSerially" (==)
1232 zipAsyncOps $ transformCombineOpsCommon S.fromFoldable "zipAsyncly" (==)
1234 serialOps $ transformCombineOpsCommon folded "serially" (==)
1235 wSerialOps $ transformCombineOpsCommon folded "wSerially" sortEq
1236 aheadOps $ transformCombineOpsCommon folded "aheadly" (==)
1237 asyncOps $ transformCombineOpsCommon folded "asyncly" sortEq
1238 wAsyncOps $ transformCombineOpsCommon folded "wAsyncly" sortEq
1239 parallelOps $ transformCombineOpsCommon folded "parallely" sortEq
1240 zipSerialOps $ transformCombineOpsCommon folded "zipSerially" (==)
1241 zipAsyncOps $ transformCombineOpsCommon folded "zipAsyncly" (==)
1243 serialOps $ transformCombineOpsOrdered S.fromFoldable "serially" (==)
1244 aheadOps $ transformCombineOpsOrdered S.fromFoldable "aheadly" (==)
1245 zipSerialOps $ transformCombineOpsOrdered S.fromFoldable "zipSerially" (==)
1246 zipAsyncOps $ transformCombineOpsOrdered S.fromFoldable "zipAsyncly" (==)
1248 serialOps $ transformCombineOpsOrdered folded "serially" (==)
1249 aheadOps $ transformCombineOpsOrdered folded "aheadly" (==)
1250 zipSerialOps $ transformCombineOpsOrdered folded "zipSerially" (==)
1251 zipAsyncOps $ transformCombineOpsOrdered folded "zipAsyncly" (==)
1253 describe "Stream group and split operations" $ do
1254 groupSplitOps "serially"
1256 describe "Stream elimination operations" $ do
1257 serialOps $ eliminationOps S.fromFoldable "serially"
1258 wSerialOps $ eliminationOps S.fromFoldable "wSerially"
1259 aheadOps $ eliminationOps S.fromFoldable "aheadly"
1260 asyncOps $ eliminationOps S.fromFoldable "asyncly"
1261 wAsyncOps $ eliminationOps S.fromFoldable "wAsyncly"
1262 parallelOps $ eliminationOps S.fromFoldable "parallely"
1263 zipSerialOps $ eliminationOps S.fromFoldable "zipSerially"
1264 zipAsyncOps $ eliminationOps S.fromFoldable "zipAsyncly"
1266 serialOps $ eliminationOps folded "serially folded"
1267 wSerialOps $ eliminationOps folded "wSerially folded"
1268 aheadOps $ eliminationOps folded "aheadly folded"
1269 asyncOps $ eliminationOps folded "asyncly folded"
1270 wAsyncOps $ eliminationOps folded "wAsyncly folded"
1271 parallelOps $ eliminationOps folded "parallely folded"
1272 zipSerialOps $ eliminationOps folded "zipSerially folded"
1273 zipAsyncOps $ eliminationOps folded "zipAsyncly folded"
1275 serialOps $ eliminationOpsWord8 S.fromFoldable "serially"
1276 wSerialOps $ eliminationOpsWord8 S.fromFoldable "wSerially"
1277 aheadOps $ eliminationOpsWord8 S.fromFoldable "aheadly"
1278 asyncOps $ eliminationOpsWord8 S.fromFoldable "asyncly"
1279 wAsyncOps $ eliminationOpsWord8 S.fromFoldable "wAsyncly"
1280 parallelOps $ eliminationOpsWord8 S.fromFoldable "parallely"
1281 zipSerialOps $ eliminationOpsWord8 S.fromFoldable "zipSerially"
1282 zipAsyncOps $ eliminationOpsWord8 S.fromFoldable "zipAsyncly"
1284 serialOps $ eliminationOpsWord8 folded "serially folded"
1285 wSerialOps $ eliminationOpsWord8 folded "wSerially folded"
1286 aheadOps $ eliminationOpsWord8 folded "aheadly folded"
1287 asyncOps $ eliminationOpsWord8 folded "asyncly folded"
1288 wAsyncOps $ eliminationOpsWord8 folded "wAsyncly folded"
1289 parallelOps $ eliminationOpsWord8 folded "parallely folded"
1290 zipSerialOps $ eliminationOpsWord8 folded "zipSerially folded"
1291 zipAsyncOps $ eliminationOpsWord8 folded "zipAsyncly folded"
1293 -- XXX Add a test where we chain all transformation APIs and make sure that
1294 -- the state is being passed through all of them.
1295 describe "Stream serial elimination operations" $ do
1296 serialOps $ eliminationOpsOrdered S.fromFoldable "serially"
1297 wSerialOps $ eliminationOpsOrdered S.fromFoldable "wSerially"
1298 aheadOps $ eliminationOpsOrdered S.fromFoldable "aheadly"
1299 zipSerialOps $ eliminationOpsOrdered S.fromFoldable "zipSerially"
1300 zipAsyncOps $ eliminationOpsOrdered S.fromFoldable "zipAsyncly"
1302 serialOps $ eliminationOpsOrdered folded "serially folded"
1303 wSerialOps $ eliminationOpsOrdered folded "wSerially folded"
1304 aheadOps $ eliminationOpsOrdered folded "aheadly folded"
1305 zipSerialOps $ eliminationOpsOrdered folded "zipSerially folded"
1306 zipAsyncOps $ eliminationOpsOrdered folded "zipAsyncly folded"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list