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, suchThat)
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
153 forAll (chooseInt (min_value, max_value)) $ \n ->
154 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
155 case S.parseD (P.fromFold $ FL.ltake n FL.toList) (S.fromList ls) of
156 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
157 Left _ -> property False
159takeEQPass :: Property
161 forAll (chooseInt (min_value, max_value)) $ \n ->
162 forAll (chooseInt (n, max_value)) $ \list_length ->
163 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
164 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
165 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
166 Left _ -> property False
170 forAll (chooseInt (min_value, max_value)) $ \n ->
171 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
173 list_length = Prelude.length ls
175 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
177 if (n <= list_length) then
178 checkListEqual parsed_list (Prelude.take n ls)
181 Left _ -> property (n > list_length)
183takeGEPass :: Property
185 forAll (chooseInt (min_value, max_value)) $ \n ->
186 forAll (chooseInt (n, max_value)) $ \list_length ->
187 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
188 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
189 Right parsed_list -> checkListEqual parsed_list ls
190 Left _ -> property False
194 forAll (chooseInt (min_value, max_value)) $ \n ->
195 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
197 list_length = Prelude.length ls
199 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
201 if (n <= list_length) then
202 checkListEqual parsed_list ls
205 Left _ -> property (n > list_length)
209 -> FL.Fold (Either SomeException) Int [Int]
210 -> P.Parser (Either SomeException) Int [Int]
212 -> (Int -> [Int] -> [Int])
214nLessThanEqual0 tk ltk =
215 forAll (elements [0, (-1)]) $ \n ->
216 forAll (listOf arbitrary) $ \ls ->
217 case S.parseD (tk n FL.toList) (S.fromList ls) of
218 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
219 Left _ -> property False
221takeProperties :: Spec
223 describe "take combinators when n <= 0/" $ do
224 prop "takeEQ n FL.toList = []" $
225 nLessThanEqual0 P.takeEQ (\_ -> const [])
226 prop "takeGE n FL.toList xs = xs" $
227 nLessThanEqual0 P.takeGE (\_ -> id)
230-- XXX lookAhead can't deal with EOF which in this case means when
231-- n==list_length, this test will fail. So excluding that case for now.
232lookAheadPass :: Property
234 forAll (chooseInt (min_value, max_value)) $ \n ->
236 takeWithoutConsume = P.lookAhead $ P.fromFold $ FL.ltake n FL.toList
238 parsed_list_1 <- takeWithoutConsume
239 parsed_list_2 <- takeWithoutConsume
240 return (parsed_list_1, parsed_list_2)
242 forAll (chooseInt (n+1, max_value)) $ \list_length ->
243 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
244 case S.parseD parseTwice (S.fromList ls) of
245 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
246 Left _ -> property $ False
250 forAll (chooseInt (min_value, max_value)) $ \n ->
252 takeWithoutConsume = P.lookAhead $ P.fromFold $ FL.ltake n FL.toList
254 parsed_list_1 <- takeWithoutConsume
255 parsed_list_2 <- takeWithoutConsume
256 return (parsed_list_1, parsed_list_2)
258 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
259 case S.parseD parseTwice (S.fromList ls) of
260 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
261 Left _ -> property ((list_length < n) || (list_length == n && n == 0))
263 list_length = Prelude.length ls
267 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
268 case S.parseD (P.takeWhile predicate FL.toList) (S.fromList ls) of
269 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
270 Left _ -> property False
274takeWhile1 :: Property
276 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
277 case S.parseD (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
278 Right parsed_list -> case ls of
282 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
287 (x : _) -> property (not $ predicate x)
293 forAll (listOf (chooseInt (0, 1)))
295 case S.parseD parser (S.fromList ls) of
296 Right parsed -> checkListEqual parsed (groupByLF ls)
297 Left _ -> property False
302 parser = P.groupBy cmp FL.toList
305 | otherwise = head $ List.groupBy cmp lst
307sliceSepBy :: Property
309 forAll (listOf (chooseInt (0, 1))) $ \ls ->
310 case S.parseD (P.fromFold $ FL.sliceSepBy predicate FL.toList) (S.fromList ls) of
311 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
312 Left _ -> property False
316sliceSepByMax :: Property
318 forAll (chooseInt (min_value, max_value)) $ \n ->
319 forAll (listOf (chooseInt (0, 1))) $ \ls ->
320 case S.parseD (P.fromFold $ FL.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
321 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
322 Left _ -> property False
328 forAll (listOf (elements [' ', 's']))
330 case S.parseD parser (S.fromList ls) of
331 Right parsed -> checkListEqual parsed (words' ls)
332 Left _ -> property False
337 parser = P.many FL.toList (P.wordBy predicate FL.toList)
340 in if wrds == [] then [""] else wrds
345 forAll (listOf (chooseInt (0, 1))) $ \ls ->
346 case S.parseD (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
347 Right (result_first, result_second) -> case ls of
348 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
354splitWithFailLeft :: Property
356 property (case S.parseD (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
360splitWithFailRight :: Property
362 property (case S.parseD (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
366splitWithFailBoth :: Property
368 property (case S.parseD (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
372teeWithPass :: Property
374 forAll (chooseInt (min_value, max_value)) $ \n ->
375 forAll (listOf (chooseInt (0, 1))) $ \ls ->
377 prsr = P.fromFold $ FL.ltake n FL.toList
379 case S.parseD (P.teeWith (,) prsr prsr) (S.fromList ls) of
380 Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
381 Left _ -> property False
383teeWithFailLeft :: Property
385 property (case S.parseD (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
389teeWithFailRight :: Property
391 property (case S.parseD (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
395teeWithFailBoth :: Property
397 property (case S.parseD (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
401shortestPass :: Property
403 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
405 half_mid_value = mid_value `Prelude.div` 2
406 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
407 prsr_2 = P.takeWhile (<= mid_value) FL.toList
408 prsr_shortest = P.shortest prsr_1 prsr_2
410 case S.parseD prsr_shortest (S.fromList ls) of
411 Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= half_mid_value) ls)
412 Left _ -> property False
414shortestPassLeft :: Property
416 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
420shortestPassRight :: Property
422 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
426shortestFailBoth :: Property
430 (P.shortest (P.die "die") (P.die "die"))
431 (S.fromList [1 :: Int]) of
435longestPass :: Property
437 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
439 half_mid_value = mid_value `Prelude.div` 2
440 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
441 prsr_2 = P.takeWhile (<= mid_value) FL.toList
442 prsr_longest = P.longest prsr_1 prsr_2
444 case S.parseD prsr_longest (S.fromList ls) of
445 Right long_list -> long_list == Prelude.takeWhile (<= mid_value) ls
448longestPassLeft :: Property
450 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
454longestPassRight :: Property
456 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
460longestFailBoth :: Property
463 (case S.parseD (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
469 forAll (listOf (chooseInt (0, 1)))
471 let fldstp conL currL = return $ FL.Partial (conL ++ currL)
473 FL.Fold fldstp (return []) return
474 prsr = P.many concatFold $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
475 in case S.parseD prsr (S.fromList ls) of
477 checkListEqual res_list (Prelude.filter (== 0) ls)
478 Left _ -> property False
480many_empty :: Property
482 property (case S.parseD (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
483 Right res_list -> checkListEqual res_list ([] :: [Int])
484 Left _ -> property False)
488 forAll (listOf (chooseInt (0, 1)))
490 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
491 concatFold = FL.Fold fldstp (return []) return
492 prsr = P.some concatFold $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
493 in case S.parseD prsr (S.fromList ls) of
494 Right res_list -> res_list == Prelude.filter (== 0) ls
499 property (case S.parseD (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
503-------------------------------------------------------------------------------
505-------------------------------------------------------------------------------
507-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
509applicative :: Property
511 forAll (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0)) $ \ list1 ->
512 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
515 <$> P.fromFold (FL.ltake (length list1) FL.toList)
516 <*> P.fromFold (FL.ltake (length list2) FL.toList)
519 run $ S.parseD parser (S.fromList $ list1 ++ list2)
520 listEquals (==) olist1 list1
521 listEquals (==) olist2 list2
523-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
527 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0))) $ \ ins ->
528 let parsers = fmap (\xs -> P.fromFold $ FL.ltake (length xs) FL.toList) ins
532 (Prelude.sequence parsers)
533 (S.fromList $ concat ins)
534 listEquals (==) outs ins
536-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
540 forAll (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0)) $ \ list1 ->
541 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
543 olist1 <- P.fromFold (FL.ltake (length list1) FL.toList)
544 olist2 <- P.fromFold (FL.ltake (length list2) FL.toList)
545 return (olist1, olist2)
548 run $ S.parseD parser (S.fromList $ list1 ++ list2)
549 listEquals (==) olist1 list1
550 listEquals (==) olist2 list2
552-------------------------------------------------------------------------------
554-------------------------------------------------------------------------------
558 forAll (chooseInt (1,100)) $ \len ->
559 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
565 (P.fromFold $ FL.ltake len FL.toList) (S.fromList $ concat ins)
567 listEquals (==) outs ins
569-------------------------------------------------------------------------------
570-- Test for a particular case hit during fs events testing
571-------------------------------------------------------------------------------
574evId = [96,238,17,9,0,0,0,0]
577evFlags = [0,4,1,0,0,0,0,0]
580evPathLen = [71,0,0,0,0,0,0,0]
584 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
585 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
586 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
587 ,114,101,97,109,108,121,47,116,109,112,47,122,122
591event = evId ++ evFlags ++ evPathLen ++ evPath
595 , eventFlags :: Word32
596 , eventAbsPath :: A.Array Word8
597 } deriving (Show, Ord, Eq)
599readOneEvent :: P.Parser IO Word8 Event
601 arr <- P.takeEQ 24 (A.writeN 24)
602 let arr1 = A.unsafeCast arr :: A.Array Word64
603 eid = A.unsafeIndex arr1 0
604 eflags = A.unsafeIndex arr1 1
605 pathLen = fromIntegral $ A.unsafeIndex arr1 2
606 path <- P.takeEQ pathLen (A.writeN pathLen)
609 , eventFlags = fromIntegral eflags
610 , eventAbsPath = path
613parseMany2Events :: Property
619 $ S.parseManyD readOneEvent
620 $ S.fromList (concat (replicate 2 event))
622 assert (length xs == 2)
623 -- XXX assuming little endian machine
625 { eventId = 152170080
627 , eventAbsPath = A.fromList evPath
629 in listEquals (==) xs (replicate 2 ev)
631-------------------------------------------------------------------------------
633-------------------------------------------------------------------------------
639 modifyMaxSuccess (const maxTestCount) $ do
640 describe "Instances" $ do
641 prop "applicative" applicative
643 prop "sequence" sequence
645 describe "Stream parsing" $ do
646 prop "parseMany" parseMany
647 prop "parseMany2Events" parseMany2Events
649 describe "test for accumulator" $ do
650 prop "P.fromFold FL.sum = FL.sum" fromFold
651 prop "yield value provided" yield
652 prop "yield monadic value provided" yieldM
653 prop "always fail" die
654 prop "always fail but monadic" dieM
656 describe "test for element parser" $ do
657 prop "peek = head with list length > 0" peekPass
658 prop "peek fail on []" peekFail
659 prop "eof pass on []" eofPass
660 prop "eof fail on non-empty list" eofFail
661 prop "first element exists and >= mid_value" satisfyPass
662 prop "check first element exists and satisfies predicate" satisfy
664 describe "test for sequence parser" $ do
665 prop "P.take = Prelude.take" Main.take
666 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
667 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
668 prop "P.takeGE n ls = ls when len >= n" takeGEPass
669 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
670 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
671 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
672 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
673 prop "P.takeWhile1 = Prelude.takeWhile if taken something, else check why failed" takeWhile1
674 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
675 prop "P.sliceSepBy = Prelude.takeWhile (not . predicate)" sliceSepBy
676 prop "P.sliceSepByMax = Prelude.take n (Prelude.takeWhile (not . predicate)" sliceSepByMax
677 prop "many (P.wordBy ' ') = words'" wordBy
678 prop "parse 0, then 1, else fail" splitWith
679 prop "fail due to die as left parser" splitWithFailLeft
680 prop "fail due to die as right parser" splitWithFailRight
681 prop "fail due to die as both parsers" splitWithFailBoth
682 prop "parsed two lists should be equal" teeWithPass
683 prop "fail due to die as left parser" teeWithFailLeft
684 prop "fail due to die as right parser" teeWithFailRight
685 prop "fail due to die as both parsers" teeWithFailBoth
686 prop "P.takeWhile (<= half_mid_value) = Prelude.takeWhile half_mid_value" shortestPass
687 prop "pass even if die is left parser" shortestPassLeft
688 prop "pass even if die is right parser" shortestPassRight
689 prop "fail due to die as both parsers" shortestFailBoth
690 prop "P.takeWhile (<= mid_value) = Prelude.takeWhile (<= mid_value)" longestPass
691 prop "pass even if die is left parser" longestPassLeft
692 prop "pass even if die is right parser" longestPassRight
693 prop "fail due to die as both parsers" longestFailBoth
694 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
695 prop "[] due to parser being die" many_empty
696 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
697 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