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.Foreign as A
32import qualified Streamly.Internal.Data.Array.Foreign.Type as A
33import qualified Streamly.Internal.Data.Stream.IsStream as IP
34import qualified Streamly.Internal.Data.Array.Stream.Foreign 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.Type 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.Type as A
44import qualified Streamly.Internal.Data.Stream.IsStream as IP
47import qualified Streamly.Internal.Data.Array as A
52#ifdef TEST_SMALL_ARRAY
53moduleName = "Data.SmallArray"
54#elif defined(TEST_ARRAY)
55moduleName = "Data.Array.Foreign"
56#elif defined(DATA_ARRAY_PRIM_PINNED)
57moduleName = "Data.Array.Prim.Pinned"
58#elif defined(DATA_ARRAY_PRIM)
59moduleName = "Data.Array.Prim"
61moduleName = "Data.Array"
64-- Coverage build takes too long with default number of tests
73allocOverhead = 2 * sizeOf (undefined :: Int)
75-- XXX this should be in sync with the defaultChunkSize in Array code, or we
76-- should expose that and use that. For fast testing we could reduce the
77-- defaultChunkSize under CPP conditionals.
79defaultChunkSize :: Int
80defaultChunkSize = 32 * k - allocOverhead
84maxArrLen = defaultChunkSize * 8
87 (Int -> SerialT IO Int -> IO (Array Int))
89genericTestFrom arrFold =
90 forAll (choose (0, maxArrLen)) $ \len ->
91 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
93 arr <- run $ arrFold len $ S.fromList list
94 assert (A.length arr == len)
97testLength = genericTestFrom (\n -> S.fold (A.writeN n))
99testLengthFromStreamN :: Property
100testLengthFromStreamN = genericTestFrom A.fromStreamN
102#ifndef TEST_SMALL_ARRAY
103testLengthFromStream :: Property
104testLengthFromStream = genericTestFrom (const A.fromStream)
108 (Int -> SerialT IO Int -> IO (Array Int))
109 -> (Array Int -> SerialT IO Int)
110 -> ([Int] -> [Int] -> Bool)
112genericTestFromTo arrFold arrUnfold listEq =
113 forAll (choose (0, maxArrLen)) $ \len ->
114 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
116 arr <- run $ arrFold len $ S.fromList list
117 xs <- run $ S.toList $ arrUnfold arr
118 assert (listEq xs list)
120testFoldNUnfold :: Property
122 genericTestFromTo (\n -> S.fold (A.writeN n)) (S.unfold A.read) (==)
124testFoldNToStream :: Property
126 genericTestFromTo (\n -> S.fold (A.writeN n)) A.toStream (==)
128testFoldNToStreamRev :: Property
129testFoldNToStreamRev =
131 (\n -> S.fold (A.writeN n))
133 (\xs list -> xs == reverse list)
135testFromStreamNUnfold :: Property
136testFromStreamNUnfold = genericTestFromTo A.fromStreamN (S.unfold A.read) (==)
138testFromStreamNToStream :: Property
139testFromStreamNToStream = genericTestFromTo A.fromStreamN A.toStream (==)
141testFromListN :: Property
143 forAll (choose (0, maxArrLen)) $ \len ->
144 forAll (choose (0, len)) $ \n ->
145 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
147 let arr = A.fromListN n list
148 xs <- run $ S.toList $ (S.unfold A.read) arr
149 listEquals (==) xs (take n list)
151#ifndef TEST_SMALL_ARRAY
152testFromStreamToStream :: Property
153testFromStreamToStream = genericTestFromTo (const A.fromStream) A.toStream (==)
155testFoldUnfold :: Property
156testFoldUnfold = genericTestFromTo (const (S.fold A.write)) (S.unfold A.read) (==)
158testFromList :: Property
160 forAll (choose (0, maxArrLen)) $ \len ->
161 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
163 let arr = A.fromList list
164 xs <- run $ S.toList $ (S.unfold A.read) arr
168#if defined(TEST_ARRAY) ||\
169 defined(DATA_ARRAY_PRIM) ||\
170 defined(DATA_ARRAY_PRIM_PINNED)
172testArraysOf :: Property
174 forAll (choose (0, maxArrLen)) $ \len ->
175 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
179 $ S.unfoldMany A.read
184 arraysOf n = IP.chunksOf n (A.writeNUnsafe n)
190lastN :: Int -> [a] -> [a]
191lastN n l = drop (length l - n) l
195 forAll (choose (0, maxArrLen)) $ \len ->
196 forAll (choose (0, len)) $ \n ->
197 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
203 assert (xs == lastN n list)
205testLastN_LN :: Int -> Int -> IO Bool
206testLastN_LN len n = do
208 l1 <- fmap A.toList $ S.fold (A.lastN n) $ S.fromList list
209 let l2 = lastN n list
212-- Instead of hard coding 10000 here we can have maxStreamLength for operations
213-- that use stream of arrays.
214concatArrayW8 :: Property
216 forAll (vectorOf 10000 (arbitrary :: Gen Word8))
218 let w8ArrList = A.fromList . (: []) <$> w8List
219 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
228 modifyMaxSuccess (const maxTestCount) $ do
229 describe moduleName $ do
230 describe "Construction" $ do
231 prop "length . writeN n === n" testLength
232 prop "length . fromStreamN n === n" testLengthFromStreamN
233 prop "read . writeN === id " testFoldNUnfold
234 prop "toStream . writeN === id" testFoldNToStream
235 prop "toStreamRev . writeN === reverse" testFoldNToStreamRev
236 prop "read . fromStreamN === id" testFromStreamNUnfold
237 prop "toStream . fromStreamN === id" testFromStreamNToStream
238 prop "fromListN" testFromListN
240#ifndef TEST_SMALL_ARRAY
241 prop "length . fromStream === n" testLengthFromStream
242 prop "toStream . fromStream === id" testFromStreamToStream
243 prop "read . write === id" testFoldUnfold
244 prop "fromList" testFromList
247#if defined(TEST_ARRAY) ||\
248 defined(DATA_ARRAY_PRIM) ||\
249 defined(DATA_ARRAY_PRIM_PINNED)
250 prop "arraysOf concats to original" testArraysOf
254 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
256 prop "lastN : 0 <= n <= len" $ testLastN
257 describe "lastN boundary conditions" $ do
258 it "lastN -1" (testLastN_LN 10 (-1) `shouldReturn` True)
259 it "lastN 0" (testLastN_LN 10 0 `shouldReturn` True)
260 it "lastN length" (testLastN_LN 10 10 `shouldReturn` True)
261 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