Skip to content

Commit 07a549c

Browse files
Add a test suite adapted from older Prelude.Fold
1 parent 1ee6c24 commit 07a549c

2 files changed

Lines changed: 158 additions & 0 deletions

File tree

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
{-# OPTIONS_GHC -Wno-deprecations #-}
2+
3+
-- |
4+
-- Module : Streamly.Test.Data.Stream.Fold
5+
-- Copyright : (c) 2020 Composewell Technologies
6+
--
7+
-- License : BSD-3-Clause
8+
-- Maintainer : streamly@composewell.com
9+
-- Stability : experimental
10+
-- Portability : GHC
11+
12+
module Streamly.Test.Data.Stream.Fold (main) where
13+
14+
import Control.Exception (ErrorCall(..), catch)
15+
import Data.IORef (newIORef, readIORef, writeIORef, IORef)
16+
#ifdef COVERAGE_BUILD
17+
import Test.Hspec.QuickCheck (modifyMaxSuccess)
18+
#endif
19+
import Test.Hspec as H
20+
#ifdef DEVBUILD
21+
#endif
22+
23+
import Control.Monad.Trans.Identity (runIdentityT)
24+
import Streamly.Internal.Data.Stream (Stream)
25+
import qualified Streamly.Internal.Data.Stream as Stream
26+
27+
#ifdef DEVBUILD
28+
checkFoldxStrictness :: IO ()
29+
checkFoldxStrictness = do
30+
-- Note: consM is strict which causes the tests to fail
31+
-- This should work with StreamK though.
32+
-- let s = return (1 :: Int) `Stream.consM` error "failure"
33+
let s = Stream.fromList ((1 :: Int) : error "failure")
34+
catch (Stream.foldlx' (\_ a -> if a == 1 then error "success" else "done")
35+
"begin" id s)
36+
(\(ErrorCall err) -> return err)
37+
`shouldReturn` "success"
38+
39+
checkScanxStrictness :: IO ()
40+
checkScanxStrictness = do
41+
let s = Stream.fromList ((1 :: Int) : error "failure")
42+
catch
43+
(Stream.drain (
44+
Stream.scanlx' (\_ a ->
45+
if a == 1
46+
then error "success"
47+
else "done")
48+
"begin" id s
49+
)
50+
>> return "finished"
51+
)
52+
(\(ErrorCall err) -> return err)
53+
`shouldReturn` "success"
54+
55+
foldxMStrictCheck :: IORef Int -> Stream IO Int -> IO ()
56+
foldxMStrictCheck ref = Stream.foldlMx' (\_ _ -> writeIORef ref 1) (return ()) return
57+
58+
#endif
59+
60+
checkFoldMStrictness :: (IORef Int -> Stream IO Int -> IO ()) -> IO ()
61+
checkFoldMStrictness f = do
62+
ref <- newIORef 0
63+
let s = Stream.fromList ((1 :: Int) : error "x")
64+
catch (f ref s) (\(_ :: ErrorCall) -> return ())
65+
readIORef ref `shouldReturn` 1
66+
67+
checkFoldl'Strictness :: IO ()
68+
checkFoldl'Strictness = do
69+
let s = Stream.fromList ((1 :: Int) : error "failure")
70+
catch (Stream.foldl' (\_ a -> if a == 1 then error "success" else "done")
71+
"begin" s)
72+
(\(ErrorCall err) -> return err)
73+
`shouldReturn` "success"
74+
75+
checkScanl'Strictness :: IO ()
76+
checkScanl'Strictness = do
77+
let s = Stream.fromList ((1 :: Int) : error "failure")
78+
catch
79+
(Stream.drain
80+
(Stream.scanl'
81+
(\_ a ->
82+
if a == 1
83+
then error "success"
84+
else "done")
85+
"begin"
86+
s)
87+
>> return "finished"
88+
)
89+
(\(ErrorCall err) -> return err)
90+
`shouldReturn` "success"
91+
92+
foldlM'StrictCheck :: IORef Int -> Stream IO Int -> IO ()
93+
foldlM'StrictCheck ref = Stream.foldlM' (\_ _ -> writeIORef ref 1) (return ())
94+
95+
scanlM'StrictCheck :: IORef Int -> Stream IO Int -> Stream IO ()
96+
scanlM'StrictCheck ref = Stream.scanlM' (\_ _ -> writeIORef ref 1) (return ())
97+
98+
checkScanlMStrictness :: (IORef Int -> Stream IO Int -> Stream IO ()) -> IO ()
99+
checkScanlMStrictness f = do
100+
ref <- newIORef 0
101+
let s = Stream.fromList ((1 :: Int) : error "x")
102+
catch (Stream.drain $ f ref s) (\(_ :: ErrorCall) -> return ())
103+
readIORef ref `shouldReturn` 1
104+
105+
checkFoldrLaziness :: IO ()
106+
checkFoldrLaziness = do
107+
Stream.foldrM (\x xs -> if odd x then return True else xs)
108+
(return False) (Stream.fromList (2:4:5:undefined :: [Int]))
109+
`shouldReturn` True
110+
111+
Stream.toList (Stream.foldrS (\x xs -> if odd x then Stream.fromPure True else xs)
112+
(Stream.fromPure False)
113+
$ (Stream.fromList (2:4:5:undefined) :: Stream IO Int))
114+
`shouldReturn` [True]
115+
116+
runIdentityT (Stream.foldrT (\x xs -> if odd x then return True else xs)
117+
(return False)
118+
$ (Stream.fromList (2:4:5:undefined) :: Stream IO Int))
119+
`shouldReturn` True
120+
121+
moduleName :: String
122+
moduleName = "Prelude.Fold"
123+
124+
main :: IO ()
125+
main = hspec
126+
$ H.parallel
127+
#ifdef COVERAGE_BUILD
128+
$ modifyMaxSuccess (const 10)
129+
#endif
130+
$ describe moduleName $ do
131+
132+
---------------------------------------------------------------------------
133+
-- Left folds are strict enough
134+
---------------------------------------------------------------------------
135+
136+
#ifdef DEVBUILD
137+
it "foldx is strict enough" checkFoldxStrictness
138+
it "scanx is strict enough" checkScanxStrictness
139+
it "foldxM is strict enough" (checkFoldMStrictness foldxMStrictCheck)
140+
#endif
141+
it "foldl' is strict enough" checkFoldl'Strictness
142+
it "scanl' is strict enough" checkScanl'Strictness
143+
it "foldlM' is strict enough" (checkFoldMStrictness foldlM'StrictCheck)
144+
it "scanlM' is strict enough" (checkScanlMStrictness scanlM'StrictCheck)
145+
146+
---------------------------------------------------------------------------
147+
-- Right folds are lazy enough
148+
---------------------------------------------------------------------------
149+
150+
it "foldrM is lazy enough" checkFoldrLaziness

test/streamly-tests.cabal

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,14 @@ test-suite Data.Stream.Exception
402402
main-is: Streamly/Test/Data/Stream/Exception.hs
403403
ghc-options: -main-is Streamly.Test.Data.Stream.Exception.main
404404

405+
test-suite Data.Stream.Fold
406+
import: test-options
407+
type: exitcode-stdio-1.0
408+
main-is: Streamly/Test/Data/Stream/Fold.hs
409+
ghc-options: -main-is Streamly.Test.Data.Stream.Fold.main
410+
if flag(use-streamly-core)
411+
buildable: False
412+
405413
-- Test suite adapted from older Prelude.Serial test
406414
-- Needs to be deduplicated with other Data.Stream.* test suites
407415
test-suite Data.Stream.Serial

0 commit comments

Comments
 (0)