1module Main (main) where
3import Control.Exception (SomeException(..), displayException)
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, property, listOf,
12 vectorOf, counterexample, Gen)
13import Test.QuickCheck.Monadic (monadicIO, PropertyM, assert, monitor, run)
15import Prelude hiding (sequence)
17import qualified Streamly.Internal.Data.Parser as P
18import qualified Streamly.Internal.Data.Stream.IsStream as S
19import qualified Streamly.Internal.Data.Fold as FL
20import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
21import qualified Test.Hspec as H
22import qualified Prelude
24#if MIN_VERSION_QuickCheck(2,14,0)
26import Test.QuickCheck (chooseAny)
30import System.Random (Random(random))
31import Test.QuickCheck.Gen (Gen(MkGen))
33-- | Generates a random element over the natural range of `a`.
34chooseAny :: Random a => Gen a
35chooseAny = 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.parse (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.parse (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.parse (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.parse (P.yield x) (S.fromList [1 :: Int]) of
111 forAll (chooseInt (min_value, max_value)) $ \x ->
112 case S.parse (P.yieldM $ return x) (S.fromList [1 :: Int]) of
119 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
126 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
130parserFail :: Property
133 case S.parse (fail err) (S.fromList [0 :: Int]) of
135 Left (SomeException e) -> err == displayException e
137 err = "Testing MonadFail.fail."
139-- Element Parser Tests
143 forAll (chooseInt (1, max_length)) $ \list_length ->
144 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
145 case S.parse P.peek (S.fromList ls) of
146 Right head_value -> case ls of
147 head_ls : _ -> head_value == head_ls
153 property (case S.parse P.peek (S.fromList []) of
159 property (case S.parse P.eof (S.fromList []) of
165 forAll (chooseInt (1, max_length)) $ \list_length ->
166 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
167 case S.parse P.eof (S.fromList ls) of
171satisfyPass :: Property
173 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
174 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
176 ls = first_element : ls_tail
177 predicate = (>= mid_value)
179 case S.parse (P.satisfy predicate) (S.fromList ls) of
180 Right r -> r == first_element
185 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
186 case S.parse (P.satisfy predicate) (S.fromList ls) of
187 Right r -> case ls of
189 (x : _) -> predicate x && (r == x)
192 (x : _) -> not $ predicate x
194 predicate = (>= mid_value)
196-- Sequence Parsers Tests
200 forAll (chooseInt (min_value, max_value)) $ \n ->
201 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
202 case S.parse (P.take n FL.toList) (S.fromList ls) of
203 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
204 Left _ -> property False
206takeEQPass :: Property
208 forAll (chooseInt (min_value, max_value)) $ \n ->
209 forAll (chooseInt (n, max_value)) $ \list_length ->
210 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
211 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
212 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
213 Left _ -> property False
217 forAll (chooseInt (min_value, max_value)) $ \n ->
218 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
220 list_length = Prelude.length ls
222 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
224 if (n <= list_length) then
225 checkListEqual parsed_list (Prelude.take n ls)
228 Left _ -> property (n > list_length)
230takeGEPass :: Property
232 forAll (chooseInt (min_value, max_value)) $ \n ->
233 forAll (chooseInt (n, max_value)) $ \list_length ->
234 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
235 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
236 Right parsed_list -> checkListEqual parsed_list ls
237 Left _ -> property False
241 forAll (chooseInt (min_value, max_value)) $ \n ->
242 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
244 list_length = Prelude.length ls
246 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
248 if (n <= list_length) then
249 checkListEqual parsed_list ls
252 Left _ -> property (n > list_length)
256 -> FL.Fold (Either SomeException) Int [Int]
257 -> P.Parser (Either SomeException) Int [Int]
259 -> (Int -> [Int] -> [Int])
261nLessThanEqual0 tk ltk =
262 forAll (elements [0, (-1)]) $ \n ->
263 forAll (listOf arbitrary) $ \ls ->
264 case S.parse (tk n FL.toList) (S.fromList ls) of
265 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
266 Left _ -> property False
268takeProperties :: Spec
270 describe "take combinators when n <= 0/" $ do
271 prop "take n FL.toList = []" $
272 nLessThanEqual0 P.take (\_ -> const [])
273 prop "takeEQ n FL.toList = []" $
274 nLessThanEqual0 P.takeEQ (\_ -> const [])
275 prop "takeGE n FL.toList xs = xs" $
276 nLessThanEqual0 P.takeGE (\_ -> id)
278-- lookAheadPass :: Property
280-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
282-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
284-- parsed_list_1 <- takeWithoutConsume
285-- parsed_list_2 <- takeWithoutConsume
286-- return (parsed_list_1, parsed_list_2)
288-- forAll (chooseInt (n, max_value)) $ \list_length ->
289-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
290-- case S.parse parseTwice (S.fromList ls) of
291-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
292-- Left _ -> property $ False
294-- lookAheadFail :: Property
296-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
298-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
300-- parsed_list_1 <- takeWithoutConsume
301-- parsed_list_2 <- takeWithoutConsume
302-- return (parsed_list_1, parsed_list_2)
304-- forAll (chooseInt (min_value, n - 1)) $ \list_length ->
305-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
306-- case S.parse parseTwice (S.fromList ls) of
310-- lookAhead :: Property
312-- forAll (chooseInt (min_value, max_value)) $ \n ->
314-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
316-- parsed_list_1 <- takeWithoutConsume
317-- parsed_list_2 <- takeWithoutConsume
318-- return (parsed_list_1, parsed_list_2)
320-- forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
321-- case S.parse parseTwice (S.fromList ls) of
322-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
323-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
325-- list_length = Prelude.length ls
329 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
330 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
331 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
332 Left _ -> property False
336takeWhile1 :: Property
338 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
339 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
340 Right parsed_list -> case ls of
344 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
349 (x : _) -> property (not $ predicate x)
353sliceSepBy :: Property
355 forAll (listOf (chooseInt (0, 1))) $ \ls ->
356 case S.parse (P.sliceSepBy predicate FL.toList) (S.fromList ls) of
357 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
358 Left _ -> property False
362sliceSepByMax :: Property
364 forAll (chooseInt (min_value, max_value)) $ \n ->
365 forAll (listOf (chooseInt (0, 1))) $ \ls ->
366 case S.parse (P.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
367 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
368 Left _ -> property False
372-- splitWithPass :: Property
374-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
375-- case S.parse (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
376-- Right (result_first, result_second) -> case ls of
377-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
379-- Left _ -> case ls of
383-- splitWithFailLeft :: Property
384-- splitWithFailLeft =
385-- property (case S.parse (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
389-- splitWithFailRight :: Property
390-- splitWithFailRight =
391-- property (case S.parse (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
395-- splitWithFailBoth :: Property
396-- splitWithFailBoth =
397-- property (case S.parse (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
401-- teeWithPass :: Property
403-- forAll (chooseInt (0, 10000)) $ \n ->
404-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
406-- prsr = P.take n FL.toList
408-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
409-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
410-- Left _ -> property False
412-- teeWithFailLeft :: Property
414-- property (case S.parse (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
418-- teeWithFailRight :: Property
420-- property (case S.parse (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
424-- teeWithFailBoth :: Property
426-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
430-- deintercalate :: Property
432-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
433-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
434-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
438-- prsr_1 = (P.takeWhile (== 0) FL.toList)
439-- prsr_2 = (P.takeWhile (== 1) FL.toList)
440-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
442-- shortestPass :: Property
444-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
446-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
447-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
448-- prsr_shortest = P.shortest prsr_1 prsr_2
450-- case S.parse prsr_shortest (S.fromList ls) of
451-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
452-- Left _ -> property False
454-- shortestFailLeft :: Property
456-- property (case S.parse (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
460-- shortestFailRight :: Property
461-- shortestFailRight =
462-- property (case S.parse (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
466-- shortestFailBoth :: Property
468-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
474 forAll (listOf (chooseInt (0, 1))) $ \ls ->
476 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
477 prsr = P.many concatFold $ P.sliceSepBy (== 1) FL.toList
479 case S.parse prsr (S.fromList ls) of
480 Right res_list -> checkListEqual res_list (Prelude.filter (== 0) ls)
481 Left _ -> property False
483-- many_empty :: Property
485-- property (case S.parse (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
486-- Right res_list -> checkListEqual res_list ([] :: [Int])
487-- Left _ -> property False)
491 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
494 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
495 prsr = P.some concatFold $ P.sliceSepBy (== 1) FL.toList
497 case S.parse prsr (S.fromList ls) of
498 Right res_list -> res_list == Prelude.filter (== 0) ls
501-- someFail :: Property
503-- property (case S.parse (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
507-------------------------------------------------------------------------------
509-------------------------------------------------------------------------------
511applicative :: Property
513 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
514 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
517 <$> P.take (length list1) FL.toList
518 <*> P.take (length list2) FL.toList
521 run $ S.parse parser (S.fromList $ list1 ++ list2)
522 listEquals (==) olist1 list1
523 listEquals (==) olist2 list2
527 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
528 let parsers = fmap (\xs -> P.take (length xs) FL.toList) ins
532 (Prelude.sequence parsers)
533 (S.fromList $ concat ins)
534 listEquals (==) outs ins
538 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
539 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
541 olist1 <- P.take (length list1) FL.toList
542 olist2 <- P.take (length list2) FL.toList
543 return (olist1, olist2)
546 run $ S.parse parser (S.fromList $ list1 ++ list2)
547 listEquals (==) olist1 list1
548 listEquals (==) olist2 list2
550-------------------------------------------------------------------------------
552-------------------------------------------------------------------------------
556 forAll (chooseInt (1,100)) $ \len ->
557 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
563 (P.take len FL.toList) (S.fromList $ concat ins)
565 listEquals (==) outs ins
567-------------------------------------------------------------------------------
568-- Test for a particular case hit during fs events testing
569-------------------------------------------------------------------------------
572evId = [96,238,17,9,0,0,0,0]
575evFlags = [0,4,1,0,0,0,0,0]
578evPathLen = [71,0,0,0,0,0,0,0]
582 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
583 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
584 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
585 ,114,101,97,109,108,121,47,116,109,112,47,122,122
589event = evId ++ evFlags ++ evPathLen ++ evPath
593 , eventFlags :: Word32
594 , eventAbsPath :: A.Array Word8
595 } deriving (Show, Ord, Eq)
597readOneEvent :: P.Parser IO Word8 Event
599 arr <- P.takeEQ 24 (A.writeN 24)
600 let arr1 = A.unsafeCast arr :: A.Array Word64
601 eid = A.unsafeIndex arr1 0
602 eflags = A.unsafeIndex arr1 1
603 pathLen = fromIntegral $ A.unsafeIndex arr1 2
604 -- XXX handle if pathLen is 0
605 path <- P.takeEQ pathLen (A.writeN pathLen)
608 , eventFlags = fromIntegral eflags
609 , eventAbsPath = path
612parseMany2Events :: Property
618 $ S.parseMany readOneEvent
619 $ S.fromList (concat (replicate 2 event))
621 assert (length xs == 2)
622 -- XXX assuming little endian machine
624 { eventId = 152170080
626 , eventAbsPath = A.fromList evPath
628 in listEquals (==) xs (replicate 2 ev)
630-------------------------------------------------------------------------------
632-------------------------------------------------------------------------------
638 modifyMaxSuccess (const maxTestCount) $ do
639 describe "Instances" $ do
640 prop "applicative" applicative
642 prop "sequence" sequence
644 describe "Stream parsing" $ do
645 prop "parseMany" parseMany
646 prop "parseMany2Events" parseMany2Events
648 describe "test for accumulator" $ do
649 prop "P.fromFold FL.sum = FL.sum" fromFold
650 prop "P.any = Prelude.any" Main.any
651 prop "P.all = Prelude.all" Main.all
652 prop "yield value provided" yield
653 prop "yield monadic value provided" yieldM
654 prop "fail err = Left (SomeException (ParseError err))" parserFail
655 prop "always fail" die
656 prop "always fail but monadic" dieM
658 describe "test for element parser" $ do
659 prop "peek = head with list length > 0" peekPass
660 prop "peek fail on []" peekFail
661 prop "eof pass on []" eofPass
662 prop "eof fail on non-empty list" eofFail
663 prop "first element exists and >= mid_value" satisfyPass
664 prop "check first element exists and satisfies predicate" satisfy
666 describe "test for sequence parser" $ do
667 prop "P.take = Prelude.take" Main.take
668 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
669 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
670 prop "P.takeGE n ls = ls when len >= n" takeGEPass
671 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
672 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
673 -- prop "Fail when stream length exceeded" lookAheadFail
674 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
675 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
676 prop "P.takeWhile = Prelude.takeWhile if taken something, else check why failed" takeWhile1
677 prop "P.sliceSepBy = Prelude.takeWhile (not . predicate)" sliceSepBy
678 prop "P.sliceSepByMax n predicate = Prelude.take n (Prelude.takeWhile (not . predicate))" sliceSepByMax
679 -- prop "" splitWithPass
680 -- prop "" splitWithFailLeft
681 -- prop "" splitWithFailRight
682 -- prop "" splitWithFailBoth
683 -- prop "" teeWithPass
684 -- prop "" teeWithFailLeft
685 -- prop "" teeWithFailRight
686 -- prop "" teeWithFailBoth
687 -- prop "" deintercalate
688 -- prop "" shortestPass
689 -- prop "" shortestFailLeft
690 -- prop "" shortestFailRight
691 -- prop "" shortestFailBoth
692 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
693 -- prop "[] due to parser being die" many_empty
694 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
695 -- 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