on f0398ee help sign in
502 lines 20 kB history raw
1module Main (main) where
3import qualified Streamly.Internal.Data.Parser as P
4import qualified Streamly.Internal.Prelude as S
5import qualified Streamly.Internal.Data.Fold as FL
7-- import Data.List (partition)
9import Test.Hspec(Spec, hspec, describe)
10import qualified Test.Hspec as H
11import Test.Hspec.QuickCheck
12import Test.QuickCheck (arbitrary, forAll, choose, elements, Property,
13 property, listOf, vectorOf, counterexample, Gen)
15import Test.QuickCheck.Monadic (monadicIO, PropertyM, assert, monitor)
16import Control.Exception (SomeException(..), displayException)
17import Control.Monad.IO.Class (MonadIO(..))
18import Control.Monad (when)
19import Data.List ((\\))
21maxTestCount :: Int
22maxTestCount = 100
24min_value :: Int
25min_value = 0
27mid_value :: Int
28mid_value = 5000
30max_value :: Int
31max_value = 10000
33max_length :: Int
34max_length = 1000
36listEquals :: (Show a, Eq a, MonadIO m)
37 => ([a] -> [a] -> Bool) -> [a] -> [a] -> PropertyM m ()
38listEquals eq parsed_list list = do
39 when (not $ parsed_list `eq` list) $ liftIO $ putStrLn $
40 "parsed list " ++ show parsed_list
41 ++ "\nlist " ++ show list
42 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
43 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
44 when (not $ parsed_list `eq` list) $
45 monitor
46 (counterexample $
47 "parsed list " ++ show parsed_list
48 ++ "\nlist " ++ show list
49 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
50 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
51 )
52 assert (parsed_list `eq` list)
54checkListEqual :: (Show a, Eq a) => [a] -> [a] -> Property
55checkListEqual ls_1 ls_2 = monadicIO (listEquals (==) ls_1 ls_2)
57chooseInt :: (Int, Int) -> Gen Int
58chooseInt = choose
60-- Accumulator Tests
62fromFold :: Property
63fromFold =
64 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
65 case (==) <$> (S.parse (P.fromFold FL.sum) (S.fromList ls)) <*> (S.fold FL.sum (S.fromList ls)) of
66 Right is_equal -> is_equal
67 Left _ -> False
69any :: Property
70any =
71 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
72 case S.parse (P.any (> mid_value)) (S.fromList ls) of
73 Right r -> r == (Prelude.any (> mid_value) ls)
74 Left _ -> False
76all :: Property
77all =
78 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
79 case S.parse (P.all (> mid_value)) (S.fromList ls) of
80 Right r -> r == (Prelude.all (> mid_value) ls)
81 Left _ -> False
83yield :: Property
84yield =
85 forAll (chooseInt (min_value, max_value)) $ \x ->
86 case S.parse (P.yield x) (S.fromList [1 :: Int]) of
87 Right r -> r == x
88 Left _ -> False
90yieldM :: Property
91yieldM =
92 forAll (chooseInt (min_value, max_value)) $ \x ->
93 case S.parse (P.yieldM $ return x) (S.fromList [1 :: Int]) of
94 Right r -> r == x
95 Left _ -> False
97die :: Property
98die =
99 property $
100 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
101 Right _ -> False
102 Left _ -> True
104dieM :: Property
105dieM =
106 property $
107 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
108 Right _ -> False
109 Left _ -> True
111parserFail :: Property
112parserFail =
113 property $
114 case S.parse (fail err) (S.fromList [0 :: Int]) of
115 Right _ -> False
116 Left (SomeException e) -> err == displayException e
117 where
118 err = "Testing MonadFail.fail."
120-- Element Parser Tests
122peekPass :: Property
123peekPass =
124 forAll (chooseInt (1, max_length)) $ \list_length ->
125 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
126 case S.parse P.peek (S.fromList ls) of
127 Right head_value -> case ls of
128 head_ls : _ -> head_value == head_ls
129 _ -> False
130 Left _ -> False
132peekFail :: Property
133peekFail =
134 property (case S.parse P.peek (S.fromList []) of
135 Right _ -> False
136 Left _ -> True)
138eofPass :: Property
139eofPass =
140 property (case S.parse P.eof (S.fromList []) of
141 Right _ -> True
142 Left _ -> False)
144eofFail :: Property
145eofFail =
146 forAll (chooseInt (1, max_length)) $ \list_length ->
147 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
148 case S.parse P.eof (S.fromList ls) of
149 Right _ -> False
150 Left _ -> True
152satisfyPass :: Property
153satisfyPass =
154 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
155 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
156 let
157 ls = first_element : ls_tail
158 predicate = (>= mid_value)
159 in
160 case S.parse (P.satisfy predicate) (S.fromList ls) of
161 Right r -> r == first_element
162 Left _ -> False
164satisfy :: Property
165satisfy =
166 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
167 case S.parse (P.satisfy predicate) (S.fromList ls) of
168 Right r -> case ls of
169 [] -> False
170 (x : _) -> predicate x && (r == x)
171 Left _ -> case ls of
172 [] -> True
173 (x : _) -> not $ predicate x
174 where
175 predicate = (>= mid_value)
177-- Sequence Parsers Tests
179take :: Property
180take =
181 forAll (chooseInt (min_value, max_value)) $ \n ->
182 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
183 case S.parse (P.take n FL.toList) (S.fromList ls) of
184 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
185 Left _ -> property False
187takeEQPass :: Property
188takeEQPass =
189 forAll (chooseInt (min_value, max_value)) $ \n ->
190 forAll (chooseInt (n, max_value)) $ \list_length ->
191 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
192 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
193 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
194 Left _ -> property False
196takeEQ :: Property
197takeEQ =
198 forAll (chooseInt (min_value, max_value)) $ \n ->
199 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
200 let
201 list_length = Prelude.length ls
202 in
203 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
204 Right parsed_list ->
205 if (n <= list_length) then
206 checkListEqual parsed_list (Prelude.take n ls)
207 else
208 property False
209 Left _ -> property (n > list_length)
211takeGEPass :: Property
212takeGEPass =
213 forAll (chooseInt (min_value, max_value)) $ \n ->
214 forAll (chooseInt (n, max_value)) $ \list_length ->
215 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
216 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
217 Right parsed_list -> checkListEqual parsed_list ls
218 Left _ -> property False
220takeGE :: Property
221takeGE =
222 forAll (chooseInt (min_value, max_value)) $ \n ->
223 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
224 let
225 list_length = Prelude.length ls
226 in
227 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
228 Right parsed_list ->
229 if (n <= list_length) then
230 checkListEqual parsed_list ls
231 else
232 property False
233 Left _ -> property (n > list_length)
235nLessThanEqual0 ::
236 ( Int
237 -> FL.Fold (Either SomeException) Int [Int]
238 -> P.Parser (Either SomeException) Int [Int]
239 )
240 -> (Int -> [Int] -> [Int])
241 -> Property
242nLessThanEqual0 tk ltk =
243 forAll (elements [0, (-1)]) $ \n ->
244 forAll (listOf arbitrary) $ \ls ->
245 case S.parse (tk n FL.toList) (S.fromList ls) of
246 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
247 Left _ -> property False
249takeProperties :: Spec
250takeProperties =
251 describe "take combinators when n <= 0/" $ do
252 prop "take n FL.toList = []" $
253 nLessThanEqual0 P.take (\_ -> const [])
254 prop "takeEQ n FL.toList = []" $
255 nLessThanEqual0 P.takeEQ (\_ -> const [])
256 prop "takeGE n FL.toList xs = xs" $
257 nLessThanEqual0 P.takeGE (\_ -> id)
259-- lookAheadPass :: Property
260-- lookAheadPass =
261-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
262-- let
263-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
264-- parseTwice = do
265-- parsed_list_1 <- takeWithoutConsume
266-- parsed_list_2 <- takeWithoutConsume
267-- return (parsed_list_1, parsed_list_2)
268-- in
269-- forAll (chooseInt (n, max_value)) $ \list_length ->
270-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
271-- case S.parse parseTwice (S.fromList ls) of
272-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
273-- Left _ -> property $ False
275-- lookAheadFail :: Property
276-- lookAheadFail =
277-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
278-- let
279-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
280-- parseTwice = do
281-- parsed_list_1 <- takeWithoutConsume
282-- parsed_list_2 <- takeWithoutConsume
283-- return (parsed_list_1, parsed_list_2)
284-- in
285-- forAll (chooseInt (min_value, n - 1)) $ \list_length ->
286-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
287-- case S.parse parseTwice (S.fromList ls) of
288-- Right _ -> False
289-- Left _ -> True
291-- lookAhead :: Property
292-- lookAhead =
293-- forAll (chooseInt (min_value, max_value)) $ \n ->
294-- let
295-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
296-- parseTwice = do
297-- parsed_list_1 <- takeWithoutConsume
298-- parsed_list_2 <- takeWithoutConsume
299-- return (parsed_list_1, parsed_list_2)
300-- in
301-- forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
302-- case S.parse parseTwice (S.fromList ls) of
303-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
304-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
305-- where
306-- list_length = Prelude.length ls
308takeWhile :: Property
309takeWhile =
310 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
311 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
312 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
313 Left _ -> property False
314 where
315 predicate = (== 0)
317takeWhile1 :: Property
318takeWhile1 =
319 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
320 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
321 Right parsed_list -> case ls of
322 [] -> property False
323 (x : _) ->
324 if predicate x then
325 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
326 else
327 property False
328 Left _ -> case ls of
329 [] -> property True
330 (x : _) -> property (not $ predicate x)
331 where
332 predicate = (== 0)
334sliceSepBy :: Property
335sliceSepBy =
336 forAll (listOf (chooseInt (0, 1))) $ \ls ->
337 case S.parse (P.sliceSepBy predicate FL.toList) (S.fromList ls) of
338 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
339 Left _ -> property False
340 where
341 predicate = (== 1)
343-- sliceSepByMax :: Property
344-- sliceSepByMax =
345-- forAll (chooseInt (min_value, max_value)) $ \n ->
346-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
347-- case S.parse (P.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
348-- Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
349-- Left _ -> property False
350-- where
351-- predicate = (== 1)
353-- splitWithPass :: Property
354-- splitWithPass =
355-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
356-- case S.parse (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
357-- Right (result_first, result_second) -> case ls of
358-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
359-- _ -> False
360-- Left _ -> case ls of
361-- 0 : 1 : _ -> False
362-- _ -> True
364-- splitWithFailLeft :: Property
365-- splitWithFailLeft =
366-- property (case S.parse (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
367-- Right _ -> False
368-- Left _ -> True)
370-- splitWithFailRight :: Property
371-- splitWithFailRight =
372-- property (case S.parse (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
373-- Right _ -> False
374-- Left _ -> True)
376-- splitWithFailBoth :: Property
377-- splitWithFailBoth =
378-- property (case S.parse (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
379-- Right _ -> False
380-- Left _ -> True)
382-- teeWithPass :: Property
383-- teeWithPass =
384-- forAll (chooseInt (0, 10000)) $ \n ->
385-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
386-- let
387-- prsr = P.take n FL.toList
388-- in
389-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
390-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
391-- Left _ -> property False
393-- teeWithFailLeft :: Property
394-- teeWithFailLeft =
395-- property (case S.parse (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
396-- Right _ -> False
397-- Left _ -> True)
399-- teeWithFailRight :: Property
400-- teeWithFailRight =
401-- property (case S.parse (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
402-- Right _ -> False
403-- Left _ -> True)
405-- teeWithFailBoth :: Property
406-- teeWithFailBoth =
407-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
408-- Right _ -> False
409-- Left _ -> True)
411-- deintercalate :: Property
412-- deintercalate =
413-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
414-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
415-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
416-- Left _ -> False
418-- where
419-- prsr_1 = (P.takeWhile (== 0) FL.toList)
420-- prsr_2 = (P.takeWhile (== 1) FL.toList)
421-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
423-- shortestPass :: Property
424-- shortestPass =
425-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
426-- let
427-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
428-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
429-- prsr_shortest = P.shortest prsr_1 prsr_2
430-- in
431-- case S.parse prsr_shortest (S.fromList ls) of
432-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
433-- Left _ -> property False
435-- shortestFailLeft :: Property
436-- shortestFailLeft =
437-- property (case S.parse (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
438-- Right r -> r == 1
439-- Left _ -> False)
441-- shortestFailRight :: Property
442-- shortestFailRight =
443-- property (case S.parse (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
444-- Right r -> r == 1
445-- Left _ -> False)
447-- shortestFailBoth :: Property
448-- shortestFailBoth =
449-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
450-- Right _ -> False
451-- Left _ -> True)
453main :: IO ()
454main =
455 hspec $
456 H.parallel $
457 modifyMaxSuccess (const maxTestCount) $ do
458 describe "test for accumulator" $ do
459 prop "P.fromFold FL.sum = FL.sum" fromFold
460 prop "P.any = Prelude.any" Main.any
461 prop "P.all = Prelude.all" Main.all
462 prop "yield value provided" yield
463 prop "yield monadic value provided" yieldM
464 prop "fail err = Left (SomeException (ParseError err))" parserFail
465 prop "always fail" die
466 prop "always fail but monadic" dieM
468 describe "test for element parser" $ do
469 prop "peek = head with list length > 0" peekPass
470 prop "peek fail on []" peekFail
471 prop "eof pass on []" eofPass
472 prop "eof fail on non-empty list" eofFail
473 prop "first element exists and >= mid_value" satisfyPass
474 prop "check first element exists and satisfies predicate" satisfy
476 describe "test for sequence parser" $ do
477 prop "P.take = Prelude.take" Main.take
478 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
479 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
480 prop "P.takeGE n ls = ls when len >= n" takeGEPass
481 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
482 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
483 -- prop "Fail when stream length exceeded" lookAheadFail
484 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
485 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
486 prop "P.takeWhile = Prelude.takeWhile if taken something, else check why failed" takeWhile1
487 prop "P.sliceSepBy = Prelude.takeWhile (not . predicate)" sliceSepBy
488 -- prop "test for sliceSepByMax function" sliceSepByMax
489 -- prop "pass test for splitWith function" splitWithPass
490 -- prop "left fail test for splitWith function" splitWithFailLeft
491 -- prop "right fail test for splitWith function" splitWithFailRight
492 -- prop "both fail test for splitWith function" splitWithFailBoth
493 -- prop "pass test for teeWith function" teeWithPass
494 -- prop "left fail test for teeWith function" teeWithFailLeft
495 -- prop "right fail test for teeWith function" teeWithFailRight
496 -- prop "both fail test for teeWith function" teeWithFailBoth
497 -- prop "test for deintercalate function" deintercalate
498 -- prop "pass test for shortest function" shortestPass
499 -- prop "left fail test for shortest function" shortestFailLeft
500 -- prop "right fail test for shortest function" shortestFailRight
501 -- prop "both fail test for shortest function" shortestFailBoth
502 takeProperties