on 57fad21 help sign in
streamly/test/Prop.hs
1125 lines 48 kB history raw
1{-# LANGUAGE CPP #-}
3module Main (main) where
5import Control.Applicative (ZipList(..))
6import Control.Concurrent (MVar, takeMVar, putMVar, newEmptyMVar)
7import Control.Exception
8 (BlockedIndefinitelyOnMVar(..), catches,
9 BlockedIndefinitelyOnSTM(..), Handler(..))
10import Control.Monad (when, forM_, replicateM, replicateM_)
11import Control.Monad.IO.Class (MonadIO(..))
12import Data.Function ((&))
13import Data.IORef (readIORef, modifyIORef, newIORef)
14import Data.List
15 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
16 elemIndex, find, insertBy, intersperse, foldl1', (\\),
17 maximumBy, minimumBy, deleteBy, isPrefixOf, isSubsequenceOf,
18 stripPrefix)
19import Data.Maybe (mapMaybe)
20import GHC.Word (Word8)
22import Test.Hspec.QuickCheck
23import Test.QuickCheck
24 (counterexample, Property, withMaxSuccess, forAll, choose)
25import Test.QuickCheck.Monadic (run, monadicIO, monitor, assert, PropertyM)
27import Test.Hspec as H
29import Streamly
30import Streamly.Prelude ((.:), nil)
31import qualified Streamly.Prelude as S
33-- Coverage build takes too long with default number of tests
34maxTestCount :: Int
35#ifdef DEVBUILD
36maxTestCount = 100
37#else
38maxTestCount = 10
39#endif
41singleton :: IsStream t => a -> t m a
42singleton a = a .: nil
44sortEq :: Ord a => [a] -> [a] -> Bool
45sortEq a b = sort a == sort b
47equals
48 :: (Show a, Monad m)
49 => (a -> a -> Bool) -> a -> a -> PropertyM m ()
50equals eq stream list = do
51 when (not $ stream `eq` list) $
52 monitor
53 (counterexample $
54 "stream " <> show stream
55 <> "\nlist " <> show list
56 )
57 assert (stream `eq` list)
59listEquals
60 :: (Show a, Eq a, MonadIO m)
61 => ([a] -> [a] -> Bool) -> [a] -> [a] -> PropertyM m ()
62listEquals eq stream list = do
63 when (not $ stream `eq` list) $ liftIO $ putStrLn $
64 "stream " <> show stream
65 <> "\nlist " <> show list
66 <> "\nstream \\\\ list " <> show (stream \\ list)
67 <> "\nlist \\\\ stream " <> show (list \\ stream)
68 when (not $ stream `eq` list) $
69 monitor
70 (counterexample $
71 "stream " <> show stream
72 <> "\nlist " <> show list
73 <> "\nstream \\\\ list " <> show (stream \\ list)
74 <> "\nlist \\\\ stream " <> show (list \\ stream)
75 )
76 assert (stream `eq` list)
78-------------------------------------------------------------------------------
79-- Construction operations
80-------------------------------------------------------------------------------
82constructWithLen
83 :: (Show a, Eq a)
84 => (Int -> t IO a)
85 -> (Int -> [a])
86 -> (t IO a -> SerialT IO a)
87 -> Word8
88 -> Property
89constructWithLen mkStream mkList op len = withMaxSuccess maxTestCount $
90 monadicIO $ do
91 stream <- run $ (S.toList . op) (mkStream (fromIntegral len))
92 let list = mkList (fromIntegral len)
93 listEquals (==) stream list
95constructWithLenM
96 :: (Int -> t IO Int)
97 -> (Int -> IO [Int])
98 -> (t IO Int -> SerialT IO Int)
99 -> Word8
100 -> Property
101constructWithLenM mkStream mkList op len = withMaxSuccess maxTestCount $
102 monadicIO $ do
103 stream <- run $ (S.toList . op) (mkStream (fromIntegral len))
104 list <- run $ mkList (fromIntegral len)
105 listEquals (==) stream list
107constructWithReplicate, constructWithReplicateM, constructWithIntFromThenTo
108 :: IsStream t
109 => (t IO Int -> SerialT IO Int)
110 -> Word8
111 -> Property
113constructWithReplicateM = constructWithLenM stream list
114 where list = flip replicateM (return 1 :: IO Int)
115 stream = flip S.replicateM (return 1 :: IO Int)
117constructWithReplicate = constructWithLen stream list
118 where list = flip replicate (1 :: Int)
119 stream = flip S.replicate (1 :: Int)
121constructWithIntFromThenTo op l =
122 forAll (choose (minBound, maxBound)) $ \from ->
123 forAll (choose (minBound, maxBound)) $ \next ->
124 forAll (choose (minBound, maxBound)) $ \to ->
125 let list len = take len [from,next..to]
126 stream len = S.take len $ S.intFromThenTo from next to
127 in constructWithLen stream list op l
129#if __GLASGOW_HASKELL__ >= 806
130-- XXX try very small steps close to 0
131constructWithDoubleFromThenTo
132 :: IsStream t
133 => (t IO Double -> SerialT IO Double)
134 -> Word8
135 -> Property
136constructWithDoubleFromThenTo op l =
137 forAll (choose (-9007199254740999,9007199254740999)) $ \from ->
138 forAll (choose (-9007199254740999,9007199254740999)) $ \next ->
139 forAll (choose (-9007199254740999,9007199254740999)) $ \to ->
140 let list len = take len [from,next..to]
141 stream len = S.take len $ S.fracFromThenTo from next to
142 in constructWithLen stream list op l
143#endif
145constructWithIterate :: IsStream t => (t IO Int -> SerialT IO Int) -> Spec
146constructWithIterate t = do
147 it "iterate" $
148 (S.toList . t . S.take 100) (S.iterate (+ 1) (0 :: Int))
149 `shouldReturn` take 100 (iterate (+ 1) 0)
150 it "iterateM" $ do
151 let addM y = return (y + 1)
152 S.toList . t . S.take 100 $ S.iterateM addM (0 :: Int)
153 `shouldReturn` take 100 (iterate (+ 1) 0)
155-------------------------------------------------------------------------------
156-- Concurrent generation
157-------------------------------------------------------------------------------
159mvarExcHandler :: String -> BlockedIndefinitelyOnMVar -> IO ()
160mvarExcHandler label BlockedIndefinitelyOnMVar =
161 error $ label <> " " <> "BlockedIndefinitelyOnMVar\n"
163stmExcHandler :: String -> BlockedIndefinitelyOnSTM -> IO ()
164stmExcHandler label BlockedIndefinitelyOnSTM =
165 error $ label <> " " <> "BlockedIndefinitelyOnSTM\n"
167dbgMVar :: String -> IO () -> IO ()
168dbgMVar label action =
169 action `catches` [ Handler (mvarExcHandler label)
170 , Handler (stmExcHandler label)
171 ]
173-- | first n actions takeMVar and the last action performs putMVar n times
174mvarSequenceOp :: MVar () -> Word8 -> Word8 -> IO Word8
175mvarSequenceOp mv n x = do
176 let msg = show x <> "/" <> show n
177 if x < n
178 then dbgMVar ("take mvarSequenceOp " <> msg) (takeMVar mv) >> return x
179 else dbgMVar ("put mvarSequenceOp" <> msg)
180 (replicateM_ (fromIntegral n) (putMVar mv ())) >> return x
182concurrentMapM
183 :: ([Word8] -> t IO Word8)
184 -> ([Word8] -> [Word8] -> Bool)
185 -> (Word8 -> MVar () -> t IO Word8 -> SerialT IO Word8)
186 -> Word8
187 -> Property
188concurrentMapM constr eq op n =
189 monadicIO $ do
190 let list = [0..n]
191 stream <- run $ do
192 mv <- newEmptyMVar :: IO (MVar ())
193 (S.toList . op n mv) (constr list)
194 listEquals eq stream list
196concurrentFromFoldable
197 :: IsStream t
198 => ([Word8] -> [Word8] -> Bool)
199 -> (t IO Word8 -> SerialT IO Word8)
200 -> Word8
201 -> Property
202concurrentFromFoldable eq op n =
203 monadicIO $ do
204 let list = [0..n]
205 stream <- run $ do
206 mv <- newEmptyMVar :: IO (MVar ())
207 (S.toList . op) (S.fromFoldableM (fmap (mvarSequenceOp mv n) list))
208 listEquals eq stream list
210sourceUnfoldrM :: IsStream t => MVar () -> Word8 -> t IO Word8
211sourceUnfoldrM mv n = S.unfoldrM step 0
212 where
213 -- argument must be integer to avoid overflow of word8 at 255
214 step :: Int -> IO (Maybe (Word8, Int))
215 step cnt = do
216 let msg = show cnt <> "/" <> show n
217 if cnt > fromIntegral n
218 then return Nothing
219 else do
220 dbgMVar ("put sourceUnfoldrM " <> msg) (putMVar mv ())
221 return (Just (fromIntegral cnt, cnt + 1))
223-- Note that this test is not guaranteed to succeed, because there is no
224-- guarantee of parallelism in case of Async/Ahead streams.
225concurrentUnfoldrM
226 :: IsStream t
227 => ([Word8] -> [Word8] -> Bool)
228 -> (t IO Word8 -> SerialT IO Word8)
229 -> Word8
230 -> Property
231concurrentUnfoldrM eq op n =
232 monadicIO $ do
233 -- XXX we should test empty list case as well
234 let list = [0..n]
235 stream <- run $ do
236 -- putStrLn $ "concurrentUnfoldrM: " <> show n
237 mv <- newEmptyMVar :: IO (MVar ())
238 cnt <- newIORef 0
239 -- since unfoldr happens in parallel with the stream processing we
240 -- can do two takeMVar in one iteration. If it is not parallel then
241 -- this will not work and the test will fail.
242 S.toList $ do
243 x <- op (sourceUnfoldrM mv n)
244 -- results may not be yielded in order, in case of
245 -- Async/WAsync/Parallel. So we use an increasing count
246 -- instead.
247 i <- S.yieldM $ readIORef cnt
248 S.yieldM $ modifyIORef cnt (+1)
249 let msg = show i <> "/" <> show n
250 S.yieldM $
251 when (even i) $ do
252 dbgMVar ("first take concurrentUnfoldrM " <> msg)
253 (takeMVar mv)
254 when (n > i) $
255 dbgMVar ("second take concurrentUnfoldrM " <> msg)
256 (takeMVar mv)
257 return x
258 listEquals eq stream list
260concurrentOps
261 :: IsStream t
262 => ([Word8] -> t IO Word8)
263 -> String
264 -> ([Word8] -> [Word8] -> Bool)
265 -> (t IO Word8 -> SerialT IO Word8)
266 -> Spec
267concurrentOps constr desc eq t = do
268 let prop1 d p = prop d $ withMaxSuccess maxTestCount p
270 prop1 (desc <> " fromFoldableM") $ concurrentFromFoldable eq t
271 prop1 (desc <> " unfoldrM") $ concurrentUnfoldrM eq t
272 -- we pass it the length of the stream n and an mvar mv.
273 -- The stream is [0..n]. The threads communicate in such a way that the
274 -- actions coming first in the stream are dependent on the last action. So
275 -- if the stream is not processed concurrently it will block forever.
276 -- Note that if the size of the stream is bigger than the thread limit
277 -- then it will block even if it is concurrent.
278 prop1 (desc <> " mapM") $
279 concurrentMapM constr eq $ \n mv stream ->
280 t $ S.mapM (mvarSequenceOp mv n) stream
282-------------------------------------------------------------------------------
283-- Concurrent Application
284-------------------------------------------------------------------------------
286concurrentApplication :: IsStream t
287 => ([Word8] -> [Word8] -> Bool)
288 -> (t IO Word8 -> SerialT IO Word8)
289 -> Word8
290 -> Property
291concurrentApplication eq t n = withMaxSuccess maxTestCount $
292 monadicIO $ do
293 -- XXX we should test empty list case as well
294 let list = [0..n]
295 stream <- run $ do
296 -- putStrLn $ "concurrentApplication: " <> show n
297 mv <- newEmptyMVar :: IO (MVar ())
298 -- since unfoldr happens in parallel with the stream processing we
299 -- can do two takeMVar in one iteration. If it is not parallel then
300 -- this will not work and the test will fail.
301 (S.toList . t) $
302 sourceUnfoldrM mv n |&
303 S.mapM (\x -> do
304 let msg = show x <> "/" <> show n
305 when (even x) $ do
306 dbgMVar ("first take concurrentApp " <> msg)
307 (takeMVar mv)
308 when (n > x) $
309 dbgMVar ("second take concurrentApp " <> msg)
310 (takeMVar mv)
311 return x)
312 listEquals eq stream list
314sourceUnfoldrM1 :: IsStream t => Word8 -> t IO Word8
315sourceUnfoldrM1 n = S.unfoldrM step 0
316 where
317 -- argument must be integer to avoid overflow of word8 at 255
318 step :: Int -> IO (Maybe (Word8, Int))
319 step cnt =
320 if cnt > fromIntegral n
321 then return Nothing
322 else return (Just (fromIntegral cnt, cnt + 1))
324concurrentFoldlApplication :: Word8 -> Property
325concurrentFoldlApplication n =
326 monadicIO $ do
327 -- XXX we should test empty list case as well
328 let list = [0..n]
329 stream <- run $
330 sourceUnfoldrM1 n |&. S.foldlM' (\xs x -> return (x : xs)) []
331 listEquals (==) (reverse stream) list
333concurrentFoldrApplication :: Word8 -> Property
334concurrentFoldrApplication n =
335 monadicIO $ do
336 -- XXX we should test empty list case as well
337 let list = [0..n]
338 stream <- run $
339 sourceUnfoldrM1 n |&. S.foldrM (\x xs -> return (x : xs)) []
340 listEquals (==) stream list
342-------------------------------------------------------------------------------
343-- Transformation operations
344-------------------------------------------------------------------------------
346transformCombineFromList
347 :: Semigroup (t IO Int)
348 => ([Int] -> t IO Int)
349 -> ([Int] -> [Int] -> Bool)
350 -> ([Int] -> [Int])
351 -> (t IO Int -> SerialT IO Int)
352 -> (t IO Int -> t IO Int)
353 -> [Int]
354 -> [Int]
355 -> [Int]
356 -> Property
357transformCombineFromList constr eq listOp t op a b c =
358 withMaxSuccess maxTestCount $
359 monadicIO $ do
360 stream <- run ((S.toList . t) $
361 constr a <> op (constr b <> constr c))
362 let list = a <> listOp (b <> c)
363 listEquals eq stream list
365-- XXX add tests for MonadReader and MonadError etc. In case an SVar is
366-- accidentally passed through them.
367--
368-- This tests transform ops along with detecting illegal sharing of SVar across
369-- conurrent streams. These tests work for all stream types whereas
370-- transformCombineOpsOrdered work only for ordered stream types i.e. excluding
371-- the Async type.
372transformCombineOpsCommon
373 :: (IsStream t, Semigroup (t IO Int))
374 => ([Int] -> t IO Int)
375 -> String
376 -> ([Int] -> [Int] -> Bool)
377 -> (t IO Int -> SerialT IO Int)
378 -> Spec
379transformCombineOpsCommon constr desc eq t = do
380 let transform = transformCombineFromList constr eq
382 -- Filtering
383 prop (desc <> " filter False") $
384 transform (filter (const False)) t (S.filter (const False))
385 prop (desc <> " filter True") $
386 transform (filter (const True)) t (S.filter (const True))
387 prop (desc <> " filter even") $
388 transform (filter even) t (S.filter even)
390 prop (desc <> " filterM False") $
391 transform (filter (const False)) t (S.filterM (const $ return False))
392 prop (desc <> " filterM True") $
393 transform (filter (const True)) t (S.filterM (const $ return True))
394 prop (desc <> " filterM even") $
395 transform (filter even) t (S.filterM (return . even))
397 prop (desc <> " take maxBound") $
398 transform (take maxBound) t (S.take maxBound)
399 prop (desc <> " take 0") $ transform (take 0) t (S.take 0)
401 prop (desc <> " takeWhile True") $
402 transform (takeWhile (const True)) t (S.takeWhile (const True))
403 prop (desc <> " takeWhile False") $
404 transform (takeWhile (const False)) t (S.takeWhile (const False))
406 prop (desc <> " takeWhileM True") $
407 transform (takeWhile (const True)) t (S.takeWhileM (const $ return True))
408 prop (desc <> " takeWhileM False") $
409 transform (takeWhile (const False)) t (S.takeWhileM (const $ return False))
411 prop (desc <> " drop maxBound") $
412 transform (drop maxBound) t (S.drop maxBound)
413 prop (desc <> " drop 0") $ transform (drop 0) t (S.drop 0)
415 prop (desc <> " dropWhile True") $
416 transform (dropWhile (const True)) t (S.dropWhile (const True))
417 prop (desc <> " dropWhile False") $
418 transform (dropWhile (const False)) t (S.dropWhile (const False))
420 prop (desc <> " dropWhileM True") $
421 transform (dropWhile (const True)) t (S.dropWhileM (const $ return True))
422 prop (desc <> " dropWhileM False") $
423 transform (dropWhile (const False)) t (S.dropWhileM (const $ return False))
425 prop (desc <> " deleteBy (<=) maxBound") $
426 transform (deleteBy (<=) maxBound) t (S.deleteBy (<=) maxBound)
427 prop (desc <> " deleteBy (==) 4") $
428 transform (deleteBy (==) 4) t (S.deleteBy (==) 4)
430 -- transformation
431 prop (desc <> " mapM (+1)") $
432 transform (fmap (+1)) t (S.mapM (\x -> return (x + 1)))
434 prop (desc <> " scanl'") $ transform (scanl' (flip const) 0) t
435 (S.scanl' (flip const) 0)
436 prop (desc <> " scanlM'") $ transform (scanl' (flip const) 0) t
437 (S.scanlM' (\_ a -> return a) 0)
438 prop (desc <> " scanl") $ transform (scanl' (flip const) 0) t
439 (S.scanl' (flip const) 0)
440 prop (desc <> " scanl1'") $ transform (scanl1 (flip const)) t
441 (S.scanl1' (flip const))
442 prop (desc <> " scanl1M'") $ transform (scanl1 (flip const)) t
443 (S.scanl1M' (\_ a -> return a))
445 let f x = if odd x then Just (x + 100) else Nothing
446 prop (desc <> " mapMaybe") $ transform (mapMaybe f) t (S.mapMaybe f)
448 -- reordering
449 prop (desc <> " reverse") $ transform reverse t S.reverse
451 -- inserting
452 prop (desc <> " intersperseM") $
453 forAll (choose (minBound, maxBound)) $ \n ->
454 transform (intersperse n) t (S.intersperseM $ return n)
455 prop (desc <> " insertBy 0") $
456 forAll (choose (minBound, maxBound)) $ \n ->
457 transform (insertBy compare n) t (S.insertBy compare n)
459 -- multi-stream
460 prop (desc <> " concatMap") $
461 forAll (choose (0, 100)) $ \n ->
462 transform (concatMap (const [1..n]))
463 t (S.concatMap (const (S.fromList [1..n])))
465-- transformation tests that can only work reliably for ordered streams i.e.
466-- Serial, Ahead and Zip. For example if we use "take 1" on an async stream, it
467-- might yield a different result every time.
468transformCombineOpsOrdered
469 :: (IsStream t, Semigroup (t IO Int))
470 => ([Int] -> t IO Int)
471 -> String
472 -> ([Int] -> [Int] -> Bool)
473 -> (t IO Int -> SerialT IO Int)
474 -> Spec
475transformCombineOpsOrdered constr desc eq t = do
476 let transform = transformCombineFromList constr eq
478 -- Filtering
479 prop (desc <> " take 1") $ transform (take 1) t (S.take 1)
480#ifdef DEVBUILD
481 prop (desc <> " take 2") $ transform (take 2) t (S.take 2)
482 prop (desc <> " take 3") $ transform (take 3) t (S.take 3)
483 prop (desc <> " take 4") $ transform (take 4) t (S.take 4)
484 prop (desc <> " take 5") $ transform (take 5) t (S.take 5)
485#endif
486 prop (desc <> " take 10") $ transform (take 10) t (S.take 10)
488 prop (desc <> " takeWhile > 0") $
489 transform (takeWhile (> 0)) t (S.takeWhile (> 0))
491 prop (desc <> " drop 1") $ transform (drop 1) t (S.drop 1)
492 prop (desc <> " drop 10") $ transform (drop 10) t (S.drop 10)
494 prop (desc <> " dropWhile > 0") $
495 transform (dropWhile (> 0)) t (S.dropWhile (> 0))
496 prop (desc <> " scan") $ transform (scanl' (+) 0) t (S.scanl' (+) 0)
498 -- XXX add uniq
499 prop (desc <> " deleteBy (<=) 0") $
500 transform (deleteBy (<=) 0) t (S.deleteBy (<=) 0)
502 prop (desc <> " findIndices") $
503 transform (findIndices odd) t (S.findIndices odd)
504 prop (desc <> " elemIndices") $
505 transform (elemIndices 0) t (S.elemIndices 0)
507 -- XXX this does not fail when the SVar is shared, need to fix.
508 prop (desc <> " concurrent application") $
509 transform (& fmap (+1)) t (|& S.map (+1))
511-------------------------------------------------------------------------------
512-- Elimination operations
513-------------------------------------------------------------------------------
515eliminateOp
516 :: (Show a, Eq a)
517 => ([s] -> t IO s)
518 -> ([s] -> a)
519 -> (t IO s -> IO a)
520 -> [s]
521 -> Property
522eliminateOp constr listOp op a =
523 monadicIO $ do
524 stream <- run $ op (constr a)
525 let list = listOp a
526 equals (==) stream list
528wrapMaybe :: ([a1] -> a2) -> [a1] -> Maybe a2
529wrapMaybe f x = if null x then Nothing else Just (f x)
531wrapOutOfBounds :: ([a1] -> Int -> a2) -> Int -> [a1] -> Maybe a2
532wrapOutOfBounds f i x | null x = Nothing
533 | i >= length x = Nothing
534 | otherwise = Just (f x i)
536wrapThe :: Eq a => [a] -> Maybe a
537wrapThe (x:xs) | all (x ==) xs = Just x
538 | otherwise = Nothing
539wrapThe [] = Nothing
541eliminationOps
542 :: ([Int] -> t IO Int)
543 -> String
544 -> (t IO Int -> SerialT IO Int)
545 -> Spec
546eliminationOps constr desc t = do
547 -- Elimination
548 prop (desc <> " null") $ eliminateOp constr null $ S.null . t
549 prop (desc <> " foldl'") $
550 eliminateOp constr (foldl' (+) 0) $ S.foldl' (+) 0 . t
551 prop (desc <> " foldl1'") $
552 eliminateOp constr (wrapMaybe $ foldl1' (+)) $ S.foldl1' (+) . t
553 prop (desc <> " foldr1") $
554 eliminateOp constr (wrapMaybe $ foldr1 (+)) $ S.foldr1 (+) . t
555 prop (desc <> " all") $ eliminateOp constr (all even) $ S.all even . t
556 prop (desc <> " any") $ eliminateOp constr (any even) $ S.any even . t
557 prop (desc <> " and") $ eliminateOp constr (and . fmap (> 0)) $
558 (S.and . S.map (> 0)) . t
559 prop (desc <> " or") $ eliminateOp constr (or . fmap (> 0)) $
560 (S.or . S.map (> 0)) . t
561 prop (desc <> " length") $ eliminateOp constr length $ S.length . t
562 prop (desc <> " sum") $ eliminateOp constr sum $ S.sum . t
563 prop (desc <> " product") $ eliminateOp constr product $ S.product . t
565 prop (desc <> " maximum") $
566 eliminateOp constr (wrapMaybe maximum) $ S.maximum . t
567 prop (desc <> " minimum") $
568 eliminateOp constr (wrapMaybe minimum) $ S.minimum . t
570 prop (desc <> " maximumBy compare") $
571 eliminateOp constr (wrapMaybe $ maximumBy compare) $
572 S.maximumBy compare . t
573 prop (desc <> " maximumBy flip compare") $
574 eliminateOp constr (wrapMaybe $ maximumBy $ flip compare) $
575 S.maximumBy (flip compare) . t
576 prop (desc <> " minimumBy compare") $
577 eliminateOp constr (wrapMaybe $ minimumBy compare) $
578 S.minimumBy compare . t
579 prop (desc <> " minimumBy flip compare") $
580 eliminateOp constr (wrapMaybe $ minimumBy $ flip compare) $
581 S.minimumBy (flip compare) . t
583 prop (desc <> " findIndex") $
584 eliminateOp constr (findIndex odd) $ S.findIndex odd . t
585 prop (desc <> " elemIndex") $
586 eliminateOp constr (elemIndex 3) $ S.elemIndex 3 . t
588 prop (desc <> " !! 5") $
589 eliminateOp constr (wrapOutOfBounds (!!) 5) $ (S.!! 5) . t
590 prop (desc <> " !! 4") $
591 eliminateOp constr (wrapOutOfBounds (!!) 0) $ (S.!! 0) . t
593 prop (desc <> " find") $ eliminateOp constr (find even) $ S.find even . t
594 prop (desc <> " lookup") $
595 eliminateOp constr (lookup 3 . flip zip [1..]) $
596 S.lookup 3 . S.zipWith (\a b -> (b, a)) (S.fromList [(1::Int)..]) . t
597 prop (desc <> " the") $ eliminateOp constr wrapThe $ S.the . t
599 -- Multi-stream eliminations
600 -- Add eqBy, cmpBy
601 -- XXX Write better tests for substreams.
602 prop (desc <> " isPrefixOf 10") $ eliminateOp constr (isPrefixOf [1..10]) $
603 S.isPrefixOf (S.fromList [(1::Int)..10]) . t
604 prop (desc <> " isSubsequenceOf 10") $
605 eliminateOp constr (isSubsequenceOf $ filter even [1..10]) $
606 S.isSubsequenceOf (S.fromList $ filter even [(1::Int)..10]) . t
607 prop (desc <> " stripPrefix 10") $ eliminateOp constr (stripPrefix [1..10]) $
608 (\s -> s >>= maybe (return Nothing) (fmap Just . S.toList)) .
609 S.stripPrefix (S.fromList [(1::Int)..10]) . t
611-- head/tail/last may depend on the order in case of parallel streams
612-- so we test these only for serial streams.
613eliminationOpsOrdered
614 :: ([Int] -> t IO Int)
615 -> String
616 -> (t IO Int -> SerialT IO Int)
617 -> Spec
618eliminationOpsOrdered constr desc t = do
619 prop (desc <> " head") $ eliminateOp constr (wrapMaybe head) $ S.head . t
620 prop (desc <> " tail") $ eliminateOp constr (wrapMaybe tail) $ \x -> do
621 r <- S.tail (t x)
622 case r of
623 Nothing -> return Nothing
624 Just s -> Just <$> S.toList s
625 prop (desc <> " last") $ eliminateOp constr (wrapMaybe last) $ S.last . t
626 prop (desc <> " init") $ eliminateOp constr (wrapMaybe init) $ \x -> do
627 r <- S.init (t x)
628 case r of
629 Nothing -> return Nothing
630 Just s -> Just <$> S.toList s
632elemOp
633 :: ([Word8] -> t IO Word8)
634 -> (t IO Word8 -> SerialT IO Word8)
635 -> (Word8 -> SerialT IO Word8 -> IO Bool)
636 -> (Word8 -> [Word8] -> Bool)
637 -> (Word8, [Word8])
638 -> Property
639elemOp constr op streamOp listOp (x, xs) =
640 monadicIO $ do
641 stream <- run $ (streamOp x . op) (constr xs)
642 let list = listOp x xs
643 equals (==) stream list
645eliminationOpsWord8
646 :: ([Word8] -> t IO Word8)
647 -> String
648 -> (t IO Word8 -> SerialT IO Word8)
649 -> Spec
650eliminationOpsWord8 constr desc t = do
651 prop (desc <> " elem") $ elemOp constr t S.elem elem
652 prop (desc <> " notElem") $ elemOp constr t S.notElem notElem
654-------------------------------------------------------------------------------
655-- Semigroup operations
656-------------------------------------------------------------------------------
658transformFromList
659 :: (Eq b, Show b) =>
660 ([a] -> t IO a)
661 -> ([b] -> [b] -> Bool)
662 -> ([a] -> [b])
663 -> (t IO a -> SerialT IO b)
664 -> [a]
665 -> Property
666transformFromList constr eq listOp op a =
667 monadicIO $ do
668 stream <- run ((S.toList . op) (constr a))
669 let list = listOp a
670 listEquals eq stream list
672foldFromList
673 :: ([Int] -> t IO Int)
674 -> (t IO Int -> SerialT IO Int)
675 -> ([Int] -> [Int] -> Bool)
676 -> [Int]
677 -> Property
678foldFromList constr op eq = transformFromList constr eq id op
680-- XXX concatenate streams of multiple elements rather than single elements
681semigroupOps
682 :: (IsStream t
684#if __GLASGOW_HASKELL__ < 804
685 , Semigroup (t IO Int)
686#endif
687 , Monoid (t IO Int))
688 => String
689 -> ([Int] -> [Int] -> Bool)
690 -> (t IO Int -> SerialT IO Int)
691 -> Spec
692semigroupOps desc eq t = do
693 prop (desc <> " <>") $ foldFromList (foldMapWith (<>) singleton) t eq
694 prop (desc <> " mappend") $ foldFromList (foldMapWith mappend singleton) t eq
696-------------------------------------------------------------------------------
697-- Functor operations
698-------------------------------------------------------------------------------
700functorOps
701 :: Functor (t IO)
702 => ([Int] -> t IO Int)
703 -> String
704 -> ([Int] -> [Int] -> Bool)
705 -> (t IO Int -> SerialT IO Int)
706 -> Spec
707functorOps constr desc eq t = do
708 prop (desc <> " id") $ transformFromList constr eq id t
709 prop (desc <> " fmap (+1)") $ transformFromList constr eq (fmap (+1)) $ t . fmap (+1)
711-------------------------------------------------------------------------------
712-- Applicative operations
713-------------------------------------------------------------------------------
715applicativeOps
716 :: Applicative (t IO)
717 => ([Int] -> t IO Int)
718 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
719 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
720 -> ([Int], [Int])
721 -> Property
722applicativeOps constr eq t (a, b) = withMaxSuccess maxTestCount $
723 monadicIO $ do
724 stream <- run ((S.toList . t) ((,) <$> constr a <*> constr b))
725 let list = (,) <$> a <*> b
726 listEquals eq stream list
728-------------------------------------------------------------------------------
729-- Zip operations
730-------------------------------------------------------------------------------
732zipApplicative
733 :: (IsStream t, Applicative (t IO))
734 => ([Int] -> t IO Int)
735 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
736 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
737 -> ([Int], [Int])
738 -> Property
739zipApplicative constr eq t (a, b) = withMaxSuccess maxTestCount $
740 monadicIO $ do
741 stream1 <- run ((S.toList . t) ((,) <$> constr a <*> constr b))
742 stream2 <- run ((S.toList . t) (pure (,) <*> constr a <*> constr b))
743 stream3 <- run ((S.toList . t) (S.zipWith (,) (constr a) (constr b)))
744 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
745 listEquals eq stream1 list
746 listEquals eq stream2 list
747 listEquals eq stream3 list
749zipMonadic
750 :: IsStream t
751 => ([Int] -> t IO Int)
752 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
753 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
754 -> ([Int], [Int])
755 -> Property
756zipMonadic constr eq t (a, b) = withMaxSuccess maxTestCount $
757 monadicIO $ do
758 stream1 <-
759 run
760 ((S.toList . t)
761 (S.zipWithM (curry return) (constr a) (constr b)))
762 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
763 listEquals eq stream1 list
765zipAsyncMonadic
766 :: IsStream t
767 => ([Int] -> t IO Int)
768 -> ([(Int, Int)] -> [(Int, Int)] -> Bool)
769 -> (t IO (Int, Int) -> SerialT IO (Int, Int))
770 -> ([Int], [Int])
771 -> Property
772zipAsyncMonadic constr eq t (a, b) = withMaxSuccess maxTestCount $
773 monadicIO $ do
774 stream1 <-
775 run
776 ((S.toList . t)
777 (S.zipWithM (curry return) (constr a) (constr b)))
778 stream2 <-
779 run
780 ((S.toList . t)
781 (S.zipAsyncWithM (curry return) (constr a) (constr b)))
782 let list = getZipList $ (,) <$> ZipList a <*> ZipList b
783 listEquals eq stream1 list
784 listEquals eq stream2 list
786-------------------------------------------------------------------------------
787-- Monad operations
788-------------------------------------------------------------------------------
790monadThen
791 :: Monad (t IO)
792 => ([Int] -> t IO Int)
793 -> ([Int] -> [Int] -> Bool)
794 -> (t IO Int -> SerialT IO Int)
795 -> ([Int], [Int])
796 -> Property
797monadThen constr eq t (a, b) = withMaxSuccess maxTestCount $ monadicIO $ do
798 stream <- run ((S.toList . t) (constr a >> constr b))
799 let list = a >> b
800 listEquals eq stream list
802monadBind
803 :: Monad (t IO)
804 => ([Int] -> t IO Int)
805 -> ([Int] -> [Int] -> Bool)
806 -> (t IO Int -> SerialT IO Int)
807 -> ([Int], [Int])
808 -> Property
809monadBind constr eq t (a, b) = withMaxSuccess maxTestCount $
810 monadicIO $ do
811 stream <-
812 run
813 ((S.toList . t)
814 (constr a >>= \x -> (+ x) <$> constr b))
815 let list = a >>= \x -> (+ x) <$> b
816 listEquals eq stream list
818main :: IO ()
819main = hspec
820 $ H.parallel
821#ifdef COVERAGE_BUILD
822 $ modifyMaxSuccess (const 10)
823#endif
824 $ do
825 let folded :: IsStream t => [a] -> t IO a
826 folded = serially . (\xs ->
827 case xs of
828 [x] -> return x -- singleton stream case
829 _ -> foldMapWith (<>) return xs
830 )
832 let makeOps t =
833 [ ("default", t)
834#ifndef COVERAGE_BUILD
835 , ("rate AvgRate 10000", t . avgRate 10000)
836 , ("rate Nothing", t . rate Nothing)
837 , ("maxBuffer 0", t . maxBuffer 0)
838 , ("maxBuffer 1", t . maxBuffer 1)
839 , ("maxThreads 0", t . maxThreads 0)
840 , ("maxThreads 1", t . maxThreads 1)
841 , ("maxThreads -1", t . maxThreads (-1))
842#endif
843 ]
845 let mapOps spec = mapM_ (\(desc, f) -> describe desc $ spec f)
846 let serialOps :: IsStream t => ((SerialT IO a -> t IO a) -> Spec) -> Spec
847 serialOps spec = mapOps spec $ makeOps serially
848#ifndef COVERAGE_BUILD
849 <> [("rate AvgRate 0.00000001", serially . avgRate 0.00000001)]
850 <> [("maxBuffer -1", serially . maxBuffer (-1))]
851#endif
852 let wSerialOps :: IsStream t => ((WSerialT IO a -> t IO a) -> Spec) -> Spec
853 wSerialOps spec = mapOps spec $ makeOps wSerially
854#ifndef COVERAGE_BUILD
855 <> [("rate AvgRate 0.00000001", wSerially . avgRate 0.00000001)]
856 <> [("maxBuffer (-1)", wSerially . maxBuffer (-1))]
857#endif
858 let asyncOps :: IsStream t => ((AsyncT IO a -> t IO a) -> Spec) -> Spec
859 asyncOps spec = mapOps spec $ makeOps asyncly
860#ifndef COVERAGE_BUILD
861 <> [("maxBuffer (-1)", asyncly . maxBuffer (-1))]
862#endif
863 let wAsyncOps :: IsStream t => ((WAsyncT IO a -> t IO a) -> Spec) -> Spec
864 wAsyncOps spec = mapOps spec $ makeOps wAsyncly
865#ifndef COVERAGE_BUILD
866 <> [("maxBuffer (-1)", wAsyncly . maxBuffer (-1))]
867#endif
868 let aheadOps :: IsStream t => ((AheadT IO a -> t IO a) -> Spec) -> Spec
869 aheadOps spec = mapOps spec $ makeOps aheadly
870#ifndef COVERAGE_BUILD
871 <> [("maxBuffer (-1)", aheadly . maxBuffer (-1))]
872#endif
873 let parallelOps :: IsStream t => ((ParallelT IO a -> t IO a) -> Spec) -> Spec
874 parallelOps spec = mapOps spec $ makeOps parallely
875#ifndef COVERAGE_BUILD
876 <> [("rate AvgRate 0.00000001", parallely . avgRate 0.00000001)]
877 <> [("maxBuffer (-1)", parallely . maxBuffer (-1))]
878#endif
879 let zipSerialOps :: IsStream t => ((ZipSerialM IO a -> t IO a) -> Spec) -> Spec
880 zipSerialOps spec = mapOps spec $ makeOps zipSerially
881#ifndef COVERAGE_BUILD
882 <> [("rate AvgRate 0.00000001", zipSerially . avgRate 0.00000001)]
883 <> [("maxBuffer (-1)", zipSerially . maxBuffer (-1))]
884#endif
885 -- Note, the "pure" of applicative Zip streams generates and infinite
886 -- stream and therefore maxBuffer (-1) must not be used for that case.
887 let zipAsyncOps :: IsStream t => ((ZipAsyncM IO a -> t IO a) -> Spec) -> Spec
888 zipAsyncOps spec = mapOps spec $ makeOps zipAsyncly
890 describe "Construction" $ do
891 serialOps $ prop "serially replicate" . constructWithReplicate
893 serialOps $ prop "serially replicateM" . constructWithReplicateM
894 wSerialOps $ prop "wSerially replicateM" . constructWithReplicateM
895 aheadOps $ prop "aheadly replicateM" . constructWithReplicateM
896 asyncOps $ prop "asyncly replicateM" . constructWithReplicateM
897 wAsyncOps $ prop "wAsyncly replicateM" . constructWithReplicateM
898 parallelOps $ prop "parallely replicateM" . constructWithReplicateM
900 serialOps $ prop "serially intFromThenTo" .
901 constructWithIntFromThenTo
902#if __GLASGOW_HASKELL__ >= 806
903 serialOps $ prop "serially DoubleFromThenTo" .
904 constructWithDoubleFromThenTo
905#endif
906 -- XXX test for all types of streams
907 constructWithIterate serially
908 -- XXX add tests for fromIndices
910 describe "Functor operations" $ do
911 serialOps $ functorOps S.fromFoldable "serially" (==)
912 serialOps $ functorOps folded "serially folded" (==)
913 wSerialOps $ functorOps S.fromFoldable "wSerially" (==)
914 wSerialOps $ functorOps folded "wSerially folded" (==)
915 aheadOps $ functorOps S.fromFoldable "aheadly" (==)
916 aheadOps $ functorOps folded "aheadly folded" (==)
917 asyncOps $ functorOps S.fromFoldable "asyncly" sortEq
918 asyncOps $ functorOps folded "asyncly folded" sortEq
919 wAsyncOps $ functorOps S.fromFoldable "wAsyncly" sortEq
920 wAsyncOps $ functorOps folded "wAsyncly folded" sortEq
921 parallelOps $ functorOps S.fromFoldable "parallely" sortEq
922 parallelOps $ functorOps folded "parallely folded" sortEq
923 zipSerialOps $ functorOps S.fromFoldable "zipSerially" (==)
924 zipSerialOps $ functorOps folded "zipSerially folded" (==)
925 zipAsyncOps $ functorOps S.fromFoldable "zipAsyncly" (==)
926 zipAsyncOps $ functorOps folded "zipAsyncly folded" (==)
928 describe "Semigroup operations" $ do
929 serialOps $ semigroupOps "serially" (==)
930 wSerialOps $ semigroupOps "wSerially" (==)
931 aheadOps $ semigroupOps "aheadly" (==)
932 asyncOps $ semigroupOps "asyncly" sortEq
933 wAsyncOps $ semigroupOps "wAsyncly" sortEq
934 parallelOps $ semigroupOps "parallely" sortEq
935 zipSerialOps $ semigroupOps "zipSerially" (==)
936 zipAsyncOps $ semigroupOps "zipAsyncly" (==)
938 describe "Applicative operations" $ do
939 -- The tests using sorted equality are weaker tests
940 -- We need to have stronger unit tests for all those
941 -- XXX applicative with three arguments
942 serialOps $ prop "serially applicative" . applicativeOps S.fromFoldable (==)
943 serialOps $ prop "serially applicative folded" . applicativeOps folded (==)
944 wSerialOps $ prop "wSerially applicative" . applicativeOps S.fromFoldable sortEq
945 wSerialOps $ prop "wSerially applicative folded" . applicativeOps folded sortEq
946 aheadOps $ prop "aheadly applicative" . applicativeOps S.fromFoldable (==)
947 aheadOps $ prop "aheadly applicative folded" . applicativeOps folded (==)
948 asyncOps $ prop "asyncly applicative" . applicativeOps S.fromFoldable sortEq
949 asyncOps $ prop "asyncly applicative folded" . applicativeOps folded sortEq
950 wAsyncOps $ prop "wAsyncly applicative" . applicativeOps S.fromFoldable sortEq
951 wAsyncOps $ prop "wAsyncly applicative folded" . applicativeOps folded sortEq
952 parallelOps $ prop "parallely applicative folded" . applicativeOps folded sortEq
954 -- XXX add tests for indexed/indexedR
955 describe "Zip operations" $ do
956 zipSerialOps $ prop "zipSerially applicative" . zipApplicative S.fromFoldable (==)
957 zipSerialOps $ prop "zipSerially applicative folded" . zipApplicative folded (==)
958 zipAsyncOps $ prop "zipAsyncly applicative" . zipApplicative S.fromFoldable (==)
959 zipAsyncOps $ prop "zipAsyncly applicative folded" . zipApplicative folded (==)
961 -- We test only the serial zip with serial streams and the parallel
962 -- stream, because the rate setting in these streams can slow down
963 -- zipAsync.
964 serialOps $ prop "zip monadic serially" . zipMonadic S.fromFoldable (==)
965 serialOps $ prop "zip monadic serially folded" . zipMonadic folded (==)
966 wSerialOps $ prop "zip monadic wSerially" . zipMonadic S.fromFoldable (==)
967 wSerialOps $ prop "zip monadic wSerially folded" . zipMonadic folded (==)
968 aheadOps $ prop "zip monadic aheadly" . zipAsyncMonadic S.fromFoldable (==)
969 aheadOps $ prop "zip monadic aheadly folded" . zipAsyncMonadic folded (==)
970 asyncOps $ prop "zip monadic asyncly" . zipAsyncMonadic S.fromFoldable (==)
971 asyncOps $ prop "zip monadic asyncly folded" . zipAsyncMonadic folded (==)
972 wAsyncOps $ prop "zip monadic wAsyncly" . zipAsyncMonadic S.fromFoldable (==)
973 wAsyncOps $ prop "zip monadic wAsyncly folded" . zipAsyncMonadic folded (==)
974 parallelOps $ prop "zip monadic parallely" . zipMonadic S.fromFoldable (==)
975 parallelOps $ prop "zip monadic parallely folded" . zipMonadic folded (==)
977 -- XXX add merge tests like zip tests
978 -- for mergeBy, we can split a list randomly into two lists and
979 -- then merge them, it should result in original list
980 -- describe "Merge operations" $ do
982 describe "Monad operations" $ do
983 serialOps $ prop "serially monad then" . monadThen S.fromFoldable (==)
984 wSerialOps $ prop "wSerially monad then" . monadThen S.fromFoldable sortEq
985 aheadOps $ prop "aheadly monad then" . monadThen S.fromFoldable (==)
986 asyncOps $ prop "asyncly monad then" . monadThen S.fromFoldable sortEq
987 wAsyncOps $ prop "wAsyncly monad then" . monadThen S.fromFoldable sortEq
988 parallelOps $ prop "parallely monad then" . monadThen S.fromFoldable sortEq
990 serialOps $ prop "serially monad then folded" . monadThen folded (==)
991 wSerialOps $ prop "wSerially monad then folded" . monadThen folded sortEq
992 aheadOps $ prop "aheadly monad then folded" . monadThen folded (==)
993 asyncOps $ prop "asyncly monad then folded" . monadThen folded sortEq
994 wAsyncOps $ prop "wAsyncly monad then folded" . monadThen folded sortEq
995 parallelOps $ prop "parallely monad then folded" . monadThen folded sortEq
997 serialOps $ prop "serially monad bind" . monadBind S.fromFoldable (==)
998 wSerialOps $ prop "wSerially monad bind" . monadBind S.fromFoldable sortEq
999 aheadOps $ prop "aheadly monad bind" . monadBind S.fromFoldable (==)
1000 asyncOps $ prop "asyncly monad bind" . monadBind S.fromFoldable sortEq
1001 wAsyncOps $ prop "wAsyncly monad bind" . monadBind S.fromFoldable sortEq
1002 parallelOps $ prop "parallely monad bind" . monadBind S.fromFoldable sortEq
1004 serialOps $ prop "serially monad bind folded" . monadBind folded (==)
1005 wSerialOps $ prop "wSerially monad bind folded" . monadBind folded sortEq
1006 aheadOps $ prop "aheadly monad bind folded" . monadBind folded (==)
1007 asyncOps $ prop "asyncly monad bind folded" . monadBind folded sortEq
1008 wAsyncOps $ prop "wAsyncly monad bind folded" . monadBind folded sortEq
1009 parallelOps $ prop "parallely monad bind folded" . monadBind folded sortEq
1011 -- These tests won't work with maxBuffer or maxThreads set to 1, so we
1012 -- exclude those cases from these.
1013 let mkOps t =
1014 [ ("default", t)
1015#ifndef COVERAGE_BUILD
1016 , ("rate Nothing", t . rate Nothing)
1017 , ("maxBuffer 0", t . maxBuffer 0)
1018 , ("maxThreads 0", t . maxThreads 0)
1019 , ("maxThreads 0", t . maxThreads (-1))
1020#endif
1023 let forOps ops spec = forM_ ops (\(desc, f) -> describe desc $ spec f)
1024 describe "Stream concurrent operations" $ do
1025 forOps (mkOps aheadly) $ concurrentOps S.fromFoldable "aheadly" (==)
1026 forOps (mkOps asyncly) $ concurrentOps S.fromFoldable "asyncly" sortEq
1027 forOps (mkOps wAsyncly) $ concurrentOps S.fromFoldable "wAsyncly" sortEq
1028 forOps (mkOps parallely) $ concurrentOps S.fromFoldable "parallely" sortEq
1030 forOps (mkOps aheadly) $ concurrentOps folded "aheadly folded" (==)
1031 forOps (mkOps asyncly) $ concurrentOps folded "asyncly folded" sortEq
1032 forOps (mkOps wAsyncly) $ concurrentOps folded "wAsyncly folded" sortEq
1033 forOps (mkOps parallely) $ concurrentOps folded "parallely folded" sortEq
1035 describe "Concurrent application" $ do
1036 serialOps $ prop "serial" . concurrentApplication (==)
1037 asyncOps $ prop "async" . concurrentApplication sortEq
1038 aheadOps $ prop "ahead" . concurrentApplication (==)
1039 parallelOps $ prop "parallel" . concurrentApplication sortEq
1041 prop "concurrent foldr application" $ withMaxSuccess maxTestCount
1042 concurrentFoldrApplication
1043 prop "concurrent foldl application" $ withMaxSuccess maxTestCount
1044 concurrentFoldlApplication
1046 describe "Stream transform and combine operations" $ do
1047 serialOps $ transformCombineOpsCommon S.fromFoldable "serially" (==)
1048 wSerialOps $ transformCombineOpsCommon S.fromFoldable "wSerially" sortEq
1049 aheadOps $ transformCombineOpsCommon S.fromFoldable "aheadly" (==)
1050 asyncOps $ transformCombineOpsCommon S.fromFoldable "asyncly" sortEq
1051 wAsyncOps $ transformCombineOpsCommon S.fromFoldable "wAsyncly" sortEq
1052 parallelOps $ transformCombineOpsCommon S.fromFoldable "parallely" sortEq
1053 zipSerialOps $ transformCombineOpsCommon S.fromFoldable "zipSerially" (==)
1054 zipAsyncOps $ transformCombineOpsCommon S.fromFoldable "zipAsyncly" (==)
1056 serialOps $ transformCombineOpsCommon folded "serially" (==)
1057 wSerialOps $ transformCombineOpsCommon folded "wSerially" sortEq
1058 aheadOps $ transformCombineOpsCommon folded "aheadly" (==)
1059 asyncOps $ transformCombineOpsCommon folded "asyncly" sortEq
1060 wAsyncOps $ transformCombineOpsCommon folded "wAsyncly" sortEq
1061 parallelOps $ transformCombineOpsCommon folded "parallely" sortEq
1062 zipSerialOps $ transformCombineOpsCommon folded "zipSerially" (==)
1063 zipAsyncOps $ transformCombineOpsCommon folded "zipAsyncly" (==)
1065 serialOps $ transformCombineOpsOrdered S.fromFoldable "serially" (==)
1066 aheadOps $ transformCombineOpsOrdered S.fromFoldable "aheadly" (==)
1067 zipSerialOps $ transformCombineOpsOrdered S.fromFoldable "zipSerially" (==)
1068 zipAsyncOps $ transformCombineOpsOrdered S.fromFoldable "zipAsyncly" (==)
1070 serialOps $ transformCombineOpsOrdered folded "serially" (==)
1071 aheadOps $ transformCombineOpsOrdered folded "aheadly" (==)
1072 zipSerialOps $ transformCombineOpsOrdered folded "zipSerially" (==)
1073 zipAsyncOps $ transformCombineOpsOrdered folded "zipAsyncly" (==)
1075 describe "Stream elimination operations" $ do
1076 serialOps $ eliminationOps S.fromFoldable "serially"
1077 wSerialOps $ eliminationOps S.fromFoldable "wSerially"
1078 aheadOps $ eliminationOps S.fromFoldable "aheadly"
1079 asyncOps $ eliminationOps S.fromFoldable "asyncly"
1080 wAsyncOps $ eliminationOps S.fromFoldable "wAsyncly"
1081 parallelOps $ eliminationOps S.fromFoldable "parallely"
1082 zipSerialOps $ eliminationOps S.fromFoldable "zipSerially"
1083 zipAsyncOps $ eliminationOps S.fromFoldable "zipAsyncly"
1085 serialOps $ eliminationOps folded "serially folded"
1086 wSerialOps $ eliminationOps folded "wSerially folded"
1087 aheadOps $ eliminationOps folded "aheadly folded"
1088 asyncOps $ eliminationOps folded "asyncly folded"
1089 wAsyncOps $ eliminationOps folded "wAsyncly folded"
1090 parallelOps $ eliminationOps folded "parallely folded"
1091 zipSerialOps $ eliminationOps folded "zipSerially folded"
1092 zipAsyncOps $ eliminationOps folded "zipAsyncly folded"
1094 serialOps $ eliminationOpsWord8 S.fromFoldable "serially"
1095 wSerialOps $ eliminationOpsWord8 S.fromFoldable "wSerially"
1096 aheadOps $ eliminationOpsWord8 S.fromFoldable "aheadly"
1097 asyncOps $ eliminationOpsWord8 S.fromFoldable "asyncly"
1098 wAsyncOps $ eliminationOpsWord8 S.fromFoldable "wAsyncly"
1099 parallelOps $ eliminationOpsWord8 S.fromFoldable "parallely"
1100 zipSerialOps $ eliminationOpsWord8 S.fromFoldable "zipSerially"
1101 zipAsyncOps $ eliminationOpsWord8 S.fromFoldable "zipAsyncly"
1103 serialOps $ eliminationOpsWord8 folded "serially folded"
1104 wSerialOps $ eliminationOpsWord8 folded "wSerially folded"
1105 aheadOps $ eliminationOpsWord8 folded "aheadly folded"
1106 asyncOps $ eliminationOpsWord8 folded "asyncly folded"
1107 wAsyncOps $ eliminationOpsWord8 folded "wAsyncly folded"
1108 parallelOps $ eliminationOpsWord8 folded "parallely folded"
1109 zipSerialOps $ eliminationOpsWord8 folded "zipSerially folded"
1110 zipAsyncOps $ eliminationOpsWord8 folded "zipAsyncly folded"
1112 -- XXX Add a test where we chain all transformation APIs and make sure that
1113 -- the state is being passed through all of them.
1114 describe "Stream serial elimination operations" $ do
1115 serialOps $ eliminationOpsOrdered S.fromFoldable "serially"
1116 wSerialOps $ eliminationOpsOrdered S.fromFoldable "wSerially"
1117 aheadOps $ eliminationOpsOrdered S.fromFoldable "aheadly"
1118 zipSerialOps $ eliminationOpsOrdered S.fromFoldable "zipSerially"
1119 zipAsyncOps $ eliminationOpsOrdered S.fromFoldable "zipAsyncly"
1121 serialOps $ eliminationOpsOrdered folded "serially folded"
1122 wSerialOps $ eliminationOpsOrdered folded "wSerially folded"
1123 aheadOps $ eliminationOpsOrdered folded "aheadly folded"
1124 zipSerialOps $ eliminationOpsOrdered folded "zipSerially folded"
1125 zipAsyncOps $ eliminationOpsOrdered folded "zipAsyncly folded"