2-- Module : Streamly.Test.FileSystem.Handle
3-- Copyright : (c) 2020 Composewell technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
9module Streamly.Test.FileSystem.Handle (main) where
11import Data.Functor.Identity (runIdentity)
12import Data.Word (Word8)
13import Streamly.Internal.Data.Stream (Stream)
14import Streamly.Internal.System.IO (defaultChunkSize)
15import System.FilePath ((</>))
25import System.IO.Temp (withSystemTempDirectory)
26import Test.QuickCheck (Property, forAll, Gen, vectorOf, choose)
27import Test.QuickCheck.Monadic (monadicIO, assert, run)
29import qualified Streamly.Data.Fold as Fold
30import qualified Streamly.Internal.FileSystem.Handle as Handle
31import qualified Streamly.Internal.Data.Stream as Stream
32import qualified Streamly.Internal.Data.Array as Array
33import qualified Streamly.Internal.Unicode.Stream as Unicode
36import Test.Hspec.QuickCheck
39maxArrLen = defaultChunkSize * 8
44chooseWord8 :: (Word8, Word8) -> Gen Word8
47toList :: Monad m => Stream m a -> m [a]
48toList = Stream.fold Fold.toList
50utf8ToString :: Array.Array Word8 -> String
52 runIdentity . toList . Unicode.decodeUtf8' . Array.read
55testData = "This is the test data for FileSystem.Handle ??`!@#$%^&*~~))`]"
57testDataLarge :: String
58testDataLarge = concat $ replicate 6000 testData
61testBinData = "01234567890123456789012345678901234567890123456789"
63executor :: (Handle -> Stream IO Char) -> IO (Stream IO Char)
65 withSystemTempDirectory "fs_handle" $ \fp -> do
66 let fpath = fp </> "tmp_read.txt"
67 writeFile fpath testDataLarge
68 h <- openFile fpath ReadMode
71readFromHandle :: IO (Stream IO Char)
73 let f = Unicode.decodeUtf8 . Stream.unfold Handle.reader
76readWithBufferFromHandle :: IO (Stream IO Char)
77readWithBufferFromHandle =
79 f2 = Unicode.decodeUtf8 . Stream.unfold Handle.readerWith . f1
82readChunksFromHandle :: IO (Stream IO Char)
84 let f = Unicode.decodeUtf8
85 . Stream.concatMap Array.read
86 . Stream.unfold Handle.chunkReader
89readChunksWithBuffer :: IO (Stream IO Char)
94 . Stream.concatMap Array.read
95 . Stream.unfold Handle.chunkReaderWith
99testRead :: IO (Stream IO Char) -> Property
100testRead fn = monadicIO $ do
101 let v2 = Stream.fromList testDataLarge
103 res <- run $ Stream.eqBy (==) v1 v2
106testWrite :: (Handle -> Fold.Fold IO Word8 ()) -> Property
108 forAll (choose (0, maxArrLen)) $ \len ->
109 forAll (vectorOf len $ chooseWord8 (0, 255)) $ \list0 ->
111 res <- run $ go list0
117 withSystemTempDirectory "fs_handle" $ \fp -> do
118 let fpathWrite = fp </> "tmp_write.txt"
119 writeFile fpathWrite ""
120 h <- openFile fpathWrite ReadWriteMode
121 hSeek h AbsoluteSeek 0
122 _ <- Stream.fold (hfold h) $ Stream.fromList list
124 hSeek h AbsoluteSeek 0
125 ls <- toList $ Stream.unfold Handle.reader h
129testWriteWithChunk :: Property
138 withSystemTempDirectory "fs_handle" $ \fp -> do
139 let fpathRead = fp </> "tmp_read.txt"
140 fpathWrite = fp </> "tmp_write.txt"
141 writeFile fpathRead testDataLarge
142 writeFile fpathWrite ""
143 hr <- openFile fpathRead ReadMode
144 hw <- openFile fpathWrite ReadWriteMode
145 hSeek hw AbsoluteSeek 0
146 _ <- Stream.fold (Handle.writeChunks hw)
147 $ Stream.unfold Handle.chunkReaderWith (1024, hr)
149 hSeek hw AbsoluteSeek 0
150 ls <- toList $ Stream.unfold Handle.reader hw
151 let arr = Array.fromList ls
152 return (testDataLarge == utf8ToString arr)
154testReadChunksFromToWith :: Int -> Int -> Int -> [[Word8]] -> Property
155testReadChunksFromToWith from to buffSize res = monadicIO $ run go
160 withSystemTempDirectory "fs_handle" $ \fp -> do
161 let fpathRead = fp </> "tmp_read.txt"
162 writeFile fpathRead testBinData
163 h <- openFile fpathRead ReadMode
167 Handle.chunkReaderFromToWith (from, to, buffSize, h)
168 return (res `shouldBe` fmap Array.toList ls)
170-- Test for first byte
171testReadChunksFromToWithFirstByte :: Property
172testReadChunksFromToWithFirstByte = testReadChunksFromToWith 0 0 15 [[48]]
174-- Test for second byte
175testReadChunksFromToWithSecondByte :: Property
176testReadChunksFromToWithSecondByte = testReadChunksFromToWith 1 1 15 [[49]]
178-- Test for second to 10th bytes
179testReadChunksFromToWithSecondToTenthBytes :: Property
180testReadChunksFromToWithSecondToTenthBytes =
181 testReadChunksFromToWith 1 10 15 [[49,50,51,52,53,54,55,56,57,48]]
183-- Test for offset of buffer size
184testReadChunksFromToWithBuffSizeOffset :: Property
185testReadChunksFromToWithBuffSizeOffset =
186 testReadChunksFromToWith 15 25 15 [[53,54,55,56,57,48,49,50,51,52,53]]
188-- Test with multi buffer size
189testReadChunksFromToWithMultiBuff :: Property
190testReadChunksFromToWithMultiBuff =
191 testReadChunksFromToWith
192 5 22 5 [[53,54,55,56,57],[48,49,50,51,52],[53,54,55,56,57],[48,49,50]]
194testReadChunksFromToWithRangeInvalid :: Property
195testReadChunksFromToWithRangeInvalid = testReadChunksFromToWith 15 5 15 []
198moduleName = "FileSystem.Handle"
204 modifyMaxSuccess (const maxTestCount) $ do
205 describe moduleName $ do
206 describe "Read From Handle" $ do
207 prop "read" $ testRead readFromHandle
208 prop "readWith" $ testRead readWithBufferFromHandle
209 prop "readChunks" $ testRead readChunksFromHandle
210 prop "readChunksWith" $ testRead readChunksWithBuffer
211 prop "readChunksFromToWith (0,0,n)"
212 testReadChunksFromToWithFirstByte
213 prop "readChunksFromToWith (1,1,n)"
214 testReadChunksFromToWithSecondByte
215 prop "readChunksFromToWith (1,10,n)"
216 testReadChunksFromToWithSecondToTenthBytes
217 prop "readChunksFromToWith (n,<2n,n)"
218 testReadChunksFromToWithBuffSizeOffset
219 prop "readChunksFromToWith (n,>2n,n)"
220 testReadChunksFromToWithMultiBuff
221 prop "readChunksFromToWith (n,<n,n)"
222 testReadChunksFromToWithRangeInvalid
223 describe "Write To Handle" $ do
224 prop "write" $ testWrite Handle.write
226 $ testWrite $ Handle.writeWith 1024
227 -- XXX This test needs a lot of stack when built with -O0
228 prop "writeChunks" testWriteWithChunk
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