1module Main (main) where
3import Control.Exception (SomeException(..))
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,
10 property, listOf, vectorOf, (.&&.), Gen)
11import Test.QuickCheck.Monadic (monadicIO, assert, run)
13import qualified Data.List as List
14import qualified Prelude
15import qualified Streamly.Internal.Data.Array.Foreign as A
16import qualified Streamly.Internal.Data.Fold as FL
17import qualified Streamly.Internal.Data.Parser.ParserD as P
18import qualified Streamly.Internal.Data.Stream.IsStream as S
19import qualified Test.Hspec as H
21import Prelude hiding (sequence)
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)
57 forAll (listOf $ chooseInt (min_value, max_value))
59 case (==) <$> (S.parseD (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.parseD (P.yield x) (S.fromList [1 :: Int]) of
73 forAll (chooseInt (min_value, max_value)) $ \x ->
74 case S.parseD (P.yieldM $ return x) (S.fromList [1 :: Int]) of
81 case S.parseD (P.die "die test") (S.fromList [0 :: Int]) of
88 case S.parseD (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
92-- Element Parser Tests
96 forAll (chooseInt (1, max_length)) $ \list_length ->
97 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
98 case S.parseD P.peek (S.fromList ls) of
99 Right head_value -> case ls of
100 head_ls : _ -> head_value == head_ls
106 property (case S.parseD P.peek (S.fromList []) of
112 property (case S.parseD P.eof (S.fromList []) of
118 forAll (chooseInt (1, max_length)) $ \list_length ->
119 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
120 case S.parseD P.eof (S.fromList ls) of
124satisfyPass :: Property
126 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
127 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
129 ls = first_element : ls_tail
130 predicate = (>= mid_value)
132 case S.parseD (P.satisfy predicate) (S.fromList ls) of
133 Right r -> r == first_element
138 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
139 case S.parseD (P.satisfy predicate) (S.fromList ls) of
140 Right r -> case ls of
142 (x : _) -> predicate x && (r == x)
145 (x : _) -> not $ predicate x
147 predicate = (>= mid_value)
149-- Sequence Parsers Tests
150takeBetweenPass :: Property
152 forAll (chooseInt (min_value, max_value)) $ \m ->
153 forAll (chooseInt (m, max_value)) $ \n ->
154 forAll (chooseInt (m, max_value)) $ \list_length ->
155 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
156 case S.parseD (P.takeBetween m n FL.toList) (S.fromList ls) of
158 let lpl = Prelude.length parsed_list
159 in checkListEqual parsed_list (Prelude.take lpl ls)
160 Left _ -> property False
163takeBetween :: Property
165 forAll (chooseInt (min_value, max_value)) $ \m ->
166 forAll (chooseInt (min_value, max_value)) $ \n ->
167 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
169 list_length = Prelude.length ls
171 case S.parseD (P.takeBetween m n FL.toList) (S.fromList ls) of
173 if m <= list_length && n >= list_length
175 let lpl = Prelude.length parsed_list
176 in checkListEqual parsed_list (Prelude.take
179 Left _ -> property (m > n || list_length < m)
183 forAll (chooseInt (min_value, max_value)) $ \n ->
184 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
185 case S.parseD (P.fromFold $ FL.takeLE n FL.toList) (S.fromList ls) of
186 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
187 Left _ -> property False
189takeEQPass :: Property
191 forAll (chooseInt (min_value, max_value)) $ \n ->
192 forAll (chooseInt (n, max_value)) $ \list_length ->
193 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
194 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
195 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
196 Left _ -> property False
200 forAll (chooseInt (min_value, max_value)) $ \n ->
201 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
203 list_length = Prelude.length ls
205 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
207 if (n <= list_length) then
208 checkListEqual parsed_list (Prelude.take n ls)
211 Left _ -> property (n > list_length)
213takeGEPass :: Property
215 forAll (chooseInt (min_value, max_value)) $ \n ->
216 forAll (chooseInt (n, max_value)) $ \list_length ->
217 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
218 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
219 Right parsed_list -> checkListEqual parsed_list ls
220 Left _ -> property False
224 forAll (chooseInt (min_value, max_value)) $ \n ->
225 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
227 list_length = Prelude.length ls
229 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
231 if (n <= list_length) then
232 checkListEqual parsed_list ls
235 Left _ -> property (n > list_length)
239 -> FL.Fold (Either SomeException) Int [Int]
240 -> P.Parser (Either SomeException) Int [Int]
242 -> (Int -> [Int] -> [Int])
244nLessThanEqual0 tk ltk =
245 forAll (elements [0, (-1)]) $ \n ->
246 forAll (listOf arbitrary) $ \ls ->
247 case S.parseD (tk n FL.toList) (S.fromList ls) of
248 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
249 Left _ -> property False
251takeProperties :: Spec
253 describe "take combinators when n <= 0/" $ do
254 prop "takeEQ n FL.toList = []" $
255 nLessThanEqual0 P.takeEQ (\_ -> const [])
256 prop "takeGE n FL.toList xs = xs" $
257 nLessThanEqual0 P.takeGE (\_ -> id)
260-- XXX lookAhead can't deal with EOF which in this case means when
261-- n==list_length, this test will fail. So excluding that case for now.
262lookAheadPass :: Property
264 forAll (chooseInt (min_value, max_value)) $ \n ->
266 takeWithoutConsume = P.lookAhead $ P.fromFold $ FL.takeLE n FL.toList
268 parsed_list_1 <- takeWithoutConsume
269 parsed_list_2 <- takeWithoutConsume
270 return (parsed_list_1, parsed_list_2)
272 forAll (chooseInt (n+1, max_value)) $ \list_length ->
273 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
274 case S.parseD parseTwice (S.fromList ls) of
275 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
276 Left _ -> property $ False
280 forAll (chooseInt (min_value, max_value)) $ \n ->
282 takeWithoutConsume = P.lookAhead $ P.fromFold $ FL.takeLE n FL.toList
284 parsed_list_1 <- takeWithoutConsume
285 parsed_list_2 <- takeWithoutConsume
286 return (parsed_list_1, parsed_list_2)
288 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
289 case S.parseD parseTwice (S.fromList ls) of
290 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
291 Left _ -> property ((list_length < n) || (list_length == n && n == 0))
293 list_length = Prelude.length ls
297 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
298 case S.parseD (P.takeWhile predicate FL.toList) (S.fromList ls) of
299 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
300 Left _ -> property False
304takeWhile1 :: Property
306 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
307 case S.parseD (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
308 Right parsed_list -> case ls of
312 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
317 (x : _) -> property (not $ predicate x)
323 forAll (listOf (chooseInt (0, 1)))
325 case S.parseD parser (S.fromList ls) of
326 Right parsed -> checkListEqual parsed (groupByLF ls)
327 Left _ -> property False
332 parser = P.groupBy cmp FL.toList
335 | otherwise = head $ List.groupBy cmp lst
337groupByRolling :: Property
339 forAll (listOf (chooseInt (0, 1)))
341 case S.parseD parser (S.fromList ls) of
342 Right parsed -> checkListEqual parsed (groupByLF Nothing ls)
343 Left _ -> property False
348 parser = P.groupBy cmp FL.toList
350 groupByLF Nothing (x:xs) = x : groupByLF (Just x) xs
351 groupByLF (Just y) (x:xs) =
353 then x : groupByLF (Just x) xs
356sliceSepByMax :: Property
358 forAll (chooseInt (min_value, max_value)) $ \n ->
359 forAll (listOf (chooseInt (0, 1))) $ \ls ->
360 case S.parseD (P.fromFold $ FL.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
361 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
362 Left _ -> property False
368 forAll (listOf (elements [' ', 's']))
370 case S.parseD parser (S.fromList ls) of
371 Right parsed -> checkListEqual parsed (words' ls)
372 Left _ -> property False
377 parser = P.many FL.toList (P.wordBy predicate FL.toList)
380 in if wrds == [] then [""] else wrds
385 forAll (listOf (chooseInt (0, 1))) $ \ls ->
386 case S.parseD (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
387 Right (result_first, result_second) -> case ls of
388 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
394splitWithFailLeft :: Property
396 property (case S.parseD (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
400splitWithFailRight :: Property
402 property (case S.parseD (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
406splitWithFailBoth :: Property
408 property (case S.parseD (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
412teeWithPass :: Property
414 forAll (chooseInt (min_value, max_value)) $ \n ->
415 forAll (listOf (chooseInt (0, 1))) $ \ls ->
417 prsr = P.fromFold $ FL.takeLE n FL.toList
419 case S.parseD (P.teeWith (,) prsr prsr) (S.fromList ls) of
420 Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
421 Left _ -> property False
423teeWithFailLeft :: Property
425 property (case S.parseD (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
429teeWithFailRight :: Property
431 property (case S.parseD (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
435teeWithFailBoth :: Property
437 property (case S.parseD (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
441shortestPass :: Property
443 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
445 half_mid_value = mid_value `Prelude.div` 2
446 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
447 prsr_2 = P.takeWhile (<= mid_value) FL.toList
448 prsr_shortest = P.shortest prsr_1 prsr_2
450 case S.parseD prsr_shortest (S.fromList ls) of
451 Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= half_mid_value) ls)
452 Left _ -> property False
454shortestPassLeft :: Property
456 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
460shortestPassRight :: Property
462 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
466shortestFailBoth :: Property
470 (P.shortest (P.die "die") (P.die "die"))
471 (S.fromList [1 :: Int]) of
475longestPass :: Property
477 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
479 half_mid_value = mid_value `Prelude.div` 2
480 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
481 prsr_2 = P.takeWhile (<= mid_value) FL.toList
482 prsr_longest = P.longest prsr_1 prsr_2
484 case S.parseD prsr_longest (S.fromList ls) of
485 Right long_list -> long_list == Prelude.takeWhile (<= mid_value) ls
488longestPassLeft :: Property
490 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
494longestPassRight :: Property
496 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
500longestFailBoth :: Property
503 (case S.parseD (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
509 forAll (listOf (chooseInt (0, 1)))
511 let fldstp conL currL = return $ FL.Partial (conL ++ currL)
513 FL.Fold fldstp (return (FL.Partial [])) return
516 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
517 in case S.parseD prsr (S.fromList ls) of
519 checkListEqual res_list (Prelude.filter (== 0) ls)
520 Left _ -> property False
522many_empty :: Property
524 property (case S.parseD (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
525 Right res_list -> checkListEqual res_list ([] :: [Int])
526 Left _ -> property False)
530 forAll (listOf (chooseInt (0, 1)))
532 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
533 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
536 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
537 in case S.parseD prsr (S.fromList ls) of
538 Right res_list -> res_list == Prelude.filter (== 0) ls
543 property (case S.parseD (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.takeLE (length list1) FL.toList)
558 <*> P.fromFold (FL.takeLE (length list2) FL.toList)
561 run $ S.parseD parser (S.fromList $ list1 ++ list2)
562 listEquals (==) olist1 list1
563 listEquals (==) olist2 list2
567 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
568 let parsers = fmap (\xs -> P.fromFold $ FL.takeLE (length xs) FL.toList) ins
572 (Prelude.sequence parsers)
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.takeLE (length list1) FL.toList)
582 olist2 <- P.fromFold (FL.takeLE (length list2) FL.toList)
583 return (olist1, olist2)
586 run $ S.parseD 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 ->
603 (P.fromFold $ FL.takeLE len FL.toList) (S.fromList $ concat ins)
605 listEquals (==) outs ins
607-------------------------------------------------------------------------------
608-- Test for a particular case hit during fs events testing
609-------------------------------------------------------------------------------
612evId = [96,238,17,9,0,0,0,0]
615evFlags = [0,4,1,0,0,0,0,0]
618evPathLen = [71,0,0,0,0,0,0,0]
622 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
623 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
624 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
625 ,114,101,97,109,108,121,47,116,109,112,47,122,122
629event = evId ++ evFlags ++ evPathLen ++ evPath
633 , eventFlags :: Word32
634 , eventAbsPath :: A.Array Word8
635 } deriving (Show, Ord, Eq)
637readOneEvent :: P.Parser IO Word8 Event
639 arr <- P.takeEQ 24 (A.writeN 24)
640 let arr1 = A.unsafeCast arr :: A.Array Word64
641 eid = A.unsafeIndex arr1 0
642 eflags = A.unsafeIndex arr1 1
643 pathLen = fromIntegral $ A.unsafeIndex arr1 2
644 path <- P.takeEQ pathLen (A.writeN pathLen)
647 , eventFlags = fromIntegral eflags
648 , eventAbsPath = path
651parseMany2Events :: Property
657 $ S.parseManyD 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)
669-------------------------------------------------------------------------------
671-------------------------------------------------------------------------------
677 modifyMaxSuccess (const maxTestCount) $ do
678 describe "Instances" $ do
679 prop "applicative" applicative
681 prop "sequence" sequence
683 describe "Stream parsing" $ do
684 prop "parseMany" parseMany
685 prop "parseMany2Events" parseMany2Events
687 describe "test for accumulator" $ do
688 prop "P.fromFold FL.sum = FL.sum" fromFold
689 prop "yield value provided" yield
690 prop "yield monadic value provided" yieldM
691 prop "always fail" die
692 prop "always fail but monadic" dieM
694 describe "test for element parser" $ do
695 prop "peek = head with list length > 0" peekPass
696 prop "peek fail on []" peekFail
697 prop "eof pass on []" eofPass
698 prop "eof fail on non-empty list" eofFail
699 prop "first element exists and >= mid_value" satisfyPass
700 prop "check first element exists and satisfies predicate" satisfy
702 describe "test for sequence parser" $ do
703 prop "P.takeBetween m n = Prelude.take when len >= m and len <= n"
705 prop "P.takeBetween m n = Prelude.take when len >= m and len <= n and\
706 \fail otherwise" takeBetween
707 prop "P.take = Prelude.take" Main.take
708 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
709 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
710 prop "P.takeGE n ls = ls when len >= n" takeGEPass
711 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
712 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
713 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
714 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
715 prop "P.takeWhile1 = Prelude.takeWhile if taken something, else check why failed" takeWhile1
716 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
717 prop "groupByRolling" groupByRolling
718 prop "P.sliceSepByMax = Prelude.take n (Prelude.takeWhile (not . predicate)" sliceSepByMax
719 prop "many (P.wordBy ' ') = words'" wordBy
720 prop "parse 0, then 1, else fail" splitWith
721 prop "fail due to die as left parser" splitWithFailLeft
722 prop "fail due to die as right parser" splitWithFailRight
723 prop "fail due to die as both parsers" splitWithFailBoth
724 prop "parsed two lists should be equal" teeWithPass
725 prop "fail due to die as left parser" teeWithFailLeft
726 prop "fail due to die as right parser" teeWithFailRight
727 prop "fail due to die as both parsers" teeWithFailBoth
728 prop "P.takeWhile (<= half_mid_value) = Prelude.takeWhile half_mid_value" shortestPass
729 prop "pass even if die is left parser" shortestPassLeft
730 prop "pass even if die is right parser" shortestPassRight
731 prop "fail due to die as both parsers" shortestFailBoth
732 prop "P.takeWhile (<= mid_value) = Prelude.takeWhile (<= mid_value)" longestPass
733 prop "pass even if die is left parser" longestPassLeft
734 prop "pass even if die is right parser" longestPassRight
735 prop "fail due to die as both parsers" longestFailBoth
736 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
737 prop "[] due to parser being die" many_empty
738 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
739 prop "fail due to parser being die" someFail
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