@@ -9,7 +9,13 @@
10module Streamly.Test.Prelude.Serial where
10module Streamly.Test.Prelude.Serial where
12+import Control.Concurrent ( threadDelay )
13+import Control.Monad ( when )
14+import Data.Function ( (&) )
15+import Data.IORef ( newIORef, readIORef, writeIORef )
16+import Data.Int (Int64)
12import Data.List (intercalate)
17import Data.List (intercalate)
18+import Data.Maybe ( isJust, fromJust )
13#if __GLASGOW_HASKELL__ < 808
19#if __GLASGOW_HASKELL__ < 808
14import Data.Semigroup ((<>))
20import Data.Semigroup ((<>))
@@ -26,13 +32,18 @@ import Test.QuickCheck
26 , vectorOf
32 , vectorOf
27 , withMaxSuccess
33 , withMaxSuccess
29−import Test.QuickCheck.Monadic (assert, monadicIO, run)
35+import Test.QuickCheck.Monadic (assert, monadicIO, pick, run)
30import Test.Hspec as H
36import Test.Hspec as H
32import Streamly.Prelude
38import Streamly.Prelude
33 ( SerialT, IsStream, avgRate, maxBuffer, serial, serially)
39 ( SerialT, IsStream, avgRate, maxBuffer, serial, serially)
34import qualified Streamly.Prelude as S
40import qualified Streamly.Prelude as S
35import qualified Streamly.Data.Fold as FL
41import qualified Streamly.Data.Fold as FL
42+import qualified Streamly.Internal.Data.Unfold as UF
43+import qualified Streamly.Internal.Data.Stream.IsStream as IS
44+import Streamly.Internal.Data.Time.Units
45+ (AbsTime, NanoSecond64(..), toRelTime64, diffAbsTime64)
46+import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
37import Streamly.Test.Common
48import Streamly.Test.Common
38import Streamly.Test.Prelude.Common
49import Streamly.Test.Prelude.Common
@@ -163,6 +174,95 @@ associativityCheck desc t = prop desc assocCheckProp
163 assocStream <- run $ S.toList $ t $ xStream <> yStream <> zStream
174 assocStream <- run $ S.toList $ t $ xStream <> yStream <> zStream
164 listEquals (==) infixAssocstream assocStream
175 listEquals (==) infixAssocstream assocStream
181+tenPow8 = 10^(8 :: Int)
184+tenPow7 = 10^(7 :: Int)
186+takeDropTime :: NanoSecond64
187+takeDropTime = NanoSecond64 $ 5 * tenPow8
189+checkTakeDropTime :: (Maybe AbsTime, Maybe AbsTime) -> IO Bool
190+checkTakeDropTime (mt0, mt1) = do
191+ let graceTime = NanoSecond64 $ 8 * tenPow7
193+ Nothing -> return True
196+ Nothing -> return True
198+ let tMax = toRelTime64 (takeDropTime + graceTime)
199+ let tMin = toRelTime64 (takeDropTime - graceTime)
200+ let t = diffAbsTime64 t1 t0
201+ let r = t >= tMin && t <= tMax
202+ when (not r) $ putStrLn $
204+ " tMin = " ++ show tMin ++
205+ " tMax = " ++ show tMax
208+testTakeByTime :: IO Bool
211+ S.fold ((,) <$> FL.head <*> FL.last)
212+ $ IS.takeByTime takeDropTime
213+ $ S.repeatM (threadDelay 1000 >> getTime Monotonic)
216+testDropByTime :: IO Bool
218+ t0 <- getTime Monotonic
221+ $ IS.dropByTime takeDropTime
222+ $ S.repeatM (threadDelay 1000 >> getTime Monotonic)
223+ checkTakeDropTime (Just t0, mt1)
226+unfold = monadicIO $ do
227+ a <- pick $ choose (0, max_length `div` 2)
228+ b <- pick $ choose (0, max_length)
229+ let unf = UF.enumerateFromToIntegral b
230+ ls <- S.toList $ S.unfold unf a
231+ return $ ls == [a..b]
234+unfold0 = monadicIO $ do
235+ a <- pick $ choose (0, max_length `div` 2)
236+ b <- pick $ choose (0, max_length)
237+ let unf = UF.supply (UF.enumerateFromToIntegral b) a
238+ ls <- S.toList $ IS.unfold0 unf
239+ return $ ls == [a..b]
241+testFromCallback :: IO Int
242+testFromCallback = do
243+ ref <- newIORef Nothing
244+ let stream = S.map Just (IS.fromCallback (setCallback ref))
245+ `S.parallel` runCallback ref
246+ S.sum $ S.map fromJust $ S.takeWhile isJust stream
250+ setCallback ref cb = do
251+ writeIORef ref (Just cb)
253+ runCallback ref = S.yieldM $ do
255+ S.repeatM (readIORef ref)
261+ & IS.delayPost 0.001
262+ & S.mapM_ (fromJust cb)
166main :: IO ()
266main :: IO ()
167main = hspec
267main = hspec
168 $ H.parallel
268 $ H.parallel
@@ -209,6 +309,10 @@ main = hspec
209 serialOps $ prop "serially fromIndices" . constructWithFromIndices
309 serialOps $ prop "serially fromIndices" . constructWithFromIndices
210 serialOps $ prop "serially fromIndicesM" . constructWithFromIndicesM
310 serialOps $ prop "serially fromIndicesM" . constructWithFromIndicesM
312+ describe "From Generators" $ do
313+ prop "unfold" unfold
314+ prop "unfold0" unfold0
212 describe "Functor operations" $ do
316 describe "Functor operations" $ do
213 serialOps $ functorOps S.fromFoldable "serially" (==)
317 serialOps $ functorOps S.fromFoldable "serially" (==)
214 serialOps $ functorOps folded "serially folded" (==)
318 serialOps $ functorOps folded "serially folded" (==)
@@ -269,6 +373,10 @@ main = hspec
269 serialOps $ transformCombineOpsOrdered S.fromFoldable "serially" (==)
373 serialOps $ transformCombineOpsOrdered S.fromFoldable "serially" (==)
270 serialOps $ transformCombineOpsOrdered folded "serially" (==)
374 serialOps $ transformCombineOpsOrdered folded "serially" (==)
376+ describe "Filtering" $ do
377+ it "takeByTime" (testTakeByTime `shouldReturn` True)
378+ it "dropByTime" (testDropByTime `shouldReturn` True)
272 describe "Stream group and split operations" $ do
380 describe "Stream group and split operations" $ do
273 groupSplitOps "serially"
381 groupSplitOps "serially"
@@ -289,3 +397,5 @@ main = hspec
289 prop "testGroupsBySep" testGroupsBySep
397 prop "testGroupsBySep" testGroupsBySep
291 describe "Composed MonadThrow serially" $ composeWithMonadThrow serially
399 describe "Composed MonadThrow serially" $ composeWithMonadThrow serially
401+ it "fromCallback" $ testFromCallback `shouldReturn` (50*101)