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,
10 vectorOf, Gen, suchThat)
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)) <*> (S.fold FL.sum (S.fromList ls)) of
60 Right is_equal -> is_equal
65 forAll (chooseInt (min_value, max_value)) $ \x ->
66 case S.parse (P.yield x) (S.fromList [1 :: Int]) of
72 forAll (chooseInt (min_value, max_value)) $ \x ->
73 case S.parse (P.yieldM $ return x) (S.fromList [1 :: Int]) of
80 case S.parse (P.die "die test") (S.fromList [0 :: Int]) of
87 case S.parse (P.dieM (Right "die test")) (S.fromList [0 :: Int]) of
94 case S.parse (fail err) (S.fromList [0 :: Int]) of
96 Left (SomeException e) -> err == displayException e
98 err = "Testing MonadFail.fail."
100-- Element Parser Tests
104 forAll (chooseInt (1, max_length)) $ \list_length ->
105 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
106 case S.parse P.peek (S.fromList ls) of
107 Right head_value -> case ls of
108 head_ls : _ -> head_value == head_ls
114 property (case S.parse P.peek (S.fromList []) of
120 property (case S.parse P.eof (S.fromList []) of
126 forAll (chooseInt (1, max_length)) $ \list_length ->
127 forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
128 case S.parse P.eof (S.fromList ls) of
132satisfyPass :: Property
134 forAll (chooseInt (mid_value, max_value)) $ \first_element ->
135 forAll (listOf (chooseInt (min_value, max_value))) $ \ls_tail ->
137 ls = first_element : ls_tail
138 predicate = (>= mid_value)
140 case S.parse (P.satisfy predicate) (S.fromList ls) of
141 Right r -> r == first_element
146 forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
147 case S.parse (P.satisfy predicate) (S.fromList ls) of
148 Right r -> case ls of
150 (x : _) -> predicate x && (r == x)
153 (x : _) -> not $ predicate x
155 predicate = (>= mid_value)
157-- Sequence Parsers Tests
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.parse (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.parse (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.parse (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.parse (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.parse (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)
229-- lookAheadPass :: Property
231-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
233-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
235-- parsed_list_1 <- takeWithoutConsume
236-- parsed_list_2 <- takeWithoutConsume
237-- return (parsed_list_1, parsed_list_2)
239-- forAll (chooseInt (n, max_value)) $ \list_length ->
240-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
241-- case S.parse parseTwice (S.fromList ls) of
242-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
243-- Left _ -> property $ False
245-- lookAheadFail :: Property
247-- forAll (chooseInt (min_value + 1, max_value)) $ \n ->
249-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
251-- parsed_list_1 <- takeWithoutConsume
252-- parsed_list_2 <- takeWithoutConsume
253-- return (parsed_list_1, parsed_list_2)
255-- forAll (chooseInt (min_value, n - 1)) $ \list_length ->
256-- forAll (vectorOf list_length (chooseInt (min_value, max_value))) $ \ls ->
257-- case S.parse parseTwice (S.fromList ls) of
261-- lookAhead :: Property
263-- forAll (chooseInt (min_value, max_value)) $ \n ->
265-- takeWithoutConsume = P.lookAhead $ P.take n FL.toList
267-- parsed_list_1 <- takeWithoutConsume
268-- parsed_list_2 <- takeWithoutConsume
269-- return (parsed_list_1, parsed_list_2)
271-- forAll (listOf (chooseInt (min_value, max_value))) $ \ls ->
272-- case S.parse parseTwice (S.fromList ls) of
273-- Right (ls_1, ls_2) -> checkListEqual ls_1 ls_2 .&&. checkListEqual ls_1 (Prelude.take n ls)
274-- Left _ -> property ((list_length < n) || (list_length == n && n == 0))
276-- list_length = Prelude.length ls
280 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
281 case S.parse (P.takeWhile predicate FL.toList) (S.fromList ls) of
282 Right parsed_list -> checkListEqual parsed_list (Prelude.takeWhile predicate ls)
283 Left _ -> property False
287takeWhile1 :: Property
289 forAll (listOf (chooseInt (0, 1))) $ \ ls ->
290 case S.parse (P.takeWhile1 predicate FL.toList) (S.fromList ls) of
291 Right parsed_list -> case ls of
295 checkListEqual parsed_list (Prelude.takeWhile predicate ls)
300 (x : _) -> property (not $ predicate x)
306 forAll (listOf (chooseInt (0, 1)))
308 case S.parse parser (S.fromList ls) of
309 Right parsed -> checkListEqual parsed (groupByLF ls)
310 Left _ -> property False
315 parser = P.groupBy cmp FL.toList
318 | otherwise = head $ List.groupBy cmp lst
323 forAll (listOf (elements [' ', 's']))
325 case S.parse parser (S.fromList ls) of
326 Right parsed -> checkListEqual parsed (words' ls)
327 Left _ -> property False
332 parser = P.many FL.toList (P.wordBy predicate FL.toList)
335 in if wrds == [] then [""] else wrds
337-- splitWithPass :: Property
339-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
340-- case S.parse (P.splitWith (,) (P.satisfy (== 0)) (P.satisfy (== 1))) (S.fromList ls) of
341-- Right (result_first, result_second) -> case ls of
342-- 0 : 1 : _ -> (result_first == 0) && (result_second == 1)
344-- Left _ -> case ls of
348-- splitWithFailLeft :: Property
349-- splitWithFailLeft =
350-- property (case S.parse (P.splitWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
354-- splitWithFailRight :: Property
355-- splitWithFailRight =
356-- property (case S.parse (P.splitWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
360-- splitWithFailBoth :: Property
361-- splitWithFailBoth =
362-- property (case S.parse (P.splitWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
366-- teeWithPass :: Property
368-- forAll (chooseInt (0, 10000)) $ \n ->
369-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
371-- prsr = P.take n FL.toList
373-- case S.parse (P.teeWith (,) prsr prsr) (S.fromList ls) of
374-- Right (ls_1, ls_2) -> checkListEqual (Prelude.take n ls) ls_1 .&&. checkListEqual ls_1 ls_2
375-- Left _ -> property False
377-- teeWithFailLeft :: Property
379-- property (case S.parse (P.teeWith (,) (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
383-- teeWithFailRight :: Property
385-- property (case S.parse (P.teeWith (,) (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
389-- teeWithFailBoth :: Property
391-- property (case S.parse (P.teeWith (,) (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
395-- deintercalate :: Property
397-- forAll (listOf (chooseInt (0, 1))) $ \ls ->
398-- case S.parse (P.deintercalate concatFold prsr_1 concatFold prsr_2) (S.fromList ls) of
399-- Right parsed_list_tuple -> parsed_list_tuple == (partition (== 0) ls)
403-- prsr_1 = (P.takeWhile (== 0) FL.toList)
404-- prsr_2 = (P.takeWhile (== 1) FL.toList)
405-- concatFold = FL.Fold (\concatList curr_list -> return $ concatList ++ curr_list) (return []) return
407-- shortestPass :: Property
409-- forAll (listOf (chooseInt(min_value, max_value))) $ \ls ->
411-- prsr_1 = P.takeWhile (<= (mid_value `Prelude.div` 2)) FL.toList
412-- prsr_2 = P.takeWhile (<= mid_value) FL.toList
413-- prsr_shortest = P.shortest prsr_1 prsr_2
415-- case S.parse prsr_shortest (S.fromList ls) of
416-- Right short_list -> checkListEqual short_list (Prelude.takeWhile (<= 2500) ls)
417-- Left _ -> property False
419-- shortestFailLeft :: Property
421-- property (case S.parse (P.shortest (P.die "die") (P.yield (1 :: Int))) (S.fromList [1 :: Int]) of
425-- shortestFailRight :: Property
426-- shortestFailRight =
427-- property (case S.parse (P.shortest (P.yield (1 :: Int)) (P.die "die")) (S.fromList [1 :: Int]) of
431-- shortestFailBoth :: Property
433-- property (case S.parse (P.shortest (P.die "die") (P.die "die")) (S.fromList [1 :: Int]) of
439 forAll (listOf (chooseInt (0, 1))) $ \ls ->
440 let fldstp conL currL = return $ FL.Partial $ conL ++ currL
441 concatFold = FL.Fold fldstp (return []) return
442 prsr = P.many concatFold
443 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
445 case S.parse prsr (S.fromList ls) of
446 Right res_list -> checkListEqual res_list (Prelude.filter (== 0) ls)
447 Left _ -> property False
449-- many_empty :: Property
451-- property (case S.parse (P.many FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
452-- Right res_list -> checkListEqual res_list ([] :: [Int])
453-- Left _ -> property False)
457 forAll (listOf (chooseInt (0, 1))) $ \genLs ->
460 concatFold = FL.Fold (\concatList curr_list -> return $ FL.Partial $ concatList ++ curr_list) (return []) return
461 prsr = P.some concatFold
462 $ P.fromFold $ FL.sliceSepBy (== 1) FL.toList
464 case S.parse prsr (S.fromList ls) of
465 Right res_list -> res_list == Prelude.filter (== 0) ls
468-- someFail :: Property
470-- property (case S.parse (P.some FL.toList (P.die "die")) (S.fromList [1 :: Int]) of
474-------------------------------------------------------------------------------
476-------------------------------------------------------------------------------
478-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
480applicative :: Property
482 forAll (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0)) $ \ list1 ->
483 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
486 <$> P.fromFold (FL.ltake (length list1) FL.toList)
487 <*> P.fromFold (FL.ltake (length list2) FL.toList)
490 run $ S.parse parser (S.fromList $ list1 ++ list2)
491 listEquals (==) olist1 list1
492 listEquals (==) olist2 list2
494-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
498 forAll (vectorOf 11 (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0))) $ \ ins ->
499 let p xs = P.fromFold (FL.ltake (length xs) FL.toList)
503 (Prelude.sequence $ fmap p ins)
504 (S.fromList $ concat ins)
505 listEquals (==) outs ins
507-- XXX Remove "`suchThat` (\x -> length x > 0)) $ \ list1 ->" once FL.ltake is
511 forAll (listOf (chooseAny :: Gen Int) `suchThat` (\x -> length x > 0)) $ \ list1 ->
512 forAll (listOf (chooseAny :: Gen Int)) $ \ list2 ->
514 olist1 <- P.fromFold (FL.ltake (length list1) FL.toList)
515 olist2 <- P.fromFold (FL.ltake (length list2) FL.toList)
516 return (olist1, olist2)
519 run $ S.parse parser (S.fromList $ list1 ++ list2)
520 listEquals (==) olist1 list1
521 listEquals (==) olist2 list2
523-------------------------------------------------------------------------------
525-------------------------------------------------------------------------------
529 forAll (chooseInt (1,100)) $ \len ->
530 forAll (listOf (vectorOf len (chooseAny :: Gen Int))) $ \ ins ->
533 let p = P.fromFold $ FL.ltake len FL.toList
536 $ S.parseMany p (S.fromList $ concat ins)
537 listEquals (==) outs ins
539-------------------------------------------------------------------------------
540-- Test for a particular case hit during fs events testing
541-------------------------------------------------------------------------------
544evId = [96,238,17,9,0,0,0,0]
547evFlags = [0,4,1,0,0,0,0,0]
550evPathLen = [71,0,0,0,0,0,0,0]
554 [47,85,115,101,114,115,47,118,111,108,47,118,101,109,98,97,47,99,111,109
555 ,112,111,115,101,119,101 ,108,108,45,116,101,99,104,47,69,110,103,47,112
556 ,114,111,106,101,99,116,115,47,115,116,114,101,97,109,108,121,47,115,116
557 ,114,101,97,109,108,121,47,116,109,112,47,122,122
561event = evId ++ evFlags ++ evPathLen ++ evPath
565 , eventFlags :: Word32
566 , eventAbsPath :: A.Array Word8
567 } deriving (Show, Ord, Eq)
569readOneEvent :: P.Parser IO Word8 Event
571 arr <- P.takeEQ 24 (A.writeN 24)
572 let arr1 = A.unsafeCast arr :: A.Array Word64
573 eid = A.unsafeIndex arr1 0
574 eflags = A.unsafeIndex arr1 1
575 pathLen = fromIntegral $ A.unsafeIndex arr1 2
576 -- XXX handle if pathLen is 0
577 path <- P.takeEQ pathLen (A.writeN pathLen)
580 , eventFlags = fromIntegral eflags
581 , eventAbsPath = path
584parseMany2Events :: Property
590 $ S.parseMany readOneEvent
591 $ S.fromList (concat (replicate 2 event))
593 assert (length xs == 2)
594 -- XXX assuming little endian machine
596 { eventId = 152170080
598 , eventAbsPath = A.fromList evPath
600 in listEquals (==) xs (replicate 2 ev)
602-------------------------------------------------------------------------------
604-------------------------------------------------------------------------------
610 modifyMaxSuccess (const maxTestCount) $ do
611 describe "Instances" $ do
612 prop "applicative" applicative
614 prop "sequence" sequence
616 describe "Stream parsing" $ do
617 prop "parseMany" parseMany
618 prop "parseMany2Events" parseMany2Events
620 describe "test for accumulator" $ do
621 prop "P.fromFold FL.sum = FL.sum" fromFold
622 prop "yield value provided" yield
623 prop "yield monadic value provided" yieldM
624 prop "fail err = Left (SomeException (ParseError err))" parserFail
625 prop "always fail" die
626 prop "always fail but monadic" dieM
628 describe "test for element parser" $ do
629 prop "peek = head with list length > 0" peekPass
630 prop "peek fail on []" peekFail
631 prop "eof pass on []" eofPass
632 prop "eof fail on non-empty list" eofFail
633 prop "first element exists and >= mid_value" satisfyPass
634 prop "check first element exists and satisfies predicate" satisfy
636 describe "test for sequence parser" $ do
637 prop "P.takeEQ = Prelude.take when len >= n" takeEQPass
638 prop "P.takeEQ = Prelude.take when len >= n and fail otherwise" Main.takeEQ
639 prop "P.takeGE n ls = ls when len >= n" takeGEPass
640 prop "P.takeGE n ls = ls when len >= n and fail otherwise" Main.takeGE
641 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n" lookAheadPass
642 -- prop "Fail when stream length exceeded" lookAheadFail
643 -- prop "lookAhead . take n >> lookAhead . take n = lookAhead . take n, else fail" lookAhead
644 prop "P.takeWhile = Prelude.takeWhile" Main.takeWhile
645 prop "P.takeWhile1 = Prelude.takeWhile if taken something, else check why failed" takeWhile1
646 prop "P.groupBy = Prelude.head . Prelude.groupBy" groupBy
647 prop "many (P.wordBy ' ') = words'" wordBy
648 -- prop "" splitWithPass
649 -- prop "" splitWithFailLeft
650 -- prop "" splitWithFailRight
651 -- prop "" splitWithFailBoth
652 -- prop "" teeWithPass
653 -- prop "" teeWithFailLeft
654 -- prop "" teeWithFailRight
655 -- prop "" teeWithFailBoth
656 -- prop "" deintercalate
657 -- prop "" shortestPass
658 -- prop "" shortestFailLeft
659 -- prop "" shortestFailRight
660 -- prop "" shortestFailBoth
661 prop "P.many concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" many
662 -- prop "[] due to parser being die" many_empty
663 prop "P.some concatFold $ P.sliceSepBy (== 1) FL.toList = Prelude.filter (== 0)" some
664 -- 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