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, chooseAny)
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
39listEquals :: (Show a, Eq a, MonadIO m)
40 => ([a] -> [a] -> Bool) -> [a] -> [a] -> PropertyM m ()
41listEquals eq parsed_list list = do
42 when (not $ parsed_list `eq` list) $ liftIO $ putStrLn $
43 "parsed list " ++ show parsed_list
44 ++ "\nlist " ++ show list
45 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
46 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
47 when (not $ parsed_list `eq` list) $
50 "parsed list " ++ show parsed_list
51 ++ "\nlist " ++ show list
52 ++ "\nparsed list \\\\ list " ++ show (parsed_list \\ list)
53 ++ "\nlist \\\\ parsed list " ++ show (list \\ parsed_list)
55 assert (parsed_list `eq` list)
57checkListEqual :: (Show a, Eq a) => [a] -> [a] -> Property
58checkListEqual ls_1 ls_2 = monadicIO (listEquals (==) ls_1 ls_2)
60chooseInt :: (Int, Int) -> Gen Int
67 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
68 case (==) <$> (S.parse (P.fromFold FL.sum) (S.fromList ls)) <*> (S.fold FL.sum (S.fromList ls)) of
69 Right is_equal -> is_equal
74 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
75 case S.parse (P.any (> mid_value)) (S.fromList ls) of
76 Right r -> r == (Prelude.any (> mid_value) ls)
81 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
82 case S.parse (P.all (> mid_value)) (S.fromList ls) of
83 Right r -> r == (Prelude.all (> mid_value) ls)
88 forAll (chooseInt (min_value, max_value)) $ \x ->
89 case S.parse (P.yield x) (S.fromList [1 :: Int]) of
95 forAll (chooseInt (min_value, max_value)) $ \x ->
96 case S.parse (P.yieldM $ return x) (S.fromList [1 :: Int]) of
103 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
110 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
114parserFail :: Property
117 case S.parse (fail err) (S.fromList [0 :: Int]) of
119 Left (SomeException e) -> err == displayException e
121 err = "Testing MonadFail.fail."
123-- Element Parser Tests
127 forAll (chooseInt (1, max_length)) $ \list_length ->
128 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
129 case S.parse P.peek (S.fromList ls) of
130 Right head_value -> case ls of
131 head_ls : _ -> head_value == head_ls
137 property (case S.parse P.peek (S.fromList []) of
143 property (case S.parse P.eof (S.fromList []) of
149 forAll (chooseInt (1, max_length)) $ \list_length ->
150 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
151 case S.parse P.eof (S.fromList ls) of
155satisfyPass :: Property
157 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
158 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
160 ls = first_element : ls_tail
161 predicate = (>= mid_value)
163 case S.parse (P.satisfy predicate) (S.fromList ls) of
164 Right r -> r == first_element
169 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
170 case S.parse (P.satisfy predicate) (S.fromList ls) of
171 Right r -> case ls of
173 (x : _) -> predicate x && (r == x)
176 (x : _) -> not $ predicate x
178 predicate = (>= mid_value)
180-- Sequence Parsers Tests
184 forAll (chooseInt (min_value, max_value)) $ \n ->
185 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
186 case S.parse (P.take n FL.toList) (S.fromList ls) of
187 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
188 Left _ -> property False
190takeEQPass :: Property
192 forAll (chooseInt (min_value, max_value)) $ \n ->
193 forAll (chooseInt (n, max_value)) $ \list_length ->
194 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
195 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
196 Right parsed_list -> checkListEqual parsed_list (Prelude.take n ls)
197 Left _ -> property False
201 forAll (chooseInt (min_value, max_value)) $ \n ->
202 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
204 list_length = Prelude.length ls
206 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
208 if (n <= list_length) then
209 checkListEqual parsed_list (Prelude.take n ls)
212 Left _ -> property (n > list_length)
214takeGEPass :: Property
216 forAll (chooseInt (min_value, max_value)) $ \n ->
217 forAll (chooseInt (n, max_value)) $ \list_length ->
218 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
219 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
220 Right parsed_list -> checkListEqual parsed_list ls
221 Left _ -> property False
225 forAll (chooseInt (min_value, max_value)) $ \n ->
226 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
228 list_length = Prelude.length ls
230 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
232 if (n <= list_length) then
233 checkListEqual parsed_list ls
236 Left _ -> property (n > list_length)
240 -> FL.Fold (Either SomeException) Int [Int]
241 -> P.Parser (Either SomeException) Int [Int]
243 -> (Int -> [Int] -> [Int])
245nLessThanEqual0 tk ltk =
246 forAll (elements [0, (-1)]) $ \n ->
247 forAll (listOf arbitrary) $ \ls ->
248 case S.parse (tk n FL.toList) (S.fromList ls) of
249 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
250 Left _ -> property False
252takeProperties :: Spec
254 describe "take combinators when n <= 0/" $ do
255 prop "take n FL.toList = []" $
256 nLessThanEqual0 P.take (\_ -> const [])
257 prop "takeEQ n FL.toList = []" $
258 nLessThanEqual0 P.takeEQ (\_ -> const [])
259 prop "takeGE n FL.toList xs = xs" $
260 nLessThanEqual0 P.takeGE (\_ -> id)
262-- lookAheadPass :: Property
264-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
266-- takeWithoutConsume = P.lookAhead $ P.take 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, max_value)) $ \list_length ->
273-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
274-- case S.parse 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
278-- lookAheadFail :: 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 (min_value, n - 1)) $ \list_length ->
289-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
290-- case S.parse parseTwice (S.fromList ls) of
294-- lookAhead :: Property
296-- forAll (chooseInt (min_value, 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 (listOf (chooseInt (min_value, max_value))) $ \ls ->
305-- case S.parse parseTwice (S.fromList ls) of
306-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
307-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
309-- list_length = Prelude.length ls
313 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
314 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
315 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
316 Left _ -> property False
320takeWhile1 :: Property
322 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
323 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
324 Right parsed_list -> case ls of
328 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
333 (x : _) -> property (not $ predicate x)
337sliceSepBy :: Property
339 forAll (listOf (chooseInt (0, 1))) $ \ls ->
340 case S.parse (P.sliceSepBy predicate FL.toList) (S.fromList ls) of
341 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile (not . predicate) ls)
342 Left _ -> property False
346sliceSepByMax :: Property
348 forAll (chooseInt (min_value, max_value)) $ \n ->
349 forAll (listOf (chooseInt (0, 1))) $ \ls ->
350 case S.parse (P.sliceSepByMax predicate n FL.toList) (S.fromList ls) of
351 Right parsed_list -> checkListEqual parsed_list (Prelude.take n (Prelude.takeWhile (not . predicate) ls))
352 Left _ -> property False
356-- splitWithPass :: Property
358-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
359-- case S.parse (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
360-- Right (result_first, result_second) -> case ls of
361-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
363-- Left _ -> case ls of
367-- splitWithFailLeft :: Property
368-- splitWithFailLeft =
369-- property (case S.parse (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
373-- splitWithFailRight :: Property
374-- splitWithFailRight =
375-- property (case S.parse (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
379-- splitWithFailBoth :: Property
380-- splitWithFailBoth =
381-- property (case S.parse (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
385-- teeWithPass :: Property
387-- forAll (chooseInt (0, 10000)) $ \n ->
388-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
390-- prsr = P.take n FL.toList
392-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
393-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
394-- Left _ -> property False
396-- teeWithFailLeft :: Property
398-- property (case S.parse (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
402-- teeWithFailRight :: Property
404-- property (case S.parse (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
408-- teeWithFailBoth :: Property
410-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
414-- deintercalate :: Property
416-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
417-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
418-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
422-- prsr_1 = (P.takeWhile (== 0) FL.toList)
423-- prsr_2 = (P.takeWhile (== 1) FL.toList)
424-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
426-- shortestPass :: Property
428-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
430-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
431-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
432-- prsr_shortest = P.shortest prsr_1 prsr_2
434-- case S.parse prsr_shortest (S.fromList ls) of
435-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
436-- Left _ -> property False
438-- shortestFailLeft :: Property
440-- property (case S.parse (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
444-- shortestFailRight :: Property
445-- shortestFailRight =
446-- property (case S.parse (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
450-- shortestFailBoth :: Property
452-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
458 forAll (listOf (chooseInt (0, 1))) $ \ls ->
460 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
461 prsr = P.many concatFold $ P.sliceSepBy (== 1) FL.toList
463 case S.parse prsr (S.fromList ls) of
464 Right res_list -> checkListEqual res_list (Prelude.filter (== 0) ls)
465 Left _ -> property False
467-- many_empty :: Property
469-- property (case S.parse (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
470-- Right res_list -> checkListEqual res_list ([] :: [Int])
471-- Left _ -> property False)
475 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
478 concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
479 prsr = P.some concatFold $ P.sliceSepBy (== 1) FL.toList
481 case S.parse prsr (S.fromList ls) of
482 Right res_list -> res_list == Prelude.filter (== 0) ls
485-- someFail :: Property
487-- property (case S.parse (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
491-------------------------------------------------------------------------------
493-------------------------------------------------------------------------------
495applicative :: Property
497 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
498 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
501 <$> P.take (length list1) FL.toList
502 <*> P.take (length list2) FL.toList
505 run $ S.parse parser (S.fromList $ list1 ++ list2)
506 listEquals (==) olist1 list1
507 listEquals (==) olist2 list2
511 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
512 let parsers = fmap (\xs -> P.take (length xs) FL.toList) ins
516 (Prelude.sequence parsers)
517 (S.fromList $ concat ins)
518 listEquals (==) outs ins
522 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
523 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
525 olist1 <- P.take (length list1) FL.toList
526 olist2 <- P.take (length list2) FL.toList
527 return (olist1, olist2)
530 run $ S.parse parser (S.fromList $ list1 ++ list2)
531 listEquals (==) olist1 list1
532 listEquals (==) olist2 list2
534-------------------------------------------------------------------------------
536-------------------------------------------------------------------------------
540 forAll (chooseInt (1,100)) $ \len ->
541 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
547 (P.take len FL.toList) (S.fromList $ concat ins)
549 listEquals (==) outs ins
551-------------------------------------------------------------------------------
552-- Test for a particular case hit during fs events testing
553-------------------------------------------------------------------------------
556evId = [96,238,17,9,0,0,0,0]
559evFlags = [0,4,1,0,0,0,0,0]
562evPathLen = [71,0,0,0,0,0,0,0]
566 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
567 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
568 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
569 ,114,101,97,109,108,121,47,116,109,112,47,122,122
573event = evId ++ evFlags ++ evPathLen ++ evPath
577 , eventFlags :: Word32
578 , eventAbsPath :: A.Array Word8
579 } deriving (Show, Ord, Eq)
581readOneEvent :: P.Parser IO Word8 Event
583 arr <- P.takeEQ 24 (A.writeN 24)
584 let arr1 = A.unsafeCast arr :: A.Array Word64
585 eid = A.unsafeIndex arr1 0
586 eflags = A.unsafeIndex arr1 1
587 pathLen = fromIntegral $ A.unsafeIndex arr1 2
588 -- XXX handle if pathLen is 0
589 path <- P.takeEQ pathLen (A.writeN pathLen)
592 , eventFlags = fromIntegral eflags
593 , eventAbsPath = path
596parseMany2Events :: Property
602 $ S.parseMany readOneEvent
603 $ S.fromList (concat (replicate 2 event))
605 assert (length xs == 2)
606 -- XXX assuming little endian machine
608 { eventId = 152170080
610 , eventAbsPath = A.fromList evPath
612 in listEquals (==) xs (replicate 2 ev)
614-------------------------------------------------------------------------------
616-------------------------------------------------------------------------------
622 modifyMaxSuccess (const maxTestCount) $ do
623 describe "Instances" $ do
624 prop "applicative" applicative
626 prop "sequence" sequence
628 describe "Stream parsing" $ do
629 prop "parseMany" parseMany
630 prop "parseMany2Events" parseMany2Events
632 describe "test for accumulator" $ do
633 prop "P.fromFold FL.sum = FL.sum" fromFold
634 prop "P.any = Prelude.any" Main.any
635 prop "P.all = Prelude.all" Main.all
636 prop "yield value provided" yield
637 prop "yield monadic value provided" yieldM
638 prop "fail err = Left (SomeException (ParseError err))" parserFail
639 prop "always fail" die
640 prop "always fail but monadic" dieM
642 describe "test for element parser" $ do
643 prop "peek = head with list length > 0" peekPass
644 prop "peek fail on []" peekFail
645 prop "eof pass on []" eofPass
646 prop "eof fail on non-empty list" eofFail
647 prop "first element exists and >= mid_value" satisfyPass
648 prop "check first element exists and satisfies predicate" satisfy
650 describe "test for sequence parser" $ do
651 prop "P.take = Prelude.take" Main.take
652 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
653 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
654 prop "P.takeGE n ls = ls when len >= n" takeGEPass
655 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
656 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
657 -- prop "Fail when stream length exceeded" lookAheadFail
658 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
659 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
660 prop "P.takeWhile = Prelude.takeWhile if taken something, else check why failed" takeWhile1
661 prop "P.sliceSepBy = Prelude.takeWhile (not . predicate)" sliceSepBy
662 prop "P.sliceSepByMax n predicate = Prelude.take n (Prelude.takeWhile (not . predicate))" sliceSepByMax
663 -- prop "" splitWithPass
664 -- prop "" splitWithFailLeft
665 -- prop "" splitWithFailRight
666 -- prop "" splitWithFailBoth
667 -- prop "" teeWithPass
668 -- prop "" teeWithFailLeft
669 -- prop "" teeWithFailRight
670 -- prop "" teeWithFailBoth
671 -- prop "" deintercalate
672 -- prop "" shortestPass
673 -- prop "" shortestFailLeft
674 -- prop "" shortestFailRight
675 -- prop "" shortestFailBoth
676 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
677 -- prop "[] due to parser being die" many_empty
678 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
679 -- 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