1module Main (main) where
3import Control.Exception (SomeException(..), displayException)
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, property, listOf,
11import Test.QuickCheck.Monadic (monadicIO, assert, run)
13import Prelude hiding (sequence)
15import qualified Data.List as List
16import qualified Prelude
17import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
18import qualified Streamly.Internal.Data.Fold as FL
19import qualified Streamly.Internal.Data.Parser as P
20import qualified Streamly.Internal.Data.Stream.IsStream as S
21import qualified Test.Hspec as H
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)
58 forAll (listOf $ chooseInt (min_value, max_value)) $ \ls ->
59 case (==) <$> S.parse (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.parse (P.yield x) (S.fromList [1 :: Int]) of
73 forAll (chooseInt (min_value, max_value)) $ \x ->
74 case S.parse (P.yieldM $ return x) (S.fromList [1 :: Int]) of
81 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
88 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
95 case S.parse (fail err) (S.fromList [0 :: Int]) of
97 Left (SomeException e) -> err == displayException e
99 err = "Testing MonadFail.fail."
101-- Element Parser Tests
105 forAll (chooseInt (1, max_length)) $ \list_length ->
106 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
107 case S.parse P.peek (S.fromList ls) of
108 Right head_value -> case ls of
109 head_ls : _ -> head_value == head_ls
115 property (case S.parse P.peek (S.fromList []) of
121 property (case S.parse P.eof (S.fromList []) of
127 forAll (chooseInt (1, max_length)) $ \list_length ->
128 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
129 case S.parse P.eof (S.fromList ls) of
133satisfyPass :: Property
135 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
136 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
138 ls = first_element : ls_tail
139 predicate = (>= mid_value)
141 case S.parse (P.satisfy predicate) (S.fromList ls) of
142 Right r -> r == first_element
147 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
148 case S.parse (P.satisfy predicate) (S.fromList ls) of
149 Right r -> case ls of
151 (x : _) -> predicate x && (r == x)
154 (x : _) -> not $ predicate x
156 predicate = (>= mid_value)
158-- Sequence Parsers Tests
159takeBetweenPass :: Property
161 forAll (chooseInt (min_value, max_value)) $ \m ->
162 forAll (chooseInt (m, max_value)) $ \n ->
163 forAll (chooseInt (m, max_value)) $ \list_length ->
164 forAll (vectorOf list_length (chooseInt (min_value, max_value)))
166 case S.parse (P.takeBetween m n FL.toList)
169 let lpl = Prelude.length parsed_list
170 in checkListEqual parsed_list
171 $ Prelude.take lpl ls
172 Left _ -> property False
174takeBetween :: Property
176 forAll (chooseInt (min_value, max_value)) $ \m ->
177 forAll (chooseInt (min_value, max_value)) $ \n ->
178 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
180 list_length = Prelude.length ls
182 case S.parse (P.takeBetween m n FL.toList)
185 if m <= list_length && n >= list_length
187 let lpl = Prelude.length parsed_list
188 in checkListEqual parsed_list
189 $ Prelude.take lpl ls
191 Left _ -> property (m > n || list_length < m)
194takeEQPass :: Property
196 forAll (chooseInt (min_value, max_value)) $ \n ->
197 forAll (chooseInt (n, max_value)) $ \list_length ->
198 forAll (vectorOf list_length
199 (chooseInt (min_value, max_value))) $ \ls ->
200 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
202 checkListEqual parsed_list (Prelude.take n ls)
203 Left _ -> property False
207 forAll (chooseInt (min_value, max_value)) $ \n ->
208 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
210 list_length = Prelude.length ls
212 case S.parse (P.takeEQ n FL.toList) (S.fromList ls) of
215 then checkListEqual parsed_list (Prelude.take n ls)
217 Left _ -> property (n > list_length)
219takeGEPass :: Property
221 forAll (chooseInt (min_value, max_value)) $ \n ->
222 forAll (chooseInt (n, max_value)) $ \list_length ->
223 forAll (vectorOf list_length (chooseInt (min_value, max_value)))
225 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
226 Right parsed_list -> checkListEqual parsed_list ls
227 Left _ -> property False
231 forAll (chooseInt (min_value, max_value)) $ \n ->
232 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
234 list_length = Prelude.length ls
236 case S.parse (P.takeGE n FL.toList) (S.fromList ls) of
239 then checkListEqual parsed_list ls
241 Left _ -> property (n > list_length)
245 -> FL.Fold (Either SomeException) Int [Int]
246 -> P.Parser (Either SomeException) Int [Int]
248 -> (Int -> [Int] -> [Int])
250nLessThanEqual0 tk ltk =
251 forAll (elements [0, (-1)]) $ \n ->
252 forAll (listOf arbitrary) $ \ls ->
253 case S.parse (tk n FL.toList) (S.fromList ls) of
254 Right parsed_list -> checkListEqual parsed_list (ltk n ls)
255 Left _ -> property False
257takeProperties :: Spec
259 describe "take combinators when n <= 0/" $ do
260 prop "takeEQ n FL.toList = []" $
261 nLessThanEqual0 P.takeEQ (\_ -> const [])
262 prop "takeGE n FL.toList xs = xs" $
263 nLessThanEqual0 P.takeGE (\_ -> id)
265-- lookAheadPass :: Property
267-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
269-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
271-- parsed_list_1 <- takeWithoutConsume
272-- parsed_list_2 <- takeWithoutConsume
273-- return (parsed_list_1, parsed_list_2)
275-- forAll (chooseInt (n, max_value)) $ \list_length ->
276-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
277-- case S.parse parseTwice (S.fromList ls) of
278-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
279-- Left _ -> property $ False
281-- lookAheadFail :: Property
283-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
285-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
287-- parsed_list_1 <- takeWithoutConsume
288-- parsed_list_2 <- takeWithoutConsume
289-- return (parsed_list_1, parsed_list_2)
291-- forAll (chooseInt (min_value, n - 1)) $ \list_length ->
292-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
293-- case S.parse parseTwice (S.fromList ls) of
297-- lookAhead :: Property
299-- forAll (chooseInt (min_value, max_value)) $ \n ->
301-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
303-- parsed_list_1 <- takeWithoutConsume
304-- parsed_list_2 <- takeWithoutConsume
305-- return (parsed_list_1, parsed_list_2)
307-- forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
308-- case S.parse parseTwice (S.fromList ls) of
309-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
310-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
312-- list_length = Prelude.length ls
314sliceSepByP :: Property
316 forAll (listOf (chooseInt (min_value, max_value ))) $ \ls ->
317 case S.parse (P.sliceSepByP predicate prsr) (S.fromList ls) of
319 checkListEqual parsed_list (tkwhl ls)
320 Left _ -> property False
323 prsr = P.many FL.toList (P.satisfy (const True))
324 tkwhl ls = Prelude.takeWhile (not . predicate) ls
329 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
330 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
332 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
333 Left _ -> property False
337takeWhile1 :: Property
339 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
340 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
341 Right parsed_list -> case ls of
346 checkListEqual parsed_list
347 $ Prelude.takeWhile predicate ls
352 (x : _) -> property (not $ predicate x)
358 forAll (listOf (chooseInt (0, 1)))
360 case S.parse parser (S.fromList ls) of
361 Right parsed -> checkListEqual parsed (groupByLF ls)
362 Left _ -> property False
367 parser = P.groupBy cmp FL.toList
370 | otherwise = head $ List.groupBy cmp lst
375 forAll (listOf (elements [' ', 's']))
377 case S.parse parser (S.fromList ls) of
378 Right parsed -> checkListEqual parsed (words' ls)
379 Left _ -> property False
384 parser = P.many FL.toList (P.wordBy predicate FL.toList)
387 in if wrds == [] then [""] else wrds
389-- splitWithPass :: Property
391-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
392-- case S.parse (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
393-- Right (result_first, result_second) -> case ls of
394-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
396-- Left _ -> case ls of
400-- splitWithFailLeft :: Property
401-- splitWithFailLeft =
402-- property (case S.parse (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
406-- splitWithFailRight :: Property
407-- splitWithFailRight =
408-- property (case S.parse (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
412-- splitWithFailBoth :: Property
413-- splitWithFailBoth =
414-- property (case S.parse (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
418-- teeWithPass :: Property
420-- forAll (chooseInt (0, 10000)) $ \n ->
421-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
423-- prsr = P.take n FL.toList
425-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
426-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
427-- Left _ -> property False
429-- teeWithFailLeft :: Property
431-- property (case S.parse (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
435-- teeWithFailRight :: Property
437-- property (case S.parse (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
441-- teeWithFailBoth :: Property
443-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
447-- deintercalate :: Property
449-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
450-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
451-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
455-- prsr_1 = (P.takeWhile (== 0) FL.toList)
456-- prsr_2 = (P.takeWhile (== 1) FL.toList)
457-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
459-- shortestPass :: Property
461-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
463-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
464-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
465-- prsr_shortest = P.shortest prsr_1 prsr_2
467-- case S.parse prsr_shortest (S.fromList ls) of
468-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
469-- Left _ -> property False
471-- shortestFailLeft :: Property
473-- property (case S.parse (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
477-- shortestFailRight :: Property
478-- shortestFailRight =
479-- property (case S.parse (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
483-- shortestFailBoth :: Property
485-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
491 forAll (listOf (chooseInt (0, 1))) $ \ls ->
492 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
493 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
495 P.many concatFold $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
497 case S.parse prsr (S.fromList ls) of
498 Right res_list -> checkListEqual res_list
499 $ Prelude.filter (== 0) ls
500 Left _ -> property False
502-- many_empty :: Property
504-- property (case S.parse (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
505-- Right res_list -> checkListEqual res_list ([] :: [Int])
506-- Left _ -> property False)
510 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
513 fldstp conL currL = return $ FL.Partial $ conL ++ currL
514 concatFold = FL.Fold fldstp (return (FL.Partial [])) return
516 P.some concatFold $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
518 case S.parse prsr (S.fromList ls) of
519 Right res_list -> res_list == Prelude.filter (== 0) ls
522-- someFail :: Property
524-- property (case S.parse (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
528-------------------------------------------------------------------------------
530-------------------------------------------------------------------------------
532applicative :: Property
534 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
535 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
538 <$> P.fromFold (FL.takeLE (length list1) FL.toList)
539 <*> P.fromFold (FL.takeLE (length list2) FL.toList)
542 run $ S.parse parser (S.fromList $ list1 ++ list2)
543 listEquals (==) olist1 list1
544 listEquals (==) olist2 list2
548 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int))) $ \ ins ->
549 let p xs = P.fromFold (FL.takeLE (length xs) FL.toList)
553 (Prelude.sequence $ fmap p ins)
554 (S.fromList $ concat ins)
555 listEquals (==) outs ins
559 forAll (listOf (chooseAny :: Gen Int)) $ \ list1 ->
560 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
562 olist1 <- P.fromFold (FL.takeLE (length list1) FL.toList)
563 olist2 <- P.fromFold (FL.takeLE (length list2) FL.toList)
564 return (olist1, olist2)
567 run $ S.parse parser (S.fromList $ list1 ++ list2)
568 listEquals (==) olist1 list1
569 listEquals (==) olist2 list2
571-------------------------------------------------------------------------------
573-------------------------------------------------------------------------------
577 forAll (chooseInt (1,100)) $ \len ->
578 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
581 let p = P.fromFold $ FL.takeLE len FL.toList
584 $ S.parseMany p (S.fromList $ concat ins)
585 listEquals (==) outs ins
587-------------------------------------------------------------------------------
588-- Test for a particular case hit during fs events testing
589-------------------------------------------------------------------------------
592evId = [96,238,17,9,0,0,0,0]
595evFlags = [0,4,1,0,0,0,0,0]
598evPathLen = [71,0,0,0,0,0,0,0]
602 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
603 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
604 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
605 ,114,101,97,109,108,121,47,116,109,112,47,122,122
609event = evId ++ evFlags ++ evPathLen ++ evPath
613 , eventFlags :: Word32
614 , eventAbsPath :: A.Array Word8
615 } deriving (Show, Ord, Eq)
617readOneEvent :: P.Parser IO Word8 Event
619 arr <- P.takeEQ 24 (A.writeN 24)
620 let arr1 = A.unsafeCast arr :: A.Array Word64
621 eid = A.unsafeIndex arr1 0
622 eflags = A.unsafeIndex arr1 1
623 pathLen = fromIntegral $ A.unsafeIndex arr1 2
624 -- XXX handle if pathLen is 0
625 path <- P.takeEQ pathLen (A.writeN pathLen)
628 , eventFlags = fromIntegral eflags
629 , eventAbsPath = path
632parseMany2Events :: Property
638 $ S.parseMany readOneEvent
639 $ S.fromList (concat (replicate 2 event))
641 assert (length xs == 2)
642 -- XXX assuming little endian machine
644 { eventId = 152170080
646 , eventAbsPath = A.fromList evPath
648 in listEquals (==) xs (replicate 2 ev)
650-------------------------------------------------------------------------------
652-------------------------------------------------------------------------------
658 modifyMaxSuccess (const maxTestCount) $ do
659 describe "Instances" $ do
660 prop "applicative" applicative
662 prop "sequence" sequence
664 describe "Stream parsing" $ do
665 prop "parseMany" parseMany
666 prop "parseMany2Events" parseMany2Events
668 describe "test for accumulator" $ do
669 prop "P.fromFold FL.sum = FL.sum" fromFold
670 prop "yield value provided" yield
671 prop "yield monadic value provided" yieldM
672 prop "fail err = Left (SomeException (ParseError err))" parserFail
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 = Prelude.take when len >= m and len <= n"
687 prop ("P.takeBetween = Prelude.take when len >= m and len <= n and fail"
688 ++ "otherwise fail") Main.takeBetween
690 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
691 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise"
693 prop "P.takeGE n ls = ls when len >= n" takeGEPass
694 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
695 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
696 -- prop "Fail when stream length exceeded" lookAheadFail
697 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
698 prop "P.sliceSepByP test" Main.sliceSepByP
699 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
700 prop ("P.takeWhile1 = Prelude.takeWhile if taken something,"
701 ++ " else check why failed") takeWhile1
702 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
703 prop "many (P.wordBy ' ') = words'" wordBy
704 -- prop "" splitWithPass
705 -- prop "" splitWithFailLeft
706 -- prop "" splitWithFailRight
707 -- prop "" splitWithFailBoth
708 -- prop "" teeWithPass
709 -- prop "" teeWithFailLeft
710 -- prop "" teeWithFailRight
711 -- prop "" teeWithFailBoth
712 -- prop "" deintercalate
713 -- prop "" shortestPass
714 -- prop "" shortestFailLeft
715 -- prop "" shortestFailRight
716 -- prop "" shortestFailBoth
717 prop ("P.many concatFold $ P.sliceSepBy (== 1) FL.toList ="
718 ++ "Prelude.filter (== 0)") many
719 -- prop "[] due to parser being die" many_empty
720 prop ("P.some concatFold $ P.sliceSepBy (== 1) FL.toList ="
721 ++ "Prelude.filter (== 0)") some
722 -- 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