streamly/test/Streamly/Test/Prelude/Top.hs
2023-08-03 17:47:07 +05:30

225 lines
6.8 KiB
Haskell

{-# OPTIONS_GHC -Wno-deprecations #-}
module Main (main) where
import Data.List (elem, intersect, nub, sort)
import Data.Maybe (isNothing)
import Streamly.Prelude (SerialT)
import Test.QuickCheck
( Gen
, Property
, choose
, forAll
, listOf
)
import Test.QuickCheck.Monadic (monadicIO, assert, run)
import qualified Streamly.Prelude as S
import qualified Streamly.Internal.Data.Stream.IsStream as Top
import Prelude hiding
(maximum, minimum, elem, notElem, null, product, sum, head, last, take)
import Test.Hspec as H
import Test.Hspec.QuickCheck
min_value :: Int
min_value = 0
max_value :: Int
max_value = 10000
chooseInt :: (Int, Int) -> Gen Int
chooseInt = choose
eq :: Int -> Int -> Bool
eq = (==)
joinInner :: Property
joinInner =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
monadicIO $ action ls0 ls1
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinInner eq (S.fromList ls0) (S.fromList $ sort ls1)
let v2 = [ (i,j) | i <- ls0, j <- ls1, i == j ]
assert (v1 == v2)
joinInnerMap :: Property
joinInnerMap =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
monadicIO $
action
(map (\a -> (a,a)) ls0)
(map (\a -> (a,a)) ls1)
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinInnerMap (S.fromList ls0) (S.fromList ls1)
let v2 = [
(fst i, fst i, fst j)
| i <- ls0, j <- nub ls1
, fst i == fst j
]
assert (sort v1 == sort v2)
joinOuterList :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Maybe Int, Maybe Int)]
joinOuterList ls0 ls1 =
let v2 = do
i <- ls0
if i `elem` ls1
then return (fst i, Just (fst i), Just (fst i))
else return (fst i, Just (fst i), Nothing)
v3 = do
j <- ls1
if j `elem` ls0
then return (fst j, Just (fst j), Just (fst j))
else return (fst j, Nothing, Just (fst j))
v4 = filter (\(_, a2, _) -> isNothing a2) v3
in v2 ++ v4
{-
joinOuter :: Property
joinOuter =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
monadicIO $ action ls0 (nub ls1)
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinOuter eq (S.fromList ls0) (S.fromList ls1)
let v2 = joinOuterList
(map (\a -> (a, a)) ls0)
(map (\a -> (a, a)) ls1)
v3 = map (\(_, v10, v20) -> (v10, v20)) v2
assert (sort v1 == sort v3)
-}
joinOuterMap :: Property
joinOuterMap =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
monadicIO $
action
(map (\a -> (a,a)) (nub ls0))
(map (\a -> (a,a)) (nub ls1))
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinOuterMap (S.fromList ls0) (S.fromList ls1)
let v2 = joinOuterList ls0 ls1
assert (sort v1 == sort v2)
joinLeftList :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Int, Maybe Int)]
joinLeftList ls0 ls1 =
let v = do
i <- ls0
if i `elem` ls1
then return (fst i, fst i, Just (fst i))
else return (fst i, fst i, Nothing)
in v
{-
joinLeft :: Property
joinLeft =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
-- nub the second list as no way to validate using list functions
monadicIO $ action ls0 (nub ls1)
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinLeft eq (S.fromList ls0) (S.fromList ls1)
let v2 = joinLeftList (map (\a -> (a,a)) ls0) (map (\a -> (a,a)) ls1)
v3 = map (\ (_, x1, x2) -> (x1, x2)) v2
assert (v1 == v3)
-}
joinLeftMap :: Property
joinLeftMap =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
-- nub the second list as no way to validate using list functions
monadicIO $
action (map (\a -> (a,a)) ls0) (map (\a -> (a,a)) (nub ls1))
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ Top.joinLeftMap (S.fromList ls0) (S.fromList ls1)
let v2 = joinLeftList ls0 ls1
assert (v1 == v2)
intersectBy ::
([Int] -> [Int])
-> ( (Int -> Int -> a)
-> SerialT IO Int
-> SerialT IO Int
-> SerialT IO Int
)
-> (Int -> Int -> a)
-> Property
intersectBy srt intersectFunc cmp =
forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
monadicIO $ action (srt ls0) (srt ls1)
where
action ls0 ls1 = do
v1 <-
run
$ S.toList
$ intersectFunc
cmp
(S.fromList ls0)
(S.fromList ls1)
let v2 = ls0 `intersect` ls1
assert (sort v1 == sort v2)
-------------------------------------------------------------------------------
-- Main
-------------------------------------------------------------------------------
moduleName :: String
moduleName = "Prelude.Top"
main :: IO ()
main = hspec $ do
describe moduleName $ do
-- Joins
prop "joinInner" Main.joinInner
prop "joinInnerMap" Main.joinInnerMap
-- prop "joinOuter" Main.joinOuter
prop "joinOuterMap" Main.joinOuterMap
-- prop "joinLeft" Main.joinLeft
prop "joinLeftMap" Main.joinLeftMap
-- intersect
prop "intersectBy"
(intersectBy id Top.intersectBy (==))
prop "intersectBySorted"
(intersectBy sort Top.intersectBySorted compare)