2-- Module : Streamly.Test.Data.Array.Foreign
3-- Copyright : (c) 2019 Composewell technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
9module Streamly.Test.Data.Array.Foreign (main) where
11#include "Streamly/Test/Data/Array/CommonImports.hs"
13import Data.Char (isLower)
14import Data.List (sort)
15import Data.Word(Word8)
16import Test.QuickCheck (chooseInt, listOf)
17import Streamly.Internal.Data.Unboxed (Storable, alignment, peek, poke)
18import GHC.Ptr (plusPtr)
19import Foreign.ForeignPtr (withForeignPtr)
21import qualified Streamly.Internal.Data.Fold as Fold
22import qualified Streamly.Internal.Data.Array.Foreign as A
23import qualified Streamly.Internal.Data.Array.Foreign.Type as A
24import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
25import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
26import qualified Streamly.Internal.Foreign.Malloc as Malloc
31moduleName = "Data.Array.Foreign"
33#include "Streamly/Test/Data/Array/Common.hs"
35testFromStreamToStream :: Property
36testFromStreamToStream = genericTestFromTo (const A.fromStream) A.toStream (==)
38testFoldUnfold :: Property
39testFoldUnfold = genericTestFromTo (const (S.fold A.write)) (S.unfold A.read) (==)
41testFromList :: Property
43 forAll (choose (0, maxArrLen)) $ \len ->
44 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
46 let arr = A.fromList list
47 xs <- run $ S.toList $ (S.unfold A.read) arr
50testLengthFromStream :: Property
51testLengthFromStream = genericTestFrom (const A.fromStream)
54unsafeWriteIndex :: [Int] -> Int -> Int -> IO Bool
55unsafeWriteIndex xs i x = do
57 MA.putIndexUnsafe i x arr
58 x1 <- MA.getIndexUnsafe i arr
61lastN :: Int -> [a] -> [a]
62lastN n l = drop (length l - n) l
66 forAll (choose (0, maxArrLen)) $ \len ->
67 forAll (choose (0, len)) $ \n ->
68 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
72 $ S.fold (A.writeLastN n)
74 assert (xs == lastN n list)
76testLastN_LN :: Int -> Int -> IO Bool
77testLastN_LN len n = do
79 l1 <- fmap A.toList $ S.fold (A.writeLastN n) $ S.fromList list
85 dt <- MA.fromList "abcDEFgeh"
86 dt' <- MA.strip isLower dt
90testStripLeft :: IO Bool
92 dt <- MA.fromList "abcDEF"
93 dt' <- MA.strip isLower dt
97testStripRight :: IO Bool
99 dt <- MA.fromList "DEFgeh"
100 dt' <- MA.strip isLower dt
104testStripZero :: IO Bool
106 dt <- MA.fromList "DEF"
107 dt' <- MA.strip isLower dt
111testStripEmpty :: IO Bool
113 dt <- MA.fromList "abc"
114 dt' <- MA.strip isLower dt
118testStripNull :: IO Bool
121 dt' <- MA.strip isLower dt
125-- Instead of hard coding 10000 here we can have maxStreamLength for operations
126-- that use stream of arrays.
127concatArrayW8 :: Property
129 forAll (vectorOf 10000 (arbitrary :: Gen Word8))
131 let w8ArrList = A.fromList . (: []) <$> w8List
132 f2 <- S.toList $ AS.concat $ S.fromList w8ArrList
135unsafeSlice :: Int -> Int -> [Int] -> Bool
136unsafeSlice i n list =
137 let lst = take n $ drop i $ list
138 arr = A.toList $ A.getSliceUnsafe i n $ A.fromList list
142testAppend :: Property
144 forAll (listOf (chooseInt (-50, 100))) $ \ls0 ->
145 monadicIO $ action ls0
151 (MA.append (MA.newArray 0))
152 (S.fromList (ls::[Int]))
157testBubbleWith :: Bool -> Property
159 forAll (listOf (chooseInt (-50, 100))) $ \ls0 ->
160 monadicIO $ action ls0
165 x <- S.fold (fldm ls) $ S.fromList ls
168 then assert (sort ls == lst)
169 else assert (sort ls == reverse lst)
176 then MA.bubble compare arr
177 else MA.bubble (flip compare) arr
180 (MA.newArray $ length ls)
182testBubbleAsc :: Property
183testBubbleAsc = testBubbleWith True
185testBubbleDesc :: Property
186testBubbleDesc = testBubbleWith False
188testByteLengthWithMA :: forall a. Storable a => a -> IO ()
189testByteLengthWithMA _ = do
190 arrA <- MA.newArray 100 :: IO (MA.Array a)
191 let arrW8 = MA.castUnsafe arrA :: MA.Array Word8
192 MA.byteLength arrA `shouldBe` MA.length arrW8
194testBreakOn :: [Word8] -> Word8 -> [Word8] -> (Maybe [Word8]) -> IO ()
195testBreakOn inp sep bef aft = do
196 (bef_, aft_) <- A.breakOn sep (A.fromList inp)
197 bef_ `shouldBe` A.fromList bef
198 aft_ `shouldBe` fmap A.fromList aft
200testWrite :: [Char] -> IO ()
202 arr <- S.fold A.write (S.fromList inp)
203 A.toList arr `shouldBe` inp
205testFromToList :: [Char] -> IO ()
206testFromToList inp = A.toList (A.fromList inp) `shouldBe` inp
208testUnsafeIndxedFromList :: [Char] -> IO ()
209testUnsafeIndxedFromList inp =
210 let arr = A.fromList inp
211 in fmap (flip A.unsafeIndex arr) [0 .. (length inp - 1)] `shouldBe` inp
213testFromForeignPtrUnsafeMA :: IO ()
214testFromForeignPtrUnsafeMA = do
215 fp <- Malloc.mallocForeignPtrAlignedBytes numBytes alignmentInt
217 withForeignPtr fp $ \p -> do
218 writeNext (0 :: Int) p
220 $ MA.fromForeignPtrUnsafe
222 (p `plusPtr` numBytes)
223 (p `plusPtr` numBytes)
224 MA.toList arr `shouldReturn` [0..99]
228 sizeOfInt = sizeOf (undefined :: Int)
229 alignmentInt = alignment (undefined :: Int)
230 numBytes = sizeOfInt * 100
232 | i >= 100 = return ()
233 writeNext i p = poke p i >> writeNext (i + 1) (p `plusPtr` sizeOfInt)
235testAsPtrUnsafeMA :: IO ()
236testAsPtrUnsafeMA = do
237 arr <- MA.fromList ([0 .. 99] :: [Int])
238 MA.asPtrUnsafe arr (getList (0 :: Int)) `shouldReturn` [0 .. 99]
242 sizeOfInt = sizeOf (undefined :: Int)
245 | i >= 100 = return []
248 rest <- getList (i + 1) (p `plusPtr` sizeOfInt)
254 bSize = len * sizeOf (undefined :: Char)
255 in forAll (vectorOf len (arbitrary :: Gen Char)) $ \vec ->
256 forAll (chooseInt (bSize - 2000, bSize + 2000)) $ \newBLen -> do
257 arr <- MA.fromList vec
258 arr1 <- MA.realloc newBLen arr
260 lst1 <- MA.toList arr1
267 modifyMaxSuccess (const maxTestCount) $ do
268 describe moduleName $ do
270 describe "Construction" $ do
271 -- XXX There is an issue https://github.com/composewell/streamly/issues/1577
272 --prop "testAppend" testAppend
273 prop "testBubbleAsc" testBubbleAsc
274 prop "testBubbleDesc" testBubbleDesc
275 prop "length . fromStream === n" testLengthFromStream
276 prop "toStream . fromStream === id" testFromStreamToStream
277 prop "read . write === id" testFoldUnfold
278 prop "fromList" testFromList
279 prop "foldMany with writeNUnsafe concats to original"
280 (foldManyWith (\n -> Fold.take n (A.writeNUnsafe n)))
281 prop "AS.concat . (A.fromList . (:[]) <$>) === id" $ concatArrayW8
282 describe "unsafeSlice" $ do
283 it "partial" $ unsafeSlice 2 4 [1..10]
284 it "none" $ unsafeSlice 10 0 [1..10]
285 it "full" $ unsafeSlice 0 10 [1..10]
286 describe "Mut.unsafeWriteIndex" $ do
287 it "first" (unsafeWriteIndex [1..10] 0 0 `shouldReturn` True)
288 it "middle" (unsafeWriteIndex [1..10] 5 0 `shouldReturn` True)
289 it "last" (unsafeWriteIndex [1..10] 9 0 `shouldReturn` True)
291 prop "writeLastN : 0 <= n <= len" $ testLastN
292 describe "writeLastN boundary conditions" $ do
293 it "writeLastN -1" (testLastN_LN 10 (-1) `shouldReturn` True)
294 it "writeLastN 0" (testLastN_LN 10 0 `shouldReturn` True)
295 it "writeLastN length" (testLastN_LN 10 10 `shouldReturn` True)
296 it "writeLastN (length + 1)" (testLastN_LN 10 11 `shouldReturn` True)
297 describe "Strip" $ do
298 it "strip" (testStrip `shouldReturn` True)
299 it "stripLeft" (testStripLeft `shouldReturn` True)
300 it "stripRight" (testStripRight `shouldReturn` True)
301 it "stripZero" (testStripZero `shouldReturn` True)
302 it "stripEmpty" (testStripEmpty `shouldReturn` True)
303 it "stripNull" (testStripNull `shouldReturn` True)
305 it "testByteLengthWithMA Int"
306 (testByteLengthWithMA (undefined :: Int))
307 it "testByteLengthWithMA Char"
308 (testByteLengthWithMA (undefined :: Char))
309 it "testFromForeignPtrUnsafeMA" testFromForeignPtrUnsafeMA
310 it "testAsPtrUnsafeMA" testAsPtrUnsafeMA
311 it "reallocMA" reallocMA
312 describe "breakOn" $ do
313 it "testBreakOn [1, 0, 2] 0"
314 (testBreakOn [1, 0, 2] 0 [1] (Just [2]))
315 it "testBreakOn [1, 0] 0" (testBreakOn [1, 0] 0 [1] (Just []))
316 it "testBreakOn [1] 0" (testBreakOn [1] 0 [1] Nothing)
317 describe "toList . fromList" $ do
318 it "testFromToList abc" (testFromToList "abc")
319 it "testFromToList \\22407" (testFromToList "\22407")
320 describe "unsafeIndex . fromList" $ do
321 it "testUnsafeIndxedFromList abc" (testUnsafeIndxedFromList "abc")
322 it "testUnsafeIndxedFromList \\22407"
323 (testUnsafeIndxedFromList "\22407")
324 describe "write" $ do
325 it "testWrite abc" (testWrite "abc")
326 it "testWrite \\22407" (testWrite "\22407")
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