foundation-0.0.2: tests/Test/Foundation/Storable.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Test.Foundation.Storable
( testForeignStorableRefs
) where
import Foundation
import Foundation.Class.Storable
import qualified Foreign.Storable
import qualified Foreign.Marshal.Alloc
import qualified Foreign.Marshal.Array
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.QuickCheck.Monadic
testForeignStorableRefs :: TestTree
testForeignStorableRefs = testGroup "Storable"
[ testGroup "Storable"
[ testPropertyStorable "Word8" (Proxy :: Proxy Word8)
, testPropertyStorable "Word16" (Proxy :: Proxy Word16)
, testPropertyStorable "Word32" (Proxy :: Proxy Word32)
, testPropertyStorable "Word64" (Proxy :: Proxy Word64)
, testPropertyStorable "Int8" (Proxy :: Proxy Int8)
, testPropertyStorable "Int16" (Proxy :: Proxy Int16)
, testPropertyStorable "Int32" (Proxy :: Proxy Int32)
, testPropertyStorable "Int64" (Proxy :: Proxy Int64)
, testPropertyStorable "Char" (Proxy :: Proxy Char)
, testPropertyStorable "Double" (Proxy :: Proxy Double)
, testPropertyStorable "Float" (Proxy :: Proxy Float)
]
, testGroup "StorableFixed"
[ testPropertyStorableFixed "Word8" (Proxy :: Proxy Word8)
, testPropertyStorableFixed "Word16" (Proxy :: Proxy Word16)
, testPropertyStorableFixed "Word32" (Proxy :: Proxy Word32)
, testPropertyStorableFixed "Word64" (Proxy :: Proxy Word64)
, testPropertyStorableFixed "Int8" (Proxy :: Proxy Int8)
, testPropertyStorableFixed "Int16" (Proxy :: Proxy Int16)
, testPropertyStorableFixed "Int32" (Proxy :: Proxy Int32)
, testPropertyStorableFixed "Int64" (Proxy :: Proxy Int64)
, testPropertyStorableFixed "Char" (Proxy :: Proxy Char)
, testPropertyStorableFixed "Double" (Proxy :: Proxy Double)
, testPropertyStorableFixed "Float" (Proxy :: Proxy Float)
]
]
testPropertyStorable :: (Storable a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> LString
-> Proxy a
-> TestTree
testPropertyStorable name p = testGroup name
[ testProperty "peek" $ testPropertyStorablePeek p
, testProperty "poke" $ testPropertyStorablePoke p
]
testPropertyStorableFixed :: (StorableFixed a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> LString
-> Proxy a
-> TestTree
testPropertyStorableFixed name p = testGroup name
[ testProperty "size" $ withProxy p $ \a -> size p === (Size $ Foreign.Storable.sizeOf a)
, testProperty "alignment" $ withProxy p $ \a -> alignment p === (Size $ Foreign.Storable.alignment a)
, testProperty "peekOff" $ testPropertyStorableFixedPeekOff p
, testProperty "pokeOff" $ testPropertyStorableFixedPokeOff p
]
where
withProxy :: (Arbitrary a, Storable a, Show a, Eq a, Foreign.Storable.Storable a)
=> Proxy a -> (a -> Property) -> (a -> Property)
withProxy _ f = f
testPropertyStorablePeek :: (Storable a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> Proxy a
-> a
-> Property
testPropertyStorablePeek _ v = monadicIO $ do
v' <- run $ Foreign.Marshal.Alloc.alloca $ \ptr -> do
Foreign.Storable.poke ptr v
peek ptr
assert $ v == v'
testPropertyStorablePoke :: (Storable a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> Proxy a
-> a
-> Property
testPropertyStorablePoke _ v = monadicIO $ do
v' <- run $ Foreign.Marshal.Alloc.alloca $ \ptr -> do
poke ptr v
Foreign.Storable.peek ptr
assert $ v == v'
data SomeWhereInArray a = SomeWhereInArray a Int Int
deriving (Show, Eq)
instance (StorableFixed a, Arbitrary a) => Arbitrary (SomeWhereInArray a) where
arbitrary = do
a <- arbitrary
let p = toProxy a
(Size minsz) = size p + (alignment p - size p)
sz <- choose (minsz, 512)
o <- choose (0, sz - minsz)
return $ SomeWhereInArray a sz o
where
toProxy :: a -> Proxy a
toProxy _ = Proxy
testPropertyStorableFixedPeekOff :: (StorableFixed a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> Proxy a
-> SomeWhereInArray a
-> Property
testPropertyStorableFixedPeekOff _ (SomeWhereInArray v sz off) = monadicIO $ do
v' <- run $ Foreign.Marshal.Array.allocaArray sz $ \ptr -> do
Foreign.Storable.pokeElemOff ptr off v
peekOff ptr (Offset off)
assert $ v == v'
testPropertyStorableFixedPokeOff :: (StorableFixed a, Foreign.Storable.Storable a, Arbitrary a, Eq a, Show a)
=> Proxy a
-> SomeWhereInArray a
-> Property
testPropertyStorableFixedPokeOff _ (SomeWhereInArray v sz off) = monadicIO $ do
v' <- run $ Foreign.Marshal.Array.allocaArray sz $ \ptr -> do
pokeOff ptr (Offset off) v
Foreign.Storable.peekElemOff ptr off
assert $ v == v'