geomancy-0.4.0.0: test/Spec/Vec64.hs
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TypeApplications #-}
module Spec.Vec64 (tests) where
import Geomancy
import Hedgehog
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.Hedgehog (testPropertyNamed)
import Data.Proxy (Proxy(..))
import Data.Word (Word64)
import Foreign (allocaBytes, peekByteOff, pokeByteOff)
import Graphics.Gl.Block qualified as Block
import Geomancy.I64Vec3 qualified
import Geomancy.U64Vec3 qualified
import Support.Gen (genInt64, genWord64)
import Support.Property (pattern PROP_TESTS, layout140, storableRoundtrip)
tests :: TestTree
tests = testGroup "Vec64"
[ testPropertyNamed "storable_roundtrip" "prop_vec64_storable_roundtrip" prop_vec64_storable_roundtrip
, testPropertyNamed "packed_write_bounds" "prop_vec64_packed_write_bounds" prop_vec64_packed_write_bounds
, testPropertyNamed "abs" "prop_vec64_abs" prop_vec64_abs
, testPropertyNamed "block_layout" "prop_vec64_block_layout" prop_vec64_block_layout
]
prop_vec64_storable_roundtrip :: Property
prop_vec64_storable_roundtrip = withTests PROP_TESTS $ property do
i2 <- forAll $ i64vec2 <$> genInt64 <*> genInt64
storableRoundtrip i2 >>= (i2 ===)
i3 <- forAll $ i64vec3 <$> genInt64 <*> genInt64 <*> genInt64
storableRoundtrip i3 >>= (i3 ===)
let i3p = Geomancy.I64Vec3.Packed i3
storableRoundtrip i3p >>= (i3p ===)
i4 <- forAll $ i64vec4 <$> genInt64 <*> genInt64 <*> genInt64 <*> genInt64
storableRoundtrip i4 >>= (i4 ===)
u2 <- forAll $ u64vec2 <$> genWord64 <*> genWord64
storableRoundtrip u2 >>= (u2 ===)
u3 <- forAll $ u64vec3 <$> genWord64 <*> genWord64 <*> genWord64
storableRoundtrip u3 >>= (u3 ===)
let u3p = Geomancy.U64Vec3.Packed u3
storableRoundtrip u3p >>= (u3p ===)
u4 <- forAll $ u64vec4 <$> genWord64 <*> genWord64 <*> genWord64 <*> genWord64
storableRoundtrip u4 >>= (u4 ===)
prop_vec64_packed_write_bounds :: Property
prop_vec64_packed_write_bounds = withTests PROP_TESTS $ property do
i3 <- forAll $ i64vec3 <$> genInt64 <*> genInt64 <*> genInt64
u3 <- forAll $ u64vec3 <$> genWord64 <*> genWord64 <*> genWord64
let sentinel = 0x5EAF00D :: Word64
(i3', u3', afterI, afterU) <- evalIO $ allocaBytes 64 \ptr -> do
pokeByteOff ptr 24 sentinel
pokeByteOff ptr 56 sentinel
pokeByteOff ptr 0 (Block.Packed i3)
pokeByteOff ptr 32 (Block.Packed u3)
(,,,)
<$> fmap Block.getPacked (peekByteOff ptr 0)
<*> fmap Block.getPacked (peekByteOff ptr 32)
<*> peekByteOff ptr 24
<*> peekByteOff ptr 56
i3 === i3'
u3 === u3'
sentinel === afterI
sentinel === afterU
prop_vec64_abs :: Property
prop_vec64_abs = withTests 1 $ property do
i64vec2 1 2 === abs (i64vec2 (-1) 2)
i64vec3 1 2 3 === abs (i64vec3 (-1) 2 (-3))
i64vec4 1 2 3 4 === abs (i64vec4 (-1) 2 (-3) 4)
prop_vec64_block_layout :: Property
prop_vec64_block_layout = withTests 1 $ property do
(16, 16) === layout140 (Proxy @I64Vec2)
(32, 32) === layout140 (Proxy @I64Vec3)
(32, 24) === layout140 (Proxy @Geomancy.I64Vec3.Packed)
(32, 32) === layout140 (Proxy @I64Vec4)
(16, 16) === layout140 (Proxy @U64Vec2)
(32, 32) === layout140 (Proxy @U64Vec3)
(32, 24) === layout140 (Proxy @Geomancy.U64Vec3.Packed)
(32, 32) === layout140 (Proxy @U64Vec4)