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.Storable.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
298 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
299 case S.parseD (P.takeWhile predicate FL.toList) (S.fromList ls) of
300 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
301 Left _ -> property False
305takeWhile1 :: Property
307 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
308 case S.parseD (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
309 Right parsed_list -> case ls of
313 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
318 (x : _) -> property (not $ predicate x)
324 forAll (listOf (chooseInt (0, 1)))
326 case S.parseD parser (S.fromList ls) of
327 Right parsed -> checkListEqual parsed (groupByLF ls)
328 Left _ -> property False
333 parser = P.groupBy cmp FL.toList
336 | otherwise = head $ List.groupBy cmp lst
338sliceSepByMax :: Property
340 forAll (chooseInt (min_value, max_value)) $ \n ->
341 forAll (listOf (chooseInt (0, 1))) $ \ls ->
342 case S.parseD (P.fromFold $ FL.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
343 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
344 Left _ -> property False
350 forAll (listOf (elements [' ', 's']))
352 case S.parseD parser (S.fromList ls) of
353 Right parsed -> checkListEqual parsed (words' ls)
354 Left _ -> property False
359 parser = P.many FL.toList (P.wordBy predicate FL.toList)
362 in if wrds == [] then [""] else wrds
367 forAll (listOf (chooseInt (0, 1))) $ \ls ->
368 case S.parseD (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
369 Right (result_first, result_second) -> case ls of
370 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
376splitWithFailLeft :: Property
378 property (case S.parseD (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
382splitWithFailRight :: Property
384 property (case S.parseD (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
388splitWithFailBoth :: Property
390 property (case S.parseD (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
394teeWithPass :: Property
396 forAll (chooseInt (min_value, max_value)) $ \n ->
397 forAll (listOf (chooseInt (0, 1))) $ \ls ->
399 prsr = P.fromFold $ FL.takeLE n FL.toList
401 case S.parseD (P.teeWith (,) prsr prsr) (S.fromList ls) of
402 Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
403 Left _ -> property False
405teeWithFailLeft :: Property
407 property (case S.parseD (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
411teeWithFailRight :: Property
413 property (case S.parseD (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
417teeWithFailBoth :: Property
419 property (case S.parseD (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
423shortestPass :: Property
425 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
427 half_mid_value = mid_value `Prelude.div` 2
428 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
429 prsr_2 = P.takeWhile (<= mid_value) FL.toList
430 prsr_shortest = P.shortest prsr_1 prsr_2
432 case S.parseD prsr_shortest (S.fromList ls) of
433 Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= half_mid_value) ls)
434 Left _ -> property False
436shortestPassLeft :: Property
438 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
442shortestPassRight :: Property
444 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
448shortestFailBoth :: Property
452 (P.shortest (P.die "die") (P.die "die"))
453 (S.fromList [1 :: Int]) of
457longestPass :: Property
459 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
461 half_mid_value = mid_value `Prelude.div` 2
462 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
463 prsr_2 = P.takeWhile (<= mid_value) FL.toList
464 prsr_longest = P.longest prsr_1 prsr_2
466 case S.parseD prsr_longest (S.fromList ls) of
467 Right long_list -> long_list == Prelude.takeWhile (<= mid_value) ls
470longestPassLeft :: Property
472 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
476longestPassRight :: Property
478 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
482longestFailBoth :: Property
485 (case S.parseD (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
491 forAll (listOf (chooseInt (0, 1)))
493 let fldstp conL currL = return $ FL.Partial (conL ++ currL)
495 FL.Fold fldstp (return (FL.Partial [])) return
498 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
499 in case S.parseD prsr (S.fromList ls) of
501 checkListEqual res_list (Prelude.filter (== 0) ls)
502 Left _ -> property False
504many_empty :: Property
506 property (case S.parseD (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
507 Right res_list -> checkListEqual res_list ([] :: [Int])
508 Left _ -> property False)
512 forAll (listOf (chooseInt (0, 1)))
514 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
515 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
518 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
519 in case S.parseD prsr (S.fromList ls) of
520 Right res_list -> res_list == Prelude.filter (== 0) ls
525 property (case S.parseD (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
529-------------------------------------------------------------------------------
531-------------------------------------------------------------------------------
533applicative :: Property
535 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
536 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
539 <$> P.fromFold (FL.takeLE (length list1) FL.toList)
540 <*> P.fromFold (FL.takeLE (length list2) FL.toList)
543 run $ S.parseD parser (S.fromList $ list1 ++ list2)
544 listEquals (==) olist1 list1
545 listEquals (==) olist2 list2
549 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
550 let parsers = fmap (\xs -> P.fromFold $ FL.takeLE (length xs) FL.toList) ins
554 (Prelude.sequence parsers)
555 (S.fromList $ concat ins)
556 listEquals (==) outs ins
560 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
561 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
563 olist1 <- P.fromFold (FL.takeLE (length list1) FL.toList)
564 olist2 <- P.fromFold (FL.takeLE (length list2) FL.toList)
565 return (olist1, olist2)
568 run $ S.parseD parser (S.fromList $ list1 ++ list2)
569 listEquals (==) olist1 list1
570 listEquals (==) olist2 list2
572-------------------------------------------------------------------------------
574-------------------------------------------------------------------------------
578 forAll (chooseInt (1,100)) $ \len ->
579 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
585 (P.fromFold $ FL.takeLE len FL.toList) (S.fromList $ concat ins)
587 listEquals (==) outs ins
589-------------------------------------------------------------------------------
590-- Test for a particular case hit during fs events testing
591-------------------------------------------------------------------------------
594evId = [96,238,17,9,0,0,0,0]
597evFlags = [0,4,1,0,0,0,0,0]
600evPathLen = [71,0,0,0,0,0,0,0]
604 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
605 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
606 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
607 ,114,101,97,109,108,121,47,116,109,112,47,122,122
611event = evId ++ evFlags ++ evPathLen ++ evPath
615 , eventFlags :: Word32
616 , eventAbsPath :: A.Array Word8
617 } deriving (Show, Ord, Eq)
619readOneEvent :: P.Parser IO Word8 Event
621 arr <- P.takeEQ 24 (A.writeN 24)
622 let arr1 = A.unsafeCast arr :: A.Array Word64
623 eid = A.unsafeIndex arr1 0
624 eflags = A.unsafeIndex arr1 1
625 pathLen = fromIntegral $ A.unsafeIndex arr1 2
626 path <- P.takeEQ pathLen (A.writeN pathLen)
629 , eventFlags = fromIntegral eflags
630 , eventAbsPath = path
633parseMany2Events :: Property
639 $ S.parseManyD readOneEvent
640 $ S.fromList (concat (replicate 2 event))
642 assert (length xs == 2)
643 -- XXX assuming little endian machine
645 { eventId = 152170080
647 , eventAbsPath = A.fromList evPath
649 in listEquals (==) xs (replicate 2 ev)
651-------------------------------------------------------------------------------
653-------------------------------------------------------------------------------
659 modifyMaxSuccess (const maxTestCount) $ do
660 describe "Instances" $ do
661 prop "applicative" applicative
663 prop "sequence" sequence
665 describe "Stream parsing" $ do
666 prop "parseMany" parseMany
667 prop "parseMany2Events" parseMany2Events
669 describe "test for accumulator" $ do
670 prop "P.fromFold FL.sum = FL.sum" fromFold
671 prop "yield value provided" yield
672 prop "yield monadic value provided" yieldM
673 prop "always fail" die
674 prop "always fail but monadic" dieM
676 describe "test for element parser" $ do
677 prop "peek = head with list length > 0" peekPass
678 prop "peek fail on []" peekFail
679 prop "eof pass on []" eofPass
680 prop "eof fail on non-empty list" eofFail
681 prop "first element exists and >= mid_value" satisfyPass
682 prop "check first element exists and satisfies predicate" satisfy
684 describe "test for sequence parser" $ do
685 prop "P.takeBetween m n = Prelude.take when len >= m and len <= n"
687 prop "P.takeBetween m n = Prelude.take when len >= m and len <= n and\
688 \fail otherwise" takeBetween
689 prop "P.take = Prelude.take" Main.take
690 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
691 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
692 prop "P.takeGE n ls = ls when len >= n" takeGEPass
693 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
694 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
695 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
696 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
697 prop "P.takeWhile1 = Prelude.takeWhile if taken something, else check why failed" takeWhile1
698 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
699 prop "P.sliceSepByMax = Prelude.take n (Prelude.takeWhile (not . predicate)" sliceSepByMax
700 prop "many (P.wordBy ' ') = words'" wordBy
701 prop "parse 0, then 1, else fail" splitWith
702 prop "fail due to die as left parser" splitWithFailLeft
703 prop "fail due to die as right parser" splitWithFailRight
704 prop "fail due to die as both parsers" splitWithFailBoth
705 prop "parsed two lists should be equal" teeWithPass
706 prop "fail due to die as left parser" teeWithFailLeft
707 prop "fail due to die as right parser" teeWithFailRight
708 prop "fail due to die as both parsers" teeWithFailBoth
709 prop "P.takeWhile (<= half_mid_value) = Prelude.takeWhile half_mid_value" shortestPass
710 prop "pass even if die is left parser" shortestPassLeft
711 prop "pass even if die is right parser" shortestPassRight
712 prop "fail due to die as both parsers" shortestFailBoth
713 prop "P.takeWhile (<= mid_value) = Prelude.takeWhile (<= mid_value)" longestPass
714 prop "pass even if die is left parser" longestPassLeft
715 prop "pass even if die is right parser" longestPassRight
716 prop "fail due to die as both parsers" longestFailBoth
717 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
718 prop "[] due to parser being die" many_empty
719 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
720 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