{-# LANGUAGE CPP #-}
module Main where
import Test.Tasty (defaultMain, testGroup)
import Test.Tasty.QuickCheck
import Test.QuickCheck.Monadic (monadicIO, run)
import System.Posix.IO
import System.Posix.Memory
import Control.Monad
import Control.Exception (bracket)
import Foreign.C.Types
import Foreign.Storable
import Data.Word
psz :: CSize
psz = fromIntegral sysconfPageSize
-- create an anonymous private mapping of page-size size.
withDummyMapping f = do
bracket (memoryMap Nothing psz [MemoryProtectionRead,MemoryProtectionWrite] MemoryMapPrivate Nothing 0)
(\mem -> memoryUnmap mem psz)
f
withDevZeroMapping f = withOpenFd "/dev/zero" $ \fd ->
bracket (memoryMap Nothing psz [MemoryProtectionRead,MemoryProtectionWrite] MemoryMapPrivate (Just fd) 0)
(\mem -> memoryUnmap mem psz)
f
where withOpenFd filename g = do
bracket (openFd filename ReadWrite Nothing defaultFileFlags)
closeFd
g
tests = testGroup "unix-memory"
[ testProperty "page-size" $ sysconfPageSize > 0 && sysconfPageSize < (2^(20::Int))
, testGroup "anonymous" $ runTestWithMapping withDummyMapping
#ifdef __APPLE__
, testGroup "fd" $ runTestWithMapping withDevZeroMapping
#endif
]
where runTestWithMapping mapF =
[ testProperty "mmap-munmap" $ monadicIO $ run $ mapF $ \_ -> return True
, testProperty "madvise" $ monadicIO $ run $ mapF $ \ptr ->
memoryAdvise ptr psz MemoryAdviceRandom >> return True
, testProperty "msync" $ monadicIO $ run $ mapF $ \ptr ->
memorySync ptr psz [MemorySyncAsync] >> return True
, testProperty "mlock-munlock" $ monadicIO $ run $ mapF $ \ptr -> do
memoryLock ptr psz
memoryUnlock ptr psz
return True
, testProperty "read" $ monadicIO $ run $ mapF $ \ptr -> do
res <- forM [0..(sysconfPageSize-1)] $ \off -> do
b <- peekElemOff ptr off :: IO Word8
return (b == 0)
return $ and res
]
main :: IO ()
main = defaultMain tests