3-- Copyright : (c) 2019 Composewell Technologies
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
11-- This is a common array test module that gets included in different
12-- Array test modules with the corresponding macro defined.
14import Foreign.Storable (Storable(..))
16import Test.Hspec.QuickCheck
17import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
18import Test.QuickCheck.Monadic (monadicIO, assert, run)
21import Streamly.Prelude (SerialT)
22import Streamly.Test.Common (listEquals)
24import qualified Streamly.Prelude as S
25#ifdef TEST_SMALL_ARRAY
26import qualified Streamly.Internal.Data.SmallArray as A
27type Array = A.SmallArray
28#elif defined(TEST_ARRAY)
29import Data.Word(Word8)
31import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
32import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
33import qualified Streamly.Internal.Data.Stream.IsStream as IP
34import qualified Streamly.Internal.Memory.ArrayStream as AS
36#elif defined(DATA_ARRAY_PRIM_PINNED)
37import qualified Streamly.Internal.Data.Array.Prim.Pinned as A
38import qualified Streamly.Internal.Data.Array.Prim.Pinned.Types as A
39import qualified Streamly.Internal.Data.Stream.IsStream as IP
41#elif defined(DATA_ARRAY_PRIM)
42import qualified Streamly.Internal.Data.Array.Prim as A
43import qualified Streamly.Internal.Data.Array.Prim.Types as A
44import qualified Streamly.Internal.Data.Stream.IsStream as IP
47import qualified Streamly.Internal.Data.Array as A
51-- Coverage build takes too long with default number of tests
60allocOverhead = 2 * sizeOf (undefined :: Int)
62-- XXX this should be in sync with the defaultChunkSize in Array code, or we
63-- should expose that and use that. For fast testing we could reduce the
64-- defaultChunkSize under CPP conditionals.
66defaultChunkSize :: Int
67defaultChunkSize = 32 * k - allocOverhead
71maxArrLen = defaultChunkSize * 8
74 (Int -> SerialT IO Int -> IO (Array Int))
76genericTestFrom arrFold =
77 forAll (choose (0, maxArrLen)) $ \len ->
78 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
80 arr <- run $ arrFold len $ S.fromList list
81 assert (A.length arr == len)
84testLength = genericTestFrom (\n -> S.fold (A.writeN n))
86testLengthFromStreamN :: Property
87testLengthFromStreamN = genericTestFrom A.fromStreamN
89#ifndef TEST_SMALL_ARRAY
90testLengthFromStream :: Property
91testLengthFromStream = genericTestFrom (const A.fromStream)
95 (Int -> SerialT IO Int -> IO (Array Int))
96 -> (Array Int -> SerialT IO Int)
97 -> ([Int] -> [Int] -> Bool)
99genericTestFromTo arrFold arrUnfold listEq =
100 forAll (choose (0, maxArrLen)) $ \len ->
101 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
103 arr <- run $ arrFold len $ S.fromList list
104 xs <- run $ S.toList $ arrUnfold arr
105 assert (listEq xs list)
107testFoldNUnfold :: Property
109 genericTestFromTo (\n -> S.fold (A.writeN n)) (S.unfold A.read) (==)
111testFoldNToStream :: Property
113 genericTestFromTo (\n -> S.fold (A.writeN n)) A.toStream (==)
115testFoldNToStreamRev :: Property
116testFoldNToStreamRev =
118 (\n -> S.fold (A.writeN n))
120 (\xs list -> xs == reverse list)
122testFromStreamNUnfold :: Property
123testFromStreamNUnfold = genericTestFromTo A.fromStreamN (S.unfold A.read) (==)
125testFromStreamNToStream :: Property
126testFromStreamNToStream = genericTestFromTo A.fromStreamN A.toStream (==)
128testFromListN :: Property
130 forAll (choose (0, maxArrLen)) $ \len ->
131 forAll (choose (0, len)) $ \n ->
132 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
134 let arr = A.fromListN n list
135 xs <- run $ S.toList $ (S.unfold A.read) arr
136 listEquals (==) xs (take n list)
138#ifndef TEST_SMALL_ARRAY
139testFromStreamToStream :: Property
140testFromStreamToStream = genericTestFromTo (const A.fromStream) A.toStream (==)
142testFoldUnfold :: Property
143testFoldUnfold = genericTestFromTo (const (S.fold A.write)) (S.unfold A.read) (==)
145testFromList :: Property
147 forAll (choose (0, maxArrLen)) $ \len ->
148 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
150 let arr = A.fromList list
151 xs <- run $ S.toList $ (S.unfold A.read) arr
155#if defined(TEST_ARRAY) ||\
156 defined(DATA_ARRAY_PRIM) ||\
157 defined(DATA_ARRAY_PRIM_PINNED)
159testArraysOf :: Property
161 forAll (choose (0, maxArrLen)) $ \len ->
162 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
166 $ S.concatUnfold A.read
171 arraysOf n = IP.chunksOf n (A.writeNUnsafe n)
177lastN :: Int -> [a] -> [a]
178lastN n l = drop (length l - n) l
182 forAll (choose (0, maxArrLen)) $ \len ->
183 forAll (choose (0, len)) $ \n ->
184 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
190 assert (xs == lastN n list)
192testLastN_LN :: Int -> Int -> IO Bool
193testLastN_LN len n = do
195 l1 <- fmap A.toList $ S.fold (A.lastN n) $ S.fromList list
196 let l2 = lastN n list
199-- Instead of hard coding 10000 here we can have maxStreamLength for operations
200-- that use stream of arrays.
201concatArrayW8 :: Property
203 forAll (vectorOf 10000 (arbitrary :: Gen Word8))
205 let w8ArrList = A.fromList . (: []) <$> w8List
206 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
215 modifyMaxSuccess (const maxTestCount) $ do
216 describe "Construction" $ do
217 prop "length . writeN n === n" testLength
218 prop "length . fromStreamN n === n" testLengthFromStreamN
219 prop "read . writeN === id " testFoldNUnfold
220 prop "toStream . writeN === id" testFoldNToStream
221 prop "toStreamRev . writeN === reverse" testFoldNToStreamRev
222 prop "read . fromStreamN === id" testFromStreamNUnfold
223 prop "toStream . fromStreamN === id" testFromStreamNToStream
224 prop "fromListN" testFromListN
226#ifndef TEST_SMALL_ARRAY
227 prop "length . fromStream === n" testLengthFromStream
228 prop "toStream . fromStream === id" testFromStreamToStream
229 prop "read . write === id" testFoldUnfold
230 prop "fromList" testFromList
233#if defined(TEST_ARRAY) ||\
234 defined(DATA_ARRAY_PRIM) ||\
235 defined(DATA_ARRAY_PRIM_PINNED)
236 prop "arraysOf concats to original" testArraysOf
240 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
242 prop "lastN : 0 <= n <= len" $ testLastN
243 describe "lastN boundary conditions" $ do
244 it "lastN -1" (testLastN_LN 10 (-1) `shouldReturn` True)
245 it "lastN 0" (testLastN_LN 10 0 `shouldReturn` True)
246 it "lastN length" (testLastN_LN 10 10 `shouldReturn` True)
247 it "lastN (length + 1)" (testLastN_LN 10 11 `shouldReturn` True)
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