streamly/test/Streamly/Test/Prelude/WAsync.hs

223 lines
8.0 KiB
Haskell

{-# OPTIONS_GHC -Wno-deprecations #-}
-- |
-- Module : Streamly.Test.Prelude.WAsync
-- Copyright : (c) 2020 Composewell Technologies
--
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
module Streamly.Test.Prelude.WAsync (main) where
#ifdef DEVBUILD
import Control.Concurrent ( threadDelay )
#endif
import Data.List (sort)
import Test.Hspec.QuickCheck
import Test.QuickCheck (Property, withMaxSuccess)
import Test.QuickCheck.Monadic (monadicIO, run)
import Test.Hspec as H
import Streamly.Prelude
import qualified Streamly.Prelude as S
import Streamly.Test.Common
import Streamly.Test.Prelude.Common
moduleName :: String
moduleName = "Prelude.WAsync"
constructfromWAsync ::
S.WAsyncT IO Int -> S.WAsyncT IO Int-> [Int] -> Property
constructfromWAsync s1 s2 res =
withMaxSuccess maxTestCount $
monadicIO $ do
x <- run
$ S.toList
$ S.fromWAsync
$ S.maxThreads 1
$ s1 `S.wAsync` s2
equals (==) x res
main :: IO ()
main = hspec
$ H.parallel
#ifdef COVERAGE_BUILD
$ modifyMaxSuccess (const 10)
#endif
$ describe moduleName $ do
let wAsyncOps :: IsStream t => ((WAsyncT IO a -> t IO a) -> Spec) -> Spec
wAsyncOps spec = mapOps spec $ makeOps fromWAsync
#ifndef COVERAGE_BUILD
<> [("maxBuffer (-1)", fromWAsync . maxBuffer (-1))]
#endif
describe "Construction" $ do
wAsyncOps $ prop "wAsyncly replicateM" . constructWithReplicateM
-- XXX add tests for fromIndices
wAsyncOps $ prop "wAsyncly cons" . constructWithCons S.cons
wAsyncOps $ prop "wAsyncly consM" . constructWithConsM S.consM sort
wAsyncOps $ prop "wAsyncly (.:)" . constructWithCons (S..:)
wAsyncOps $ prop "wAsyncly (|:)" . constructWithConsM (S.|:) sort
prop "wAsync1" $
constructfromWAsync
(S.fromList [1,2,3,4,5])
(S.fromList [6,7,8,9,10])
[1,6,2,7,3,8,4,9,5,10]
prop "wAsync2" $
constructfromWAsync
(S.fromList [1,2,3,4,5,6,7])
(S.fromList [8,9,10])
[1,8,2,9,3,10,4,5,6,7]
prop "wAsync3" $
constructfromWAsync
(S.fromList [1,2,3,4])
(S.fromList [5,6,7,8,9,10])
[1,5,2,6,3,7,4,8,9,10]
prop "wAsync4" $
constructfromWAsync
(S.fromList [])
(S.fromList [5,6,7,8,9,10])
[5,6,7,8,9,10]
prop "wAsync5" $
constructfromWAsync
(S.fromList [1,2,3,4])
(S.fromList [])
[1,2,3,4]
prop "wAsync6" $
constructfromWAsync
(S.fromList [])
(S.fromList [])
[]
describe "Functor operations" $ do
wAsyncOps $ functorOps S.fromFoldable "wAsyncly" sortEq
wAsyncOps $ functorOps folded "wAsyncly folded" sortEq
describe "Monoid operations" $ do
wAsyncOps $ monoidOps "wAsyncly" mempty sortEq
describe "WAsync loops" $ loops fromWAsync sort sort
describe "Bind and Monoidal composition combinations" $ do
wAsyncOps $ bindAndComposeSimpleOps "WAsync" sortEq
wAsyncOps $ bindAndComposeHierarchyOps "WAsync"
wAsyncOps $ nestTwoStreams "WAsync" sort sort
wAsyncOps $ nestTwoStreamsApp "WAsync" sort sort
describe "Semigroup operations" $ do
wAsyncOps $ semigroupOps "wAsyncly" sortEq
describe "Applicative operations" $ do
wAsyncOps $ applicativeOps S.fromFoldable "wAsyncly applicative" sortEq
wAsyncOps $ applicativeOps folded "wAsyncly applicative folded" sortEq
-- XXX add tests for indexed/indexedR
describe "Zip operations" $
-- We test only the serial zip with serial streams and the parallel
-- stream, because the rate setting in these streams can slow down
-- zipAsync.
do
wAsyncOps $ prop "zip applicative wAsyncly" . zipAsyncApplicative S.fromFoldable (==)
wAsyncOps $ prop "zip applicative wAsyncly folded" . zipAsyncApplicative folded (==)
wAsyncOps $
prop "zip monadic wAsyncly" . zipAsyncMonadic S.fromFoldable (==)
wAsyncOps $ prop "zip monadic wAsyncly folded" . zipAsyncMonadic folded (==)
-- XXX add merge tests like zip tests
-- for mergeBy, we can split a list randomly into two lists and
-- then merge them, it should result in original list
-- describe "Merge operations" $ do
describe "Monad operations" $ do
wAsyncOps $ prop "wAsyncly monad then" . monadThen S.fromFoldable sortEq
wAsyncOps $ prop "wAsyncly monad then folded" . monadThen folded sortEq
wAsyncOps $ prop "wAsyncly monad bind" . monadBind S.fromFoldable sortEq
wAsyncOps $ prop "wAsyncly monad bind folded" . monadBind folded sortEq
describe "Stream transform and combine operations" $ do
wAsyncOps $ transformCombineOpsCommon S.fromFoldable "wAsyncly" sortEq
wAsyncOps $ transformCombineOpsCommon folded "wAsyncly" sortEq
describe "Stream elimination operations" $ do
wAsyncOps $ eliminationOps S.fromFoldable "wAsyncly"
wAsyncOps $ eliminationOps folded "wAsyncly folded"
wAsyncOps $ eliminationOpsWord8 S.fromFoldable "wAsyncly"
wAsyncOps $ eliminationOpsWord8 folded "wAsyncly folded"
-- describe "WAsync interleaved (<>) ordering check" $
-- interleaveCheck fromWAsync (<>)
-- describe "WAsync interleaved mappend ordering check" $
-- interleaveCheck fromWAsync mappend
-- XXX this keeps failing intermittently, need to investigate
-- describe "WAsync (<>) time order check" $
-- parallelCheck fromWAsync (<>)
-- describe "WAsync mappend time order check" $
-- parallelCheck fromWAsync mappend
describe "Tests for exceptions" $ wAsyncOps $ exceptionOps "wAsyncly"
describe "Composed MonadThrow wAsyncly" $ composeWithMonadThrow fromWAsync
-- Ad-hoc tests
it "takes n from stream of streams" (takeCombined 3 fromWAsync)
#ifdef DEVBUILD
let timed :: (IsStream t, Monad (t IO)) => Int -> t IO Int
timed x = S.fromEffect (threadDelay (x * 100000)) >> return x
-- These are not run fromParallel because the timing gets affected
-- unpredictably when other tests are running on the same machine.
--
-- Also, they fail intermittently due to scheduling delays, so not run on
-- CI machines.
describe "Nested parallel and serial compositions" $ do
let t = timed
p = fromWAsync
s = fromSerial
{-
-- This is not correct, the result can also be [4,4,8,0,8,0,2,2]
-- because of parallelism of [8,0] and [8,0].
it "Nest <|>, <>, <|> (1)" $
let t = timed
in toListSerial (
((t 8 <|> t 4) <> (t 2 <|> t 0))
<|> ((t 8 <|> t 4) <> (t 2 <|> t 0)))
`shouldReturn` ([4,4,8,8,0,0,2,2])
-}
it "Nest <|>, <>, <|> (2)" $
(S.toList . fromWAsync) (
s (p (t 4 <> t 8) <> p (t 1 <> t 2))
<> s (p (t 4 <> t 8) <> p (t 1 <> t 2)))
`shouldReturn` ([4,4,8,8,1,1,2,2])
-- FIXME: These two keep failing intermittently on Mac OS X
-- Need to examine and fix the tests.
{-
it "Nest <|>, <=>, <|> (1)" $
let t = timed
in toListSerial (
((t 8 <|> t 4) <=> (t 2 <|> t 0))
<|> ((t 9 <|> t 4) <=> (t 2 <|> t 0)))
`shouldReturn` ([4,4,0,0,8,2,9,2])
it "Nest <|>, <=>, <|> (2)" $
let t = timed
in toListSerial (
((t 4 <|> t 8) <=> (t 1 <|> t 2))
<|> ((t 4 <|> t 9) <=> (t 1 <|> t 2)))
`shouldReturn` ([4,4,1,1,8,2,9,2])
-}
it "Nest <|>, <|>, <|>" $
(S.toList . fromWAsync) (
((t 4 <> t 8) <> (t 0 <> t 2))
<> ((t 4 <> t 8) <> (t 0 <> t 2)))
`shouldReturn` ([0,0,2,2,4,4,8,8])
#endif