1module Main (main) where
3import Control.Exception (SomeException(..))
4import Control.Monad (when)
5import Control.Monad.IO.Class (MonadIO(..))
7import Data.Word (Word8, Word32, Word64)
8import Test.Hspec (Spec, hspec, describe)
9import Test.Hspec.QuickCheck
11 (arbitrary, forAll, choose, elements, Property,
12 property, listOf, vectorOf, counterexample, (.&&.), Gen)
13import Test.QuickCheck.Monadic
14 (monadicIO, PropertyM, assert, monitor, run)
16import qualified Streamly.Internal.Data.Parser.ParserD as P
17import qualified Streamly.Internal.Data.Stream.IsStream as S
18import qualified Streamly.Internal.Data.Fold as FL
19import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
20import qualified Prelude
21import qualified Test.Hspec as H
23import Prelude hiding (sequence)
25#if MIN_VERSION_QuickCheck(2,14,0)
27import Test.QuickCheck (chooseAny)
31import System.Random (Random(random))
32import Test.QuickCheck.Gen (Gen(MkGen))
34-- | Generates a random element over the natural range of `a`.
35chooseAny :: Random a => Gen a
36chooseAny = MkGen (\r _ -> let (x,_) = random r in x)
55listEquals :: (Show a, Eq a, MonadIO m)
56 => ([a] -> [a] -> Bool) -> [a] -> [a] -> PropertyM m ()
57listEquals eq parsed_list list = do
58 when (not $ parsed_list `eq` list) $ liftIO $ putStrLn $
59 "parsed list " ++ show parsed_list
60 ++ "\nlist " ++ show list
61 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
62 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
63 when (not $ parsed_list `eq` list) $
66 "parsed list " ++ show parsed_list
67 ++ "\nlist " ++ show list
68 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
69 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
71 assert (parsed_list `eq` list)
73checkListEqual :: (Show a, Eq a) => [a] -> [a] -> Property
74checkListEqual ls_1 ls_2 = monadicIO (listEquals (==) ls_1 ls_2)
76chooseInt :: (Int, Int) -> Gen Int
83 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
84 case (==) <$> (S.parseD (P.fromFold FL.sum) (S.fromList ls)) <*> (S.fold FL.sum (S.fromList ls)) of
85 Right is_equal -> is_equal
90 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
91 case S.parseD (P.any (> mid_value)) (S.fromList ls) of
92 Right r -> r == (Prelude.any (> mid_value) ls)
97 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
98 case S.parseD (P.all (> mid_value)) (S.fromList ls) of
99 Right r -> r == (Prelude.all (> mid_value) ls)
104 forAll (chooseInt (min_value, max_value)) $ \x ->
105 case S.parseD (P.yield x) (S.fromList [1 :: Int]) of
111 forAll (chooseInt (min_value, max_value)) $ \x ->
112 case S.parseD (P.yieldM $ return x) (S.fromList [1 :: Int]) of
119 case S.parseD (P.die "die test") (S.fromList [0 :: Int]) of
126 case S.parseD (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
130-- Element Parser Tests
134 forAll (chooseInt (1, max_length)) $ \list_length ->
135 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
136 case S.parseD P.peek (S.fromList ls) of
137 Right head_value -> case ls of
138 head_ls : _ -> head_value == head_ls
144 property (case S.parseD P.peek (S.fromList []) of
150 property (case S.parseD P.eof (S.fromList []) of
156 forAll (chooseInt (1, max_length)) $ \list_length ->
157 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
158 case S.parseD P.eof (S.fromList ls) of
162satisfyPass :: Property
164 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
165 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
167 ls = first_element : ls_tail
168 predicate = (>= mid_value)
170 case S.parseD (P.satisfy predicate) (S.fromList ls) of
171 Right r -> r == first_element
176 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
177 case S.parseD (P.satisfy predicate) (S.fromList ls) of
178 Right r -> case ls of
180 (x : _) -> predicate x && (r == x)
183 (x : _) -> not $ predicate x
185 predicate = (>= mid_value)
187-- Sequence Parsers Tests
191 forAll (chooseInt (min_value, max_value)) $ \n ->
192 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
193 case S.parseD (P.take n FL.toList) (S.fromList ls) of
194 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
195 Left _ -> property False
197takeEQPass :: Property
199 forAll (chooseInt (min_value, max_value)) $ \n ->
200 forAll (chooseInt (n, max_value)) $ \list_length ->
201 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
202 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
203 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
204 Left _ -> property False
208 forAll (chooseInt (min_value, max_value)) $ \n ->
209 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
211 list_length = Prelude.length ls
213 case S.parseD (P.takeEQ n FL.toList) (S.fromList ls) of
215 if (n <= list_length) then
216 checkListEqual parsed_list (Prelude.take n ls)
219 Left _ -> property (n > list_length)
221takeGEPass :: Property
223 forAll (chooseInt (min_value, max_value)) $ \n ->
224 forAll (chooseInt (n, max_value)) $ \list_length ->
225 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
226 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
227 Right parsed_list -> checkListEqual parsed_list ls
228 Left _ -> property False
232 forAll (chooseInt (min_value, max_value)) $ \n ->
233 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
235 list_length = Prelude.length ls
237 case S.parseD (P.takeGE n FL.toList) (S.fromList ls) of
239 if (n <= list_length) then
240 checkListEqual parsed_list ls
243 Left _ -> property (n > list_length)
247 -> FL.Fold (Either SomeException) Int [Int]
248 -> P.Parser (Either SomeException) Int [Int]
250 -> (Int -> [Int] -> [Int])
252nLessThanEqual0 tk ltk =
253 forAll (elements [0, (-1)]) $ \n ->
254 forAll (listOf arbitrary) $ \ls ->
255 case S.parseD (tk n FL.toList) (S.fromList ls) of
256 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
257 Left _ -> property False
259takeProperties :: Spec
261 describe "take combinators when n <= 0/" $ do
262 prop "take n FL.toList = []" $
263 nLessThanEqual0 P.take (\_ -> const [])
264 prop "takeEQ n FL.toList = []" $
265 nLessThanEqual0 P.takeEQ (\_ -> const [])
266 prop "takeGE n FL.toList xs = xs" $
267 nLessThanEqual0 P.takeGE (\_ -> id)
270-- XXX lookAhead can't deal with EOF which in this case means when
271-- n==list_length, this test will fail. So excluding that case for now.
272lookAheadPass :: Property
274 forAll (chooseInt (min_value, max_value)) $ \n ->
276 takeWithoutConsume = P.lookAhead $ P.take n FL.toList
278 parsed_list_1 <- takeWithoutConsume
279 parsed_list_2 <- takeWithoutConsume
280 return (parsed_list_1, parsed_list_2)
282 forAll (chooseInt (n+1, max_value)) $ \list_length ->
283 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
284 case S.parseD parseTwice (S.fromList ls) of
285 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
286 Left _ -> property $ False
290 forAll (chooseInt (min_value, max_value)) $ \n ->
292 takeWithoutConsume = P.lookAhead $ P.take n FL.toList
294 parsed_list_1 <- takeWithoutConsume
295 parsed_list_2 <- takeWithoutConsume
296 return (parsed_list_1, parsed_list_2)
298 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
299 case S.parseD parseTwice (S.fromList ls) of
300 Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
301 Left _ -> property ((list_length < n) || (list_length == n && n == 0))
303 list_length = Prelude.length ls
307 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
308 case S.parseD (P.takeWhile predicate FL.toList) (S.fromList ls) of
309 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
310 Left _ -> property False
314takeWhile1 :: Property
316 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
317 case S.parseD (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
318 Right parsed_list -> case ls of
322 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
327 (x : _) -> property (not $ predicate x)
331sliceSepBy :: Property
333 forAll (listOf (chooseInt (0, 1))) $ \ls ->
334 case S.parseD (P.sliceSepBy predicate FL.toList) (S.fromList ls) of
335 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
336 Left _ -> property False
340sliceSepByMax :: Property
342 forAll (chooseInt (min_value, max_value)) $ \n ->
343 forAll (listOf (chooseInt (0, 1))) $ \ls ->
344 case S.parseD (P.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
345 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
346 Left _ -> property False
352 forAll (listOf (chooseInt (0, 1))) $ \ls ->
353 case S.parseD (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
354 Right (result_first, result_second) -> case ls of
355 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
361splitWithFailLeft :: Property
363 property (case S.parseD (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
367splitWithFailRight :: Property
369 property (case S.parseD (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
373splitWithFailBoth :: Property
375 property (case S.parseD (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
379teeWithPass :: Property
381 forAll (chooseInt (min_value, max_value)) $ \n ->
382 forAll (listOf (chooseInt (0, 1))) $ \ls ->
384 prsr = P.take n FL.toList
386 case S.parseD (P.teeWith (,) prsr prsr) (S.fromList ls) of
387 Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
388 Left _ -> property False
390teeWithFailLeft :: Property
392 property (case S.parseD (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
396teeWithFailRight :: Property
398 property (case S.parseD (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
402teeWithFailBoth :: Property
404 property (case S.parseD (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
408shortestPass :: Property
410 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
412 half_mid_value = mid_value `Prelude.div` 2
413 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
414 prsr_2 = P.takeWhile (<= mid_value) FL.toList
415 prsr_shortest = P.shortest prsr_1 prsr_2
417 case S.parseD prsr_shortest (S.fromList ls) of
418 Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= half_mid_value) ls)
419 Left _ -> property False
421shortestPassLeft :: Property
423 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
427shortestPassRight :: Property
429 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
433shortestFailBoth :: Property
435 property (case S.parseD (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
439longestPass :: Property
441 forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
443 half_mid_value = mid_value `Prelude.div` 2
444 prsr_1 = P.takeWhile (<= half_mid_value) FL.toList
445 prsr_2 = P.takeWhile (<= mid_value) FL.toList
446 prsr_longest = P.longest prsr_1 prsr_2
448 case S.parseD prsr_longest (S.fromList ls) of
449 Right long_list -> long_list == Prelude.takeWhile (<= mid_value) ls
452longestPassLeft :: Property
454 property (case S.parseD (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
458longestPassRight :: Property
460 property (case S.parseD (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
464longestFailBoth :: Property
466 property (case S.parseD (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
472 forAll (listOf (chooseInt (0, 1))) $ \ls ->
474 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
475 prsr = P.many concatFold $ P.sliceSepBy (== 1) FL.toList
477 case S.parseD prsr (S.fromList ls) of
478 Right res_list -> checkListEqual res_list (Prelude.filter (== 0) ls)
479 Left _ -> property False
481many_empty :: Property
483 property (case S.parseD (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
484 Right res_list -> checkListEqual res_list ([] :: [Int])
485 Left _ -> property False)
489 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
492 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
493 prsr = P.some concatFold $ P.sliceSepBy (== 1) FL.toList
495 case S.parseD prsr (S.fromList ls) of
496 Right res_list -> res_list == Prelude.filter (== 0) ls
501 property (case S.parseD (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
505-------------------------------------------------------------------------------
507-------------------------------------------------------------------------------
509applicative :: Property
511 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
512 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
515 <$> P.take (length list1) FL.toList
516 <*> P.take (length list2) FL.toList
519 run $ S.parseD parser (S.fromList $ list1 ++ list2)
520 listEquals (==) olist1 list1
521 listEquals (==) olist2 list2
525 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
526 let parsers = fmap (\xs -> P.take (length xs) FL.toList) ins
530 (Prelude.sequence parsers)
531 (S.fromList $ concat ins)
532 listEquals (==) outs ins
536 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
537 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
539 olist1 <- P.take (length list1) FL.toList
540 olist2 <- P.take (length list2) FL.toList
541 return (olist1, olist2)
544 run $ S.parseD parser (S.fromList $ list1 ++ list2)
545 listEquals (==) olist1 list1
546 listEquals (==) olist2 list2
548-------------------------------------------------------------------------------
550-------------------------------------------------------------------------------
554 forAll (chooseInt (1,100)) $ \len ->
555 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
561 (P.take len FL.toList) (S.fromList $ concat ins)
563 listEquals (==) outs ins
565-------------------------------------------------------------------------------
566-- Test for a particular case hit during fs events testing
567-------------------------------------------------------------------------------
570evId = [96,238,17,9,0,0,0,0]
573evFlags = [0,4,1,0,0,0,0,0]
576evPathLen = [71,0,0,0,0,0,0,0]
580 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
581 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
582 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
583 ,114,101,97,109,108,121,47,116,109,112,47,122,122
587event = evId ++ evFlags ++ evPathLen ++ evPath
591 , eventFlags :: Word32
592 , eventAbsPath :: A.Array Word8
593 } deriving (Show, Ord, Eq)
595readOneEvent :: P.Parser IO Word8 Event
597 arr <- P.takeEQ 24 (A.writeN 24)
598 let arr1 = A.unsafeCast arr :: A.Array Word64
599 eid = A.unsafeIndex arr1 0
600 eflags = A.unsafeIndex arr1 1
601 pathLen = fromIntegral $ A.unsafeIndex arr1 2
602 path <- P.takeEQ pathLen (A.writeN pathLen)
605 , eventFlags = fromIntegral eflags
606 , eventAbsPath = path
609parseMany2Events :: Property
615 $ S.parseManyD readOneEvent
616 $ S.fromList (concat (replicate 2 event))
618 assert (length xs == 2)
619 -- XXX assuming little endian machine
621 { eventId = 152170080
623 , eventAbsPath = A.fromList evPath
625 in listEquals (==) xs (replicate 2 ev)
627-------------------------------------------------------------------------------
629-------------------------------------------------------------------------------
635 modifyMaxSuccess (const maxTestCount) $ do
636 describe "Instances" $ do
637 prop "applicative" applicative
639 prop "sequence" sequence
641 describe "Stream parsing" $ do
642 prop "parseMany" parseMany
643 prop "parseMany2Events" parseMany2Events
645 describe "test for accumulator" $ do
646 prop "P.fromFold FL.sum = FL.sum" fromFold
647 prop "P.any = Prelude.any" Main.any
648 prop "P.all = Prelude.all" Main.all
649 prop "yield value provided" yield
650 prop "yield monadic value provided" yieldM
651 prop "always fail" die
652 prop "always fail but monadic" dieM
654 describe "test for element parser" $ do
655 prop "peek = head with list length > 0" peekPass
656 prop "peek fail on []" peekFail
657 prop "eof pass on []" eofPass
658 prop "eof fail on non-empty list" eofFail
659 prop "first element exists and >= mid_value" satisfyPass
660 prop "check first element exists and satisfies predicate" satisfy
662 describe "test for sequence parser" $ do
663 prop "P.take = Prelude.take" Main.take
664 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
665 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
666 prop "P.takeGE n ls = ls when len >= n" takeGEPass
667 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
668 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
669 prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
670 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
671 prop "P.takeWhile1 = Prelude.takeWhile if taken something, else check why failed" takeWhile1
672 prop "P.sliceSepBy = Prelude.takeWhile (not . predicate)" sliceSepBy
673 prop "P.sliceSepByMax = Prelude.take n (Prelude.takeWhile (not . predicate)" sliceSepByMax
674 prop "parse 0, then 1, else fail" splitWith
675 prop "fail due to die as left parser" splitWithFailLeft
676 prop "fail due to die as right parser" splitWithFailRight
677 prop "fail due to die as both parsers" splitWithFailBoth
678 prop "parsed two lists should be equal" teeWithPass
679 prop "fail due to die as left parser" teeWithFailLeft
680 prop "fail due to die as right parser" teeWithFailRight
681 prop "fail due to die as both parsers" teeWithFailBoth
682 prop "P.takeWhile (<= half_mid_value) = Prelude.takeWhile half_mid_value" shortestPass
683 prop "pass even if die is left parser" shortestPassLeft
684 prop "pass even if die is right parser" shortestPassRight
685 prop "fail due to die as both parsers" shortestFailBoth
686 prop "P.takeWhile (<= mid_value) = Prelude.takeWhile (<= mid_value)" longestPass
687 prop "pass even if die is left parser" longestPassLeft
688 prop "pass even if die is right parser" longestPassRight
689 prop "fail due to die as both parsers" longestFailBoth
690 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
691 prop "[] due to parser being die" many_empty
692 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
693 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