Z-IO-0.1.2.0: test/Z/IO/FileSystemSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Z.IO.FileSystemSpec where
import Control.Concurrent.MVar (readMVar)
import Control.Monad
import Data.Bits
import Z.Data.Vector as V
import Z.Data.Vector.Base as V
import Data.List as List
import Foreign.Marshal.Array
import Foreign.Ptr
import Z.IO.Buffered
import Z.IO.Exception
import Z.IO.FileSystem
import Z.IO.Resource
import Z.IO.UV.Manager
import Test.Hspec
import Test.HUnit
spec :: Spec
spec = describe "filesystem operations" $ do
let content = "Hello world!"
content2 = V.cycleN 1024 "quick fox jumps over the lazy dog, 世界你好!\n"
size = V.length content
size2 = V.length content2
it "create a temp dir" $ do
tempdir <- mkdtemp "stdio-filesystem-unit"
dirs <- scandir "./"
rmdir tempdir
List.lookup tempdir dirs @?= Just DirEntDir
let flags = O_RDWR .|. O_CREAT
mode = DEFAULT_MODE
filename = "test-file"
it "Opens and writes a file" $ do
withResource (initFile filename flags mode) $ \ file -> do
o <- newBufferedOutput 4096 file
writeBuffer o content
flushBuffer o
withResource (initFile filename flags mode) $ \ file -> do
i <- newBufferedInput 4096 file
written <- readExactly size i
written @?= content
fr <- newFilePtr file 0
i <- newBufferedInput 4096 fr
written <- readExactly size i
written @=? content
unlink filename
it "Opens and writes a file II" $ do
withResource (initFile filename flags mode) $ \ file -> do
o <- newBufferedOutput 4096 file
writeBuffer o content2
flushBuffer o
withResource (initFile filename flags mode) $ \ file -> do
i <- newBufferedInput 4096 file
written <- readExactly size2 i
written @?= content2
withResource (initFile filename flags mode) $ \ file -> do
i <- newBufferedInput 4096 file
Just firstLine <- readLine i
firstLine @?= fst (V.break (== V.c2w '\n') content2)
fr <- newFilePtr file (fromIntegral $ size2 `div` 2)
i <- newBufferedInput 4096 fr
replicateM_ 512 $ do
Just firstLine <- readLine i
firstLine @=? fst (V.break (== V.c2w '\n') content2)
unlink filename
it "create and remove dir" $ do
tempdir <- mkdtemp "stdio-filesystem-unit"
let dirname = tempdir <> "/test-dir"
mkdir dirname mode
dirs <- scandir tempdir
print dirs
rmdir dirname
rmdir tempdir
List.lookup "test-dir" dirs @?= Just DirEntDir
let linkname = "test-link"
symlinkname = "test-symlink"
symlinkname2 = "test-symlink2"
it "link stat should be equal to target file" $ ( do
withResource (initFile filename flags mode) $ \ file -> return ()
s0 <- stat filename
link filename linkname
symlink "test-link" symlinkname SYMLINK_DEFAULT
absfp <- realpath filename
symlink absfp symlinkname2 SYMLINK_DEFAULT -- the second way to create a proper symlink
s1 <- stat linkname
s2 <- stat symlinkname
s2' <- stat symlinkname2
s0 @=? s1 {stNlink = 1, stCtim = stCtim s0} -- update hard link number, stCtim could have some small diff
s0 @=? s2 {stNlink = 1, stCtim = stCtim s0}
s0 @=? s2' {stNlink = 1, stCtim = stCtim s0}
withResource (initFile filename flags mode) $ \ file -> do
s4 <- fstat file
s0 @=? s4 {stNlink = 1, stCtim = stCtim s0}
) `finally` ( do
unlink filename
unlink linkname
unlink symlinkname
unlink symlinkname2
)
it "utime result in stat change" $ do
withResource (initFile filename flags mode) $ \ file -> return ()
utime filename 1000.2000 3000.4000
s <- stat filename
print s
uvtSecond (stAtim s) @?= 1000
uvtNanoSecond (stAtim s) @?= 200000000
uvtSecond (stMtim s) @?= 3000
uvtNanoSecond (stMtim s) @?= 400000000
unlink filename
it "futime result in fstat change" $ do
withResource (initFile filename flags mode) $ \ file -> do
futime file 5000.6000 7000.8000
s <- fstat file
print s
uvtSecond (stAtim s) @?= 5000
uvtNanoSecond (stAtim s) @?= 600000000
uvtSecond (stMtim s) @?= 7000
uvtNanoSecond (stMtim s) @?= 800000000
unlink filename