streamly-0.7.1: test/Streamly/Test/Array.hs
{-# LANGUAGE CPP #-}
-- |
-- Module : Main
-- Copyright : (c) 2019 Composewell Technologies
--
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
--
module Main (main) where
import Foreign.Storable (Storable(..))
import Test.Hspec.QuickCheck
import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
import Test.QuickCheck.Monadic (monadicIO, assert, run)
import Test.Hspec as H
import Streamly (SerialT)
import qualified Streamly.Prelude as S
#ifdef TEST_SMALL_ARRAY
import qualified Streamly.Internal.Data.SmallArray as A
type Array = A.SmallArray
#elif defined(TEST_ARRAY)
import qualified Streamly.Memory.Array as A
import qualified Streamly.Internal.Memory.Array as A
import qualified Streamly.Internal.Prelude as IP
type Array = A.Array
#elif defined(TEST_PRIM_ARRAY)
import qualified Streamly.Internal.Data.Prim.Array as A
type Array = A.PrimArray
#else
import qualified Streamly.Internal.Data.Array as A
type Array = A.Array
#endif
-- Coverage build takes too long with default number of tests
maxTestCount :: Int
#ifdef DEVBUILD
maxTestCount = 100
#else
maxTestCount = 10
#endif
allocOverhead :: Int
allocOverhead = 2 * sizeOf (undefined :: Int)
-- XXX this should be in sync with the defaultChunkSize in Array code, or we
-- should expose that and use that. For fast testing we could reduce the
-- defaultChunkSize under CPP conditionals.
--
defaultChunkSize :: Int
defaultChunkSize = 32 * k - allocOverhead
where k = 1024
maxArrLen :: Int
maxArrLen = defaultChunkSize * 8
genericTestFrom ::
(Int -> SerialT IO Int -> IO (Array Int))
-> Property
genericTestFrom arrFold =
forAll (choose (0, maxArrLen)) $ \len ->
forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
monadicIO $ do
arr <- run $ arrFold len $ S.fromList list
assert (A.length arr == len)
testLength :: Property
testLength = genericTestFrom (\n -> S.fold (A.writeN n))
testLengthFromStreamN :: Property
testLengthFromStreamN = genericTestFrom A.fromStreamN
#ifndef TEST_SMALL_ARRAY
testLengthFromStream :: Property
testLengthFromStream = genericTestFrom (const A.fromStream)
#endif
genericTestFromTo ::
(Int -> SerialT IO Int -> IO (Array Int))
-> (Array Int -> SerialT IO Int)
-> ([Int] -> [Int] -> Bool)
-> Property
genericTestFromTo arrFold arrUnfold listEq =
forAll (choose (0, maxArrLen)) $ \len ->
forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
monadicIO $ do
arr <- run $ arrFold len $ S.fromList list
xs <- run $ S.toList $ arrUnfold arr
assert (listEq xs list)
testFoldNUnfold :: Property
testFoldNUnfold =
genericTestFromTo (\n -> S.fold (A.writeN n)) (S.unfold A.read) (==)
testFoldNToStream :: Property
testFoldNToStream =
genericTestFromTo (\n -> S.fold (A.writeN n)) A.toStream (==)
testFoldNToStreamRev :: Property
testFoldNToStreamRev =
genericTestFromTo
(\n -> S.fold (A.writeN n))
A.toStreamRev
(\xs list -> xs == reverse list)
testFromStreamNUnfold :: Property
testFromStreamNUnfold = genericTestFromTo A.fromStreamN (S.unfold A.read) (==)
testFromStreamNToStream :: Property
testFromStreamNToStream = genericTestFromTo A.fromStreamN A.toStream (==)
#ifndef TEST_SMALL_ARRAY
testFromStreamToStream :: Property
testFromStreamToStream = genericTestFromTo (const A.fromStream) A.toStream (==)
testFoldUnfold :: Property
testFoldUnfold = genericTestFromTo (const (S.fold A.write)) (S.unfold A.read) (==)
#endif
#ifdef TEST_ARRAY
testArraysOf :: Property
testArraysOf =
forAll (choose (0, maxArrLen)) $ \len ->
forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
monadicIO $ do
xs <- S.toList
$ S.concatUnfold A.read
$ IP.arraysOf 240
$ S.fromList list
assert (xs == list)
lastN :: Int -> [a] -> [a]
lastN n l = drop (length l - n) l
testLastN :: Property
testLastN =
forAll (choose (0, maxArrLen)) $ \len ->
forAll (choose (0, len)) $ \n ->
forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
monadicIO $ do
xs <- fmap A.toList
$ S.fold (A.lastN n)
$ S.fromList list
assert (xs == lastN n list)
#endif
main :: IO ()
main =
hspec $
H.parallel $
modifyMaxSuccess (const maxTestCount) $ do
describe "Construction" $ do
prop "length . writeN n === n" testLength
prop "length . fromStreamN n === n" testLengthFromStreamN
prop "read . writeN === id " testFoldNUnfold
prop "toStream . writeN === id" testFoldNToStream
prop "toStreamRev . writeN === reverse" testFoldNToStreamRev
prop "read . fromStreamN === id" testFromStreamNUnfold
prop "toStream . fromStreamN === id" testFromStreamNToStream
#ifndef TEST_SMALL_ARRAY
prop "length . fromStream === n" testLengthFromStream
prop "toStream . fromStream === id" testFromStreamToStream
prop "read . write === id" testFoldUnfold
#endif
#ifdef TEST_ARRAY
prop "arraysOf concats to original" testArraysOf
#endif
#ifdef TEST_ARRAY
describe "Fold" $ do
prop "lastN" $ testLastN
#endif