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.
14-- Meanings of CPP macros:
15-- Default => Data.Array
16-- TEST_ARRAY => Data.Array.Foreign
17-- TEST_SMALL_ARRAY => Data.SmallArray
18-- DATA_ARRAY_PRIM => Data.Array.Prim
19-- DATA_ARRAY_PRIM_PINNED => Data.Array.Prim.Pinned
21import Foreign.Storable (Storable(..))
23import Test.Hspec.QuickCheck
24import Test.QuickCheck (Property, forAll, Gen, vectorOf, arbitrary, choose)
25import Test.QuickCheck.Monadic (monadicIO, assert, run)
28import Streamly.Data.Fold (Fold)
29import Streamly.Prelude (SerialT)
30import Streamly.Test.Common (listEquals)
32import qualified Streamly.Prelude as S
34#if defined(TEST_ARRAY) ||\
35 defined(DATA_ARRAY_PRIM) ||\
36 defined(DATA_ARRAY_PRIM_PINNED)
37import qualified Streamly.Internal.Data.Fold as Fold
40#ifdef TEST_SMALL_ARRAY
41import qualified Streamly.Internal.Data.SmallArray as A
42type Array = A.SmallArray
43#elif defined(TEST_ARRAY)
44import Data.Word(Word8)
46import qualified Streamly.Internal.Data.Array.Foreign as A
47import qualified Streamly.Internal.Data.Array.Foreign.Type as A
48import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
49import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
51#elif defined(DATA_ARRAY_PRIM_PINNED)
52import qualified Streamly.Internal.Data.Array.Prim.Pinned as A
53import qualified Streamly.Internal.Data.Array.Prim.Pinned.Type as A
55#elif defined(DATA_ARRAY_PRIM)
56import qualified Streamly.Internal.Data.Array.Prim as A
57import qualified Streamly.Internal.Data.Array.Prim.Type as A
60import qualified Streamly.Internal.Data.Array as A
65#ifdef TEST_SMALL_ARRAY
66moduleName = "Data.SmallArray"
67#elif defined(TEST_ARRAY)
68moduleName = "Data.Array.Foreign"
69#elif defined(DATA_ARRAY_PRIM_PINNED)
70moduleName = "Data.Array.Prim.Pinned"
71#elif defined(DATA_ARRAY_PRIM)
72moduleName = "Data.Array.Prim"
74moduleName = "Data.Array"
77-- Coverage build takes too long with default number of tests
86allocOverhead = 2 * sizeOf (undefined :: Int)
88-- XXX this should be in sync with the defaultChunkSize in Array code, or we
89-- should expose that and use that. For fast testing we could reduce the
90-- defaultChunkSize under CPP conditionals.
92defaultChunkSize :: Int
93defaultChunkSize = 32 * k - allocOverhead
97maxArrLen = defaultChunkSize * 8
100 (Int -> SerialT IO Int -> IO (Array Int))
102genericTestFrom arrFold =
103 forAll (choose (0, maxArrLen)) $ \len ->
104 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
106 arr <- run $ arrFold len $ S.fromList list
107 assert (A.length arr == len)
109testLength :: Property
110testLength = genericTestFrom (\n -> S.fold (A.writeN n))
112testLengthFromStreamN :: Property
113testLengthFromStreamN = genericTestFrom A.fromStreamN
115#ifndef TEST_SMALL_ARRAY
116testLengthFromStream :: Property
117testLengthFromStream = genericTestFrom (const A.fromStream)
121 (Int -> SerialT IO Int -> IO (Array Int))
122 -> (Array Int -> SerialT IO Int)
123 -> ([Int] -> [Int] -> Bool)
125genericTestFromTo arrFold arrUnfold listEq =
126 forAll (choose (0, maxArrLen)) $ \len ->
127 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
129 arr <- run $ arrFold len $ S.fromList list
130 xs <- run $ S.toList $ arrUnfold arr
131 assert (listEq xs list)
133testFoldNUnfold :: Property
135 genericTestFromTo (\n -> S.fold (A.writeN n)) (S.unfold A.read) (==)
137testFoldNToStream :: Property
139 genericTestFromTo (\n -> S.fold (A.writeN n)) A.toStream (==)
141testFoldNToStreamRev :: Property
142testFoldNToStreamRev =
144 (\n -> S.fold (A.writeN n))
146 (\xs list -> xs == reverse list)
148testFromStreamNUnfold :: Property
149testFromStreamNUnfold = genericTestFromTo A.fromStreamN (S.unfold A.read) (==)
151testFromStreamNToStream :: Property
152testFromStreamNToStream = genericTestFromTo A.fromStreamN A.toStream (==)
154testFromListN :: Property
156 forAll (choose (0, maxArrLen)) $ \len ->
157 forAll (choose (0, len)) $ \n ->
158 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
160 let arr = A.fromListN n list
161 xs <- run $ S.toList $ (S.unfold A.read) arr
162 listEquals (==) xs (take n list)
164#ifndef TEST_SMALL_ARRAY
165testFromStreamToStream :: Property
166testFromStreamToStream = genericTestFromTo (const A.fromStream) A.toStream (==)
168testFoldUnfold :: Property
169testFoldUnfold = genericTestFromTo (const (S.fold A.write)) (S.unfold A.read) (==)
171testFromList :: Property
173 forAll (choose (0, maxArrLen)) $ \len ->
174 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
176 let arr = A.fromList list
177 xs <- run $ S.toList $ (S.unfold A.read) arr
181foldManyWith :: (Int -> Fold IO Int (Array Int)) -> Property
183 forAll (choose (0, maxArrLen)) $ \len ->
184 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
188 $ S.unfoldMany A.read
195unsafeWriteIndex :: [Int] -> Int -> Int -> IO Bool
196unsafeWriteIndex xs i x = do
197 arr <- MA.fromList xs
198 MA.putIndexUnsafe arr i x
199 x1 <- MA.getIndexUnsafe arr i
202lastN :: Int -> [a] -> [a]
203lastN n l = drop (length l - n) l
207 forAll (choose (0, maxArrLen)) $ \len ->
208 forAll (choose (0, len)) $ \n ->
209 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
213 $ S.fold (A.writeLastN n)
215 assert (xs == lastN n list)
217testLastN_LN :: Int -> Int -> IO Bool
218testLastN_LN len n = do
220 l1 <- fmap A.toList $ S.fold (A.writeLastN n) $ S.fromList list
221 let l2 = lastN n list
224-- Instead of hard coding 10000 here we can have maxStreamLength for operations
225-- that use stream of arrays.
226concatArrayW8 :: Property
228 forAll (vectorOf 10000 (arbitrary :: Gen Word8))
230 let w8ArrList = A.fromList . (: []) <$> w8List
231 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
234unsafeSlice :: Int -> Int -> [Int] -> Bool
235unsafeSlice i n list =
236 let lst = take n $ drop i $ list
237 arr = A.toList $ A.getSliceUnsafe i n $ A.fromList list
246 modifyMaxSuccess (const maxTestCount) $ do
247 describe moduleName $ do
248 describe "Construction" $ do
249 prop "length . writeN n === n" testLength
250 prop "length . fromStreamN n === n" testLengthFromStreamN
251 prop "read . writeN === id " testFoldNUnfold
252 prop "toStream . writeN === id" testFoldNToStream
253 prop "toStreamRev . writeN === reverse" testFoldNToStreamRev
254 prop "read . fromStreamN === id" testFromStreamNUnfold
255 prop "toStream . fromStreamN === id" testFromStreamNToStream
256 prop "fromListN" testFromListN
258#ifndef TEST_SMALL_ARRAY
259 prop "length . fromStream === n" testLengthFromStream
260 prop "toStream . fromStream === id" testFromStreamToStream
261 prop "read . write === id" testFoldUnfold
262 prop "fromList" testFromList
265#if defined(TEST_ARRAY) ||\
266 defined(DATA_ARRAY_PRIM) ||\
267 defined(DATA_ARRAY_PRIM_PINNED)
268 prop "foldMany with writeNUnsafe concats to original"
269 (foldManyWith (\n -> Fold.take n (A.writeNUnsafe n)))
271 prop "foldMany with writeN concats to original"
272 (foldManyWith A.writeN)
275 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
276 describe "unsafeSlice" $ do
277 it "partial" $ unsafeSlice 2 4 [1..10]
278 it "none" $ unsafeSlice 10 0 [1..10]
279 it "full" $ unsafeSlice 0 10 [1..10]
280 describe "Mut.unsafeWriteIndex" $ do
281 it "first" (unsafeWriteIndex [1..10] 0 0 `shouldReturn` True)
282 it "middle" (unsafeWriteIndex [1..10] 5 0 `shouldReturn` True)
283 it "last" (unsafeWriteIndex [1..10] 9 0 `shouldReturn` True)
285 prop "writeLastN : 0 <= n <= len" $ testLastN
286 describe "writeLastN boundary conditions" $ do
287 it "writeLastN -1" (testLastN_LN 10 (-1) `shouldReturn` True)
288 it "writeLastN 0" (testLastN_LN 10 0 `shouldReturn` True)
289 it "writeLastN length" (testLastN_LN 10 10 `shouldReturn` True)
290 it "writeLastN (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