@@ -1,19 +1,29 @@
11module Main (main) where
22
3−import qualified Streamly.Prelude as S
43import Streamly.Internal.Data.Fold
4+import qualified Streamly.Prelude as S
5+import qualified Streamly.Data.Fold as FL
56
7+import Test.Hspec as H
68import Test.Hspec.QuickCheck
79import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
810import Test.QuickCheck.Monadic (monadicIO, assert, run)
911
10−import Test.Hspec as H
11−
1212maxStreamLen :: Int
1313maxStreamLen = 1000
1414
15+intMin :: Int
16+intMin = minBound
17+
18+intMax :: Int
19+intMax = maxBound
20+
21+{-# INLINE maxStreamLen #-}
22+{-# INLINE intMin #-}
23+{-# INLINE intMax #-}
24+
1525testRollingHashFirstN :: Property
16−testRollingHashFirstN =
26+testRollingHashFirstN =
1727 forAll (choose (0, maxStreamLen)) $ \len ->
1828 forAll (choose (0, len)) $ \n ->
1929 forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec -> monadicIO $ do
@@ -21,7 +31,175 @@ testRollingHashFirstN =
2131 b <- run $ S.fold (rollingHashFirstN n) $ S.fromList vec
2232 assert $ a == b
2333
34+
35+testHead :: [Int] -> Expectation
36+testHead ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
37+ where
38+ headl [] = Nothing
39+ headl (x:_) = Just x
40+
41+
42+testLength :: [Int] -> Expectation
43+testLength ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
44+
45+
46+testSum :: [Int] -> Expectation
47+testSum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` foldl (+) 0 ls
48+
49+
50+testProduct :: [Int] -> Expectation
51+testProduct ls = S.fold FL.product (S.fromList ls) `shouldReturn` foldl (*) 1 ls
52+
53+
54+lesser :: (a -> a -> Ordering) -> a -> a -> a
55+lesser f x y = if f x y == LT then x else y
56+
57+
58+greater :: (a -> a -> Ordering) -> a -> a -> a
59+greater f x y = if f x y == GT then x else y
60+
61+
62+foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
63+foldMaybe f acc ls = case ls of
64+ [] -> Nothing
65+ _ -> Just (foldl f acc ls)
66+
67+
68+testMaximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
69+testMaximumBy genmin f ls = S.fold (FL.maximumBy f) (S.fromList ls) `shouldReturn` foldMaybe (greater f) genmin ls
70+
71+
72+testMaximum :: (Show a, Ord a) => a -> [a] -> Expectation
73+testMaximum genmin ls = S.fold FL.maximum (S.fromList ls) `shouldReturn` foldMaybe (greater compare) genmin ls
74+
75+
76+testMinimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
77+testMinimumBy genmax f ls = S.fold (FL.minimumBy f) (S.fromList ls) `shouldReturn` foldMaybe (lesser f) genmax ls
78+
79+
80+testMinimum :: (Show a, Ord a) => a -> [a] -> Expectation
81+testMinimum genmax ls = S.fold FL.minimum (S.fromList ls) `shouldReturn` foldMaybe (lesser compare) genmax ls
82+
83+
84+testToList :: [Int] -> Expectation
85+testToList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
86+
87+
88+safeLast :: [a] -> Maybe a
89+safeLast [] = Nothing
90+safeLast (x:[]) = Just x
91+safeLast (_:xs) = safeLast xs
92+
93+
94+testLast :: [String] -> Expectation
95+testLast ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
96+
97+
98+nth :: Int -> [a] -> Maybe a
99+nth idx (x:xs) = if idx == 0
100+ then Just x
101+ else if idx < 0
102+ then Nothing
103+ else nth (idx - 1) xs
104+nth _ [] = Nothing
105+
106+
107+testIndex :: Int -> [String] -> Expectation
108+testIndex idx ls = let
109+ x = S.fold (FL.index idx) (S.fromList ls)
110+ in
111+ x `shouldReturn` (nth idx ls)
112+
113+
114+testFind :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
115+testFind f ls = do
116+ let x = S.fold (FL.findIndex f) (S.fromList ls)
117+ y <- x
118+ case y of
119+ Nothing -> S.fold (FL.find f) (S.fromList ls) `shouldReturn` Nothing
120+ Just idx -> S.fold (FL.any f) (S.fromList $ take idx ls) `shouldReturn` False
121+
122+
123+neg :: (a -> Bool) -> a -> Bool
124+neg f x = if f x == True then False else True
125+
126+testFindIndex :: (a -> Bool) -> [a] -> Expectation
127+testFindIndex f ls = do
128+ let x = S.fold (FL.findIndex f) (S.fromList ls)
129+ y <- x
130+ case y of
131+ Nothing -> S.fold (FL.all $ neg f) (S.fromList ls) `shouldReturn` True
132+ Just idx -> if idx == 0
133+ then S.fold (FL.all f) (S.fromList []) `shouldReturn` True
134+ else S.fold (FL.all f) (S.fromList $ (take idx ls)) `shouldReturn` False
135+
136+predicate :: Int -> Bool
137+predicate x = if x * x < 100 then True else False
138+
139+testElemIndex :: Int -> [Int] -> Expectation
140+testElemIndex elm ls = do
141+ let x = S.fold (FL.elemIndex elm) (S.fromList ls)
142+ y <- x
143+ case y of
144+ Nothing -> S.fold (FL.any (\z -> if z == elm then True else False)) (S.fromList ls) `shouldReturn` False
145+ Just idx -> S.fold (FL.any (\z -> if z == elm then True else False)) (S.fromList $ (take idx ls)) `shouldReturn` False
146+
147+testNull :: [Int] -> Expectation
148+testNull ls = S.fold FL.null (S.fromList ls) `shouldReturn` case ls of
149+ [] -> True
150+ _ -> False
151+testElem :: Int -> [Int] -> Expectation
152+testElem elm ls = do
153+ let x = S.fold (FL.elem elm) (S.fromList ls)
154+ y <- x
155+ S.fold (FL.any (\z -> if z == elm then True else False)) (S.fromList ls) `shouldReturn` y
156+
157+
158+testNotElem :: Int -> [Int] -> Expectation
159+testNotElem elm ls = do
160+ let x = S.fold (FL.notElem elm) (S.fromList ls)
161+ y <- x
162+ S.fold (FL.any (\z -> if z == elm then True else False)) (S.fromList ls) `shouldReturn` (if y == True then False else True)
163+
164+
165+testAll :: (a -> Bool) -> [a] -> Expectation
166+testAll f ls = S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.and (map f ls)
167+
168+
169+testAny :: (a -> Bool) -> [a] -> Expectation
170+testAny f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
171+
172+
173+testAnd :: [Bool] -> Expectation
174+testAnd ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
175+
176+
177+testOr :: [Bool] -> Expectation
178+testOr ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
179+
180+
24181main :: IO ()
25182main = hspec $
26− describe "Rolling Hash Folds" $
183+ describe "Fold Tests" $ do
27184 prop "testRollingHashFirstN" testRollingHashFirstN
185+ prop "testIndex" $ testIndex
186+ prop "testHead" testHead
187+ prop "testLast" testLast
188+ prop "testLength" testLength
189+ prop "testSum" testSum
190+ prop "testProduct" testProduct
191+ prop "testMaximumBy" $ testMaximumBy intMin compare
192+ prop "testMaximum" $ testMaximum intMin
193+ prop "testMinimumBy" $ testMinimumBy intMax compare
194+ prop "testMinimum" $ testMinimum intMax
195+ prop "testToList" testToList
196+ prop "testFind" $ testFind predicate
197+ prop "testFindIndex" $ testFindIndex predicate
198+ prop "testElemIndex" $ testElemIndex 10
199+ prop "testNull" testNull
200+ prop "testElem" $ testElem 10
201+ prop "testNotElem" $ testNotElem 10
202+ prop "testAll" $ testAll predicate
203+ prop "testAny" $ testAny predicate
204+ prop "testAnd" testAnd
205+ prop "testOr" testOr