1module Main (main) where
3import Control.Exception (SomeException(..), displayException)
4import Data.Word (Word8, Word32, Word64)
5import Streamly.Test.Common (listEquals, checkListEqual, chooseInt)
6import Test.Hspec (Spec, hspec, describe)
7import Test.Hspec.QuickCheck
9 (arbitrary, forAll, elements, Property, property, listOf,
11import Test.QuickCheck.Monadic (monadicIO, assert, run)
13import Prelude hiding (sequence)
15import qualified Data.List as List
16import qualified Prelude
17import qualified Streamly.Internal.Data.Array.Foreign as A
18import qualified Streamly.Internal.Data.Fold as FL
19import qualified Streamly.Internal.Data.Parser as P
20import qualified Streamly.Internal.Data.Stream.IsStream as S
21import qualified Test.Hspec as H
23#if MIN_VERSION_QuickCheck(2,14,0)
25import Test.QuickCheck (chooseAny)
29import System.Random (Random(random))
30import Test.QuickCheck.Gen (Gen(MkGen))
32-- | Generates a random element over the natural range of `a`.
33chooseAny :: Random a => Gen a
34chooseAny = MkGen (\r _ -> let (x,_) = random r in x)
58 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
59 case (==) <$> S.parse (P.fromFold FL.sum) (S.fromList ls)
60 <*> S.fold FL.sum (S.fromList ls) of
61 Right is_equal -> is_equal
66 forAll (chooseInt (min_value, max_value)) $ \x ->
67 case S.parse (P.fromPure x) (S.fromList [1 :: Int]) of
73 forAll (chooseInt (min_value, max_value)) $ \x ->
74 case S.parse (P.fromEffect $ return x) (S.fromList [1 :: Int]) of
81 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
88 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
95 case S.parse (fail err) (S.fromList [0 :: Int]) of
97 Left (SomeException e) -> err == displayException e
99 err = "Testing MonadFail.fail."
101-- Element Parser Tests
105 forAll (chooseInt (1, max_length)) $ \list_length ->
106 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
107 case S.parse P.peek (S.fromList ls) of
108 Right head_value -> case ls of
109 head_ls : _ -> head_value == head_ls
115 property (case S.parse P.peek (S.fromList []) of
121 property (case S.parse P.eof (S.fromList []) of
127 forAll (chooseInt (1, max_length)) $ \list_length ->
128 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
129 case S.parse P.eof (S.fromList ls) of
133satisfyPass :: Property
135 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
136 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
138 ls = first_element : ls_tail
139 predicate = (>= mid_value)
141 case S.parse (P.satisfy predicate) (S.fromList ls) of
142 Right r -> r == first_element
147 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
148 case S.parse (P.satisfy predicate) (S.fromList ls) of
149 Right r -> case ls of
151 (x : _) -> predicate x && (r == x)
154 (x : _) -> not $ predicate x
156 predicate = (>= mid_value)
158-- Sequence Parsers Tests
159takeBetweenPass :: Property
161 forAll (chooseInt (min_value, max_value)) $ \m ->
162 forAll (chooseInt (m, max_value)) $ \n ->
163 forAll (chooseInt (m, max_value)) $ \list_length ->
164 forAll (vectorOf list_length (chooseInt (min_value, max_value)))
166 case S.parse (P.takeBetween m n FL.toList)
169 let lpl = Prelude.length parsed_list
170 in checkListEqual parsed_list
171 $ Prelude.take lpl ls
172 Left _ -> property False
174takeBetween :: Property
176 forAll (chooseInt (min_value, max_value)) $ \m ->
177 forAll (chooseInt (min_value, max_value)) $ \n ->
178 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
180 list_length = Prelude.length ls
182 case S.parse (P.takeBetween m n FL.toList)
185 if m <= list_length && n >= list_length
187 let lpl = Prelude.length parsed_list
188 in checkListEqual parsed_list
189 $ Prelude.take lpl ls
191 Left _ -> property (m > n || list_length < m)
194takeEQPass :: Property
196 forAll (chooseInt (min_value, max_value)) $ \n ->
197 forAll (chooseInt (n, max_value)) $ \list_length ->
198 forAll (vectorOf list_length
199 (chooseInt (min_value, max_value))) $ \ls ->
200 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
202 checkListEqual parsed_list (Prelude.take n ls)
203 Left _ -> property False
207 forAll (chooseInt (min_value, max_value)) $ \n ->
208 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
210 list_length = Prelude.length ls
212 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
215 then checkListEqual parsed_list (Prelude.take n ls)
217 Left _ -> property (n > list_length)
219takeGEPass :: Property
221 forAll (chooseInt (min_value, max_value)) $ \n ->
222 forAll (chooseInt (n, max_value)) $ \list_length ->
223 forAll (vectorOf list_length (chooseInt (min_value, max_value)))
225 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
226 Right parsed_list -> checkListEqual parsed_list ls
227 Left _ -> property False
231 forAll (chooseInt (min_value, max_value)) $ \n ->
232 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
234 list_length = Prelude.length ls
236 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
239 then checkListEqual parsed_list ls
241 Left _ -> property (n > list_length)
245 -> FL.Fold (Either SomeException) Int [Int]
246 -> P.Parser (Either SomeException) Int [Int]
248 -> (Int -> [Int] -> [Int])
250nLessThanEqual0 tk ltk =
251 forAll (elements [0, (-1)]) $ \n ->
252 forAll (listOf arbitrary) $ \ls ->
253 case S.parse (tk n FL.toList) (S.fromList ls) of
254 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
255 Left _ -> property False
257takeProperties :: Spec
259 describe "take combinators when n <= 0/" $ do
260 prop "takeEQ n FL.toList = []" $
261 nLessThanEqual0 P.takeEQ (\_ -> const [])
262 prop "takeGE n FL.toList xs = xs" $
263 nLessThanEqual0 P.takeGE (\_ -> id)
265-- lookAheadPass :: Property
267-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
269-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
271-- parsed_list_1 <- takeWithoutConsume
272-- parsed_list_2 <- takeWithoutConsume
273-- return (parsed_list_1, parsed_list_2)
275-- forAll (chooseInt (n, max_value)) $ \list_length ->
276-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
277-- case S.parse parseTwice (S.fromList ls) of
278-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
279-- Left _ -> property $ False
281-- lookAheadFail :: Property
283-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
285-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
287-- parsed_list_1 <- takeWithoutConsume
288-- parsed_list_2 <- takeWithoutConsume
289-- return (parsed_list_1, parsed_list_2)
291-- forAll (chooseInt (min_value, n - 1)) $ \list_length ->
292-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
293-- case S.parse parseTwice (S.fromList ls) of
297-- lookAhead :: Property
299-- forAll (chooseInt (min_value, max_value)) $ \n ->
301-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
303-- parsed_list_1 <- takeWithoutConsume
304-- parsed_list_2 <- takeWithoutConsume
305-- return (parsed_list_1, parsed_list_2)
307-- forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
308-- case S.parse parseTwice (S.fromList ls) of
309-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
310-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
312-- list_length = Prelude.length ls
314sliceSepByP :: Property
316 forAll (listOf (chooseInt (min_value, max_value ))) $ \ls ->
317 case S.parse (P.sliceSepByP predicate prsr) (S.fromList ls) of
319 checkListEqual parsed_list (tkwhl ls)
320 Left _ -> property False
323 prsr = P.many (P.satisfy (const True)) FL.toList
324 tkwhl ls = Prelude.takeWhile (not . predicate) ls
326sliceBeginWith :: Property
328 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
331 case S.parse parser (S.fromList ls1) of
333 if not $ Prelude.null ls1
335 let tls = Prelude.takeWhile (not . predicate) (tail ls1)
336 in checkListEqual parsed_list $
337 if predicate (head ls1)
339 else Prelude.takeWhile (not . predicate) ls1
340 else property $ Prelude.null parsed_list
341 Left _ -> property False
344 parser = P.sliceBeginWith predicate FL.toList
348 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
349 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
351 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
352 Left _ -> property False
356takeWhile1 :: Property
358 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
359 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
360 Right parsed_list -> case ls of
365 checkListEqual parsed_list
366 $ Prelude.takeWhile predicate ls
371 (x : _) -> property (not $ predicate x)
377 forAll (listOf (chooseInt (0, 1)))
379 case S.parse parser (S.fromList ls) of
380 Right parsed -> checkListEqual parsed (groupByLF ls)
381 Left _ -> property False
386 parser = P.groupBy cmp FL.toList
389 | otherwise = head $ List.groupBy cmp lst
394 forAll (listOf (elements [' ', 's']))
396 case S.parse parser (S.fromList ls) of
397 Right parsed -> checkListEqual parsed (words' ls)
398 Left _ -> property False
403 parser = P.many (P.wordBy predicate FL.toList) FL.toList
406 in if wrds == [] && length lst > 0 then [""] else wrds
408-- splitWithPass :: Property
410-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
411-- case S.parse (P.serialWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
412-- Right (result_first, result_second) -> case ls of
413-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
415-- Left _ -> case ls of
419-- splitWithFailLeft :: Property
420-- splitWithFailLeft =
421-- property (case S.parse (P.serialWith (,) (P.die "die") (P.fromPure (1 :: Int))) (S.fromList [1 :: Int]) of
425-- splitWithFailRight :: Property
426-- splitWithFailRight =
427-- property (case S.parse (P.serialWith (,) (P.fromPure (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
431-- splitWithFailBoth :: Property
432-- splitWithFailBoth =
433-- property (case S.parse (P.serialWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
437-- teeWithPass :: Property
439-- forAll (chooseInt (0, 10000)) $ \n ->
440-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
442-- prsr = P.take n FL.toList
444-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
445-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
446-- Left _ -> property False
448-- teeWithFailLeft :: Property
450-- property (case S.parse (P.teeWith (,) (P.die "die") (P.fromPure (1 :: Int))) (S.fromList [1 :: Int]) of
454-- teeWithFailRight :: Property
456-- property (case S.parse (P.teeWith (,) (P.fromPure (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
460-- teeWithFailBoth :: Property
462-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
466-- deintercalate :: Property
468-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
469-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
470-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
474-- prsr_1 = (P.takeWhile (== 0) FL.toList)
475-- prsr_2 = (P.takeWhile (== 1) FL.toList)
476-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
478-- shortestPass :: Property
480-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
482-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
483-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
484-- prsr_shortest = P.shortest prsr_1 prsr_2
486-- case S.parse prsr_shortest (S.fromList ls) of
487-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
488-- Left _ -> property False
490-- shortestFailLeft :: Property
492-- property (case S.parse (P.shortest (P.die "die") (P.fromPure (1 :: Int))) (S.fromList [1 :: Int]) of
496-- shortestFailRight :: Property
497-- shortestFailRight =
498-- property (case S.parse (P.shortest (P.fromPure (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
502-- shortestFailBoth :: Property
504-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
510 forAll (listOf (chooseInt (0, 1))) $ \ls ->
511 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
512 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
514 flip P.many concatFold $ P.fromFold $ FL.takeEndBy_ (== 1) FL.toList
516 case S.parse prsr (S.fromList ls) of
517 Right res_list -> checkListEqual res_list
518 $ Prelude.filter (== 0) ls
519 Left _ -> property False
521-- many_empty :: Property
523-- property (case S.parse (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
524-- Right res_list -> checkListEqual res_list ([] :: [Int])
525-- Left _ -> property False)
529 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
532 fldstp conL currL = return $ FL.Partial $ conL ++ currL
533 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
535 flip P.some concatFold $ P.fromFold $ FL.takeEndBy_ (== 1) FL.toList
537 case S.parse prsr (S.fromList ls) of
538 Right res_list -> res_list == Prelude.filter (== 0) ls
541-- someFail :: Property
543-- property (case S.parse (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
547-------------------------------------------------------------------------------
549-------------------------------------------------------------------------------
551applicative :: Property
553 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
554 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
557 <$> P.fromFold (FL.take (length list1) FL.toList)
558 <*> P.fromFold (FL.take (length list2) FL.toList)
561 run $ S.parse parser (S.fromList $ list1 ++ list2)
562 listEquals (==) olist1 list1
563 listEquals (==) olist2 list2
567 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
568 let p xs = P.fromFold (FL.take (length xs) FL.toList)
572 (Prelude.sequence $ fmap p ins)
573 (S.fromList $ concat ins)
574 listEquals (==) outs ins
578 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
579 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
581 olist1 <- P.fromFold (FL.take (length list1) FL.toList)
582 olist2 <- P.fromFold (FL.take (length list2) FL.toList)
583 return (olist1, olist2)
586 run $ S.parse parser (S.fromList $ list1 ++ list2)
587 listEquals (==) olist1 list1
588 listEquals (==) olist2 list2
590-------------------------------------------------------------------------------
592-------------------------------------------------------------------------------
596 forAll (chooseInt (1,100)) $ \len ->
597 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
600 let p = P.fromFold $ FL.take len FL.toList
603 $ S.parseMany p (S.fromList $ concat ins)
604 listEquals (==) outs ins
606-------------------------------------------------------------------------------
607-- Test for a particular case hit during fs events testing
608-------------------------------------------------------------------------------
611evId = [96,238,17,9,0,0,0,0]
614evFlags = [0,4,1,0,0,0,0,0]
617evPathLen = [71,0,0,0,0,0,0,0]
621 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
622 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
623 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
624 ,114,101,97,109,108,121,47,116,109,112,47,122,122
628event = evId ++ evFlags ++ evPathLen ++ evPath
632 , eventFlags :: Word32
633 , eventAbsPath :: A.Array Word8
634 } deriving (Show, Ord, Eq)
636readOneEvent :: P.Parser IO Word8 Event
638 arr <- P.takeEQ 24 (A.writeN 24)
639 let arr1 = A.unsafeCast arr :: A.Array Word64
640 eid = A.unsafeIndex arr1 0
641 eflags = A.unsafeIndex arr1 1
642 pathLen = fromIntegral $ A.unsafeIndex arr1 2
643 -- XXX handle if pathLen is 0
644 path <- P.takeEQ pathLen (A.writeN pathLen)
647 , eventFlags = fromIntegral eflags
648 , eventAbsPath = path
651parseMany2Events :: Property
657 $ S.parseMany readOneEvent
658 $ S.fromList (concat (replicate 2 event))
660 assert (length xs == 2)
661 -- XXX assuming little endian machine
663 { eventId = 152170080
665 , eventAbsPath = A.fromList evPath
667 in listEquals (==) xs (replicate 2 ev)
669manyEqParseMany :: Property
671 forAll (listOf (chooseInt (0, 100))) $ \lst ->
672 forAll (chooseInt (1, 100)) $ \i ->
674 let strm = S.fromList lst
675 r1 <- run $ S.parse (P.many (split i) FL.toList) strm
676 r2 <- run $ S.toList $ S.parseMany (split i) strm
681 split i = P.fromFold (FL.take i FL.toList)
683-------------------------------------------------------------------------------
685-------------------------------------------------------------------------------
688moduleName = "Data.Parser"
694 modifyMaxSuccess (const maxTestCount) $ do
695 describe moduleName $ do
697 describe "Instances" $ do
698 prop "applicative" applicative
700 prop "sequence" sequence
702 describe "Stream parsing" $ do
703 prop "parseMany" parseMany
704 prop "parseMany2Events" parseMany2Events
706 describe "test for accumulator" $ do
707 prop "P.fromFold FL.sum = FL.sum" fromFold
708 prop "fromPure value provided" fromPure
709 prop "fromPure monadic value provided" fromEffect
710 prop "fail err = Left (SomeException (ParseError err))" parserFail
711 prop "always fail" die
712 prop "always fail but monadic" dieM
714 describe "test for element parser" $ do
715 prop "peek = head with list length > 0" peekPass
716 prop "peek fail on []" peekFail
717 prop "eof pass on []" eofPass
718 prop "eof fail on non-empty list" eofFail
719 prop "first element exists and >= mid_value" satisfyPass
720 prop "check first element exists and satisfies predicate" satisfy
722 describe "test for sequence parser" $ do
723 prop "P.takeBetween = Prelude.take when len >= m and len <= n"
725 prop ("P.takeBetween = Prelude.take when len >= m and len <= n and fail"
726 ++ "otherwise fail") Main.takeBetween
728 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
729 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise"
731 prop "P.takeGE n ls = ls when len >= n" takeGEPass
732 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
733 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
734 -- prop "Fail when stream length exceeded" lookAheadFail
735 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
736 prop "P.sliceSepByP test" Main.sliceSepByP
737 prop ("P.sliceBeginWith pred = head : Prelude.takeWhile (not . pred)"
738 ++ " tail") sliceBeginWith
739 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
740 prop ("P.takeWhile1 = Prelude.takeWhile if taken something,"
741 ++ " else check why failed") takeWhile1
742 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
743 prop "many (P.wordBy ' ') = words'" wordBy
744 -- prop "" splitWithPass
745 -- prop "" splitWithFailLeft
746 -- prop "" splitWithFailRight
747 -- prop "" splitWithFailBoth
748 -- prop "" teeWithPass
749 -- prop "" teeWithFailLeft
750 -- prop "" teeWithFailRight
751 -- prop "" teeWithFailBoth
752 -- prop "" deintercalate
753 -- prop "" shortestPass
754 -- prop "" shortestFailLeft
755 -- prop "" shortestFailRight
756 -- prop "" shortestFailBoth
757 prop ("P.many concatFold $ P.takeEndBy_ (== 1) FL.toList ="
758 ++ "Prelude.filter (== 0)") many
759 -- prop "[] due to parser being die" many_empty
760 prop ("P.some concatFold $ P.takeEndBy_ (== 1) FL.toList ="
761 ++ "Prelude.filter (== 0)") some
762 -- prop "fail due to parser being die" someFail
763 prop "P.many == S.parseMany" manyEqParseMany
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list