grisette-0.13.0.1: test/Grisette/SymPrim/BVTests.hs
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Grisette.SymPrim.BVTests (bvTests) where
import Control.DeepSeq (NFData (rnf), deepseq, force)
import Control.Exception
( ArithException,
SomeException,
catch,
evaluate,
)
import Control.Monad (when)
import Data.Bifunctor (Bifunctor (bimap))
import Data.Bits
( Bits
( bit,
bitSizeMaybe,
clearBit,
complement,
complementBit,
isSigned,
popCount,
rotate,
rotateL,
rotateR,
setBit,
shift,
shiftL,
shiftR,
testBit,
xor,
zeroBits,
(.&.),
(.|.)
),
FiniteBits (countLeadingZeros, countTrailingZeros, finiteBitSize),
)
import Data.Int (Int8)
import Data.Proxy (Proxy (Proxy))
import Data.Serialize (decode, encode)
import Data.Typeable (Typeable, typeRep)
import Data.Word (Word8)
import GHC.Stack (HasCallStack)
import Grisette
( BV (bv),
SizedBV
( sizedBVConcat,
sizedBVExt,
sizedBVSelect,
sizedBVSext,
sizedBVZext
),
SomeIntN,
SomeWordN,
pattern SomeIntN,
pattern SomeWordN,
)
import Grisette.Internal.SymPrim.BV
( IntN (IntN),
WordN (unWordN),
)
import Test.Framework (Test, TestName, testGroup)
import Test.Framework.Providers.HUnit (testCase)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.HUnit (Assertion, assertFailure, (@=?), (@?=))
import Test.QuickCheck (Arbitrary, Property, ioProperty)
unaryConform :: forall a b c d. (Show c, Eq c, HasCallStack) => (a -> b) -> (d -> c) -> (a -> c) -> (b -> d) -> a -> Property
unaryConform a2b d2c f g x = ioProperty $ f x @=? d2c (g (a2b x))
binaryConform ::
forall a b c d e f.
(Show e, Eq e, HasCallStack) =>
(a -> b) ->
(c -> d) ->
(f -> e) ->
(a -> c -> e) ->
(b -> d -> f) ->
a ->
c ->
Property
binaryConform a2b c2d f2e f g x y = ioProperty $ f x y @=? f2e (g (a2b x) (c2d y))
wordUnaryConform :: (HasCallStack) => (WordN 8 -> WordN 8) -> (Word8 -> Word8) -> Word8 -> Assertion
wordUnaryConform f g x = unWordN (f (fromIntegral x)) @=? toInteger (g x)
wordUnaryNonNegIntConform :: (HasCallStack) => (Int -> WordN 8) -> (Int -> Word8) -> Int -> Assertion
wordUnaryNonNegIntConform f g y = when (y >= 0) $ unWordN (f y) @=? toInteger (g y)
wordBinIntConform :: (HasCallStack) => (WordN 8 -> Int -> WordN 8) -> (Word8 -> Int -> Word8) -> Word8 -> Int -> Assertion
wordBinIntConform f g x y = unWordN (f (fromIntegral x) y) @=? toInteger (g x y)
wordBinNonNegIntConform :: (HasCallStack) => (WordN 8 -> Int -> WordN 8) -> (Word8 -> Int -> Word8) -> Word8 -> Int -> Assertion
wordBinNonNegIntConform f g x y = when (y >= 0) $ unWordN (f (fromIntegral x) y) @=? toInteger (g x y)
wordBinConform :: (HasCallStack) => (WordN 8 -> WordN 8 -> WordN 8) -> (Word8 -> Word8 -> Word8) -> Word8 -> Word8 -> Assertion
wordBinConform f g x y = unWordN (f (fromIntegral x) (fromIntegral y)) @=? toInteger (g x y)
intN8eqint8 :: IntN 8 -> Int8 -> Assertion
intN8eqint8 (IntN v) i
| v < 0 = assertFailure "Bad IntN"
| v <= 127 = v @=? fromIntegral i
| v == 128 = i @=? -128
| otherwise = 256 - v @=? fromIntegral (-i)
intUnaryConform :: (IntN 8 -> IntN 8) -> (Int8 -> Int8) -> Int8 -> Assertion
intUnaryConform f g x = intN8eqint8 (f (fromIntegral x)) (g x)
intUnaryNonNegIntConform :: (Int -> IntN 8) -> (Int -> Int8) -> Int -> Assertion
intUnaryNonNegIntConform f g y = when (y >= 0) $ intN8eqint8 (f y) (g y)
intBinIntConform :: (IntN 8 -> Int -> IntN 8) -> (Int8 -> Int -> Int8) -> Int8 -> Int -> Assertion
intBinIntConform f g x y = intN8eqint8 (f (fromIntegral x) y) (g x y)
intBinNonNegIntConform :: (IntN 8 -> Int -> IntN 8) -> (Int8 -> Int -> Int8) -> Int8 -> Int -> Assertion
intBinNonNegIntConform f g x y = when (y >= 0) $ intN8eqint8 (f (fromIntegral x) y) (g x y)
intBinConform :: (IntN 8 -> IntN 8 -> IntN 8) -> (Int8 -> Int8 -> Int8) -> Int8 -> Int8 -> Assertion
intBinConform f g x y = intN8eqint8 (f (fromIntegral x) (fromIntegral y)) (g x y)
finiteBitsConformTest ::
forall ref typ.
( Arbitrary ref,
Typeable ref,
Typeable typ,
Show ref,
FiniteBits ref,
FiniteBits typ,
Integral ref,
Integral typ
) =>
Proxy ref ->
Proxy typ ->
Int ->
Test
finiteBitsConformTest pref ptyp numBits =
testGroup
(show (typeRep ptyp) ++ " conform to " ++ show (typeRep pref) ++ " for FiniteBits instances")
[ testCase "finiteBitSize" $ finiteBitSize (0 :: typ) @=? numBits,
testProperty "countLeadingZeros" $ unaryConform @ref @typ fromIntegral id countLeadingZeros countLeadingZeros,
testProperty "countTrailingZeros" $ unaryConform @ref @typ fromIntegral id countTrailingZeros countTrailingZeros
]
boundedConformTest ::
forall ref typ.
(Typeable ref, Typeable typ, Bounded typ, Bounded ref, Integral ref, Num typ, Eq typ, Show typ) =>
Proxy ref ->
Proxy typ ->
Test
boundedConformTest pref ptyp =
testGroup
(show (typeRep ptyp) ++ " conform to " ++ show (typeRep pref) ++ " for Bounded instances")
[ testCase "minBound" $ (minBound :: typ) @=? fromIntegral (minBound :: ref),
testCase "maxBound" $ (maxBound :: typ) @=? fromIntegral (maxBound :: ref)
]
shouldThrow :: (NFData a) => String -> a -> IO ()
shouldThrow name x = do
errored <- catch (evaluate $ x `deepseq` True) (\(_ :: SomeException) -> return False)
when errored $ assertFailure $ name ++ " should throw an exception"
succPredLikeTest ::
forall a b.
(Arbitrary a, Eq a, Eq b, Show a, Show b, NFData b) =>
TestName ->
String ->
(a -> b) ->
(a -> a) ->
(b -> b) ->
a ->
b ->
Test
succPredLikeTest name boundName a2b fa fb bounda boundb =
testGroup
name
[ testProperty (name ++ " non " ++ boundName) $
ioProperty . \(x :: a) ->
if x == bounda then return () else a2b (fa x) @=? fb (a2b x),
testCase (name ++ " " ++ boundName) $ shouldThrow (name ++ " " ++ boundName) $ fb boundb
]
enumConformTest ::
forall ref typ.
( Arbitrary ref,
Typeable ref,
Typeable typ,
Show ref,
Show typ,
NFData typ,
Integral ref,
Integral typ,
Bounded ref,
Bounded typ
) =>
Proxy ref ->
Proxy typ ->
Test
enumConformTest pref ptyp =
testGroup
(show (typeRep ptyp) ++ " conform to " ++ show (typeRep pref) ++ " for Enum instances")
[ succPredLikeTest @ref @typ "succ" "maxBound" fromIntegral succ succ maxBound maxBound,
succPredLikeTest @ref @typ "pred" "minBound" fromIntegral pred pred minBound minBound,
testGroup
"toEnum"
[ testProperty "toEnum in bounds" $
ioProperty . \(x :: ref) ->
toInteger (toEnum (fromIntegral x) :: ref) @=? toInteger (toEnum (fromIntegral x) :: typ),
testCase "toEnum (fromIntegral minBound - 1)" $
shouldThrow "toEnum (fromIntegral minBound - 1)" (toEnum (fromIntegral (minBound :: typ) - 1) :: typ),
testCase "toEnum (fromIntegral maxBound + 1)" $
shouldThrow "toEnum (fromIntegral maxBound + 1)" (toEnum (fromIntegral (maxBound :: typ) + 1) :: typ)
],
testProperty "fromEnum" $ unaryConform @ref @typ fromIntegral id fromEnum fromEnum,
testProperty "enumFrom" $ unaryConform @ref @typ fromIntegral (fromIntegral <$>) enumFrom enumFrom,
testProperty "enumFromThen" $ \(x :: ref) y ->
ioProperty $ do
if x == y
then return ()
else do
(fromIntegral <$> enumFromThen x y) @=? enumFromThen (fromIntegral x :: typ) (fromIntegral y),
testProperty "enumFromTo" $ binaryConform @ref @typ fromIntegral fromIntegral (fromIntegral <$>) enumFromTo enumFromTo,
testProperty "enumFromThenTo" $ \(x :: ref) y z ->
ioProperty $
if x == y
then return ()
else (fromIntegral <$> enumFromThenTo x y z) @=? enumFromThenTo (fromIntegral x :: typ) (fromIntegral y) (fromIntegral z)
]
newtype AEWrapper = AEWrapper ArithException deriving (Eq)
instance Show AEWrapper where
show (AEWrapper x) = show x
instance NFData AEWrapper where
rnf (AEWrapper x) = x `seq` ()
sameDiv :: (NFData a, NFData b, Eq b, Show b) => a -> a -> (a -> b) -> (a -> a -> a) -> (b -> b -> b) -> IO ()
sameDiv x y a2b fa fb = do
xa <- evaluate (force $ Right $ fa x y) `catch` \(e :: ArithException) -> return $ Left $ AEWrapper e
xb <- evaluate (force $ Right $ fb (a2b x) (a2b y)) `catch` \(e :: ArithException) -> return $ Left $ AEWrapper e
xb @=? a2b <$> xa
sameDivMod :: (NFData a, NFData b, Eq b, Show b) => a -> a -> (a -> b) -> (a -> a -> (a, a)) -> (b -> b -> (b, b)) -> IO ()
sameDivMod x y a2b fa fb = do
xa <- evaluate (force $ Right $ fa x y) `catch` \(e :: ArithException) -> return $ Left $ AEWrapper e
xb <- evaluate (force $ Right $ fb (a2b x) (a2b y)) `catch` \(e :: ArithException) -> return $ Left $ AEWrapper e
xb @=? bimap a2b a2b <$> xa
divLikeTest ::
forall a b.
(Arbitrary a, Eq b, Num a, Show a, Bounded a, Show b, NFData b, NFData a) =>
TestName ->
(a -> b) ->
(a -> a -> a) ->
(b -> b -> b) ->
Test
divLikeTest name a2b fa fb =
testGroup
name
[ testCase "divided by zero" $ do
sameDiv 1 0 a2b fa fb
sameDiv 0 0 a2b fa fb
sameDiv (-1) 0 a2b fa fb
sameDiv minBound 0 a2b fa fb
sameDiv maxBound 0 a2b fa fb,
testCase "min divided by -1" $ do
sameDiv minBound (-1) a2b fa fb,
testProperty "prop" $ \(x :: a) y -> ioProperty $ sameDiv x y a2b fa fb
]
divModLikeTest ::
forall a b.
(Arbitrary a, Eq b, Num a, NFData a, Show a, Bounded a, Show b, NFData b) =>
TestName ->
(a -> b) ->
(a -> a -> (a, a)) ->
(b -> b -> (b, b)) ->
Test
divModLikeTest name a2b fa fb =
testGroup
name
[ testCase "divided by zero" $ do
sameDivMod 1 0 a2b fa fb
sameDivMod 0 0 a2b fa fb
sameDivMod (-1) 0 a2b fa fb
sameDivMod minBound 0 a2b fa fb
sameDivMod maxBound 0 a2b fa fb,
testCase "min divided by -1" $ do
sameDivMod minBound (-1) a2b fa fb,
testProperty "prop" $ \(x :: a) y -> ioProperty $ sameDivMod x y a2b fa fb
]
realConformTest ::
forall proxy ref typ.
(Typeable ref, Typeable typ, Integral ref, Arbitrary ref, Real typ, Show ref) =>
proxy ref ->
proxy typ ->
Test
realConformTest pref ptyp =
testGroup
(show (typeRep ptyp) ++ " conform to " ++ show (typeRep pref) ++ " for Real instances")
[ testProperty "toRational" $ unaryConform @ref @typ fromIntegral id toRational toRational
]
integralConformTest ::
forall ref typ.
( Arbitrary ref,
Typeable ref,
Typeable typ,
Show ref,
Show typ,
Integral ref,
Integral typ,
Bounded ref,
NFData typ,
NFData ref
) =>
Proxy ref ->
Proxy typ ->
Test
integralConformTest pref ptyp =
testGroup
(show (typeRep ptyp) ++ " conform to " ++ show (typeRep pref) ++ " for Integral instances")
[ divLikeTest @ref @typ "quot" fromIntegral quot quot,
divLikeTest @ref @typ "rem" fromIntegral rem rem,
divModLikeTest @ref @typ "quotRem" fromIntegral quotRem quotRem,
divLikeTest @ref @typ "div" fromIntegral div div,
divLikeTest @ref @typ "mod" fromIntegral mod mod,
divModLikeTest @ref @typ "divMod" fromIntegral divMod divMod,
testProperty "toInteger" $ unaryConform @ref @typ fromIntegral id toInteger toInteger
]
sizedBVTests :: Test
sizedBVTests =
testGroup
"sizedBV"
[ testGroup
"WordN 8 conform to Word8 for Bits instances"
[ testProperty "(.&.)" $ \x y -> ioProperty $ wordBinConform (.&.) (.&.) x y,
testProperty "(.|.)" $ \x y -> ioProperty $ wordBinConform (.|.) (.|.) x y,
testProperty "xor" $ \x y -> ioProperty $ wordBinConform xor xor x y,
testProperty "complement" $ ioProperty . wordUnaryConform complement complement,
testProperty "shift" $ \x y -> ioProperty $ wordBinIntConform shift shift x y,
testProperty "rotate" $ \x y -> ioProperty $ wordBinIntConform rotate rotate x y,
testCase "zeroBits" $ (zeroBits :: WordN 8) @=? 0,
testProperty "bit" $ ioProperty . wordUnaryNonNegIntConform bit bit,
testProperty "setBit" $ \x y -> ioProperty $ wordBinNonNegIntConform setBit setBit x y,
testProperty "clearBit" $ \x y -> ioProperty $ wordBinNonNegIntConform clearBit clearBit x y,
testProperty "complementBit" $ \x y -> ioProperty $ wordBinNonNegIntConform complementBit complementBit x y,
testProperty "testBit" $ \(x :: Word8) i -> i < 0 || testBit x i == testBit (fromIntegral x :: WordN 8) i,
testCase "bitSizeMaybe" $ bitSizeMaybe (0 :: WordN 8) @=? Just 8,
testCase "isSigned" $ isSigned (0 :: WordN 8) @=? False,
testProperty "shiftL" $ \x y -> ioProperty $ wordBinNonNegIntConform shiftL shiftL x y,
testProperty "shiftR" $ \x y -> ioProperty $ wordBinNonNegIntConform shiftR shiftR x y,
testProperty "rotateL" $ \x y -> ioProperty $ wordBinNonNegIntConform rotateL rotateL x y,
testProperty "rotateR" $ \x y -> ioProperty $ wordBinNonNegIntConform rotateR rotateR x y,
testProperty "popCount" $ ioProperty . \(x :: Word8) -> popCount x @=? popCount (fromIntegral x :: WordN 8)
],
finiteBitsConformTest (Proxy @Word8) (Proxy @(WordN 8)) 8,
boundedConformTest (Proxy @Word8) (Proxy @(WordN 8)),
enumConformTest (Proxy @Word8) (Proxy @(WordN 8)),
realConformTest (Proxy @Word8) (Proxy @(WordN 8)),
integralConformTest (Proxy @Word8) (Proxy @(WordN 8)),
testGroup
"WordN 8 conform to Word8 for Num instances"
[ testProperty "(+)" $ \x y -> ioProperty $ wordBinConform (+) (+) x y,
testProperty "(*)" $ \x y -> ioProperty $ wordBinConform (*) (*) x y,
testProperty "(-)" $ \x y -> ioProperty $ wordBinConform (-) (-) x y,
testProperty "negate" $ ioProperty . wordUnaryConform negate negate,
testProperty "abs" $ ioProperty . wordUnaryConform abs abs,
testProperty "signum" $ ioProperty . wordUnaryConform signum signum,
testProperty "fromInteger" $
ioProperty . \(x :: Integer) ->
unWordN (fromInteger x :: WordN 8) @=? toInteger (fromInteger x :: Word8)
],
testGroup
"WordN 8 conform to Word8 for Ord instances"
[ testProperty "(<=)" $ \(x :: Word8) y -> ioProperty $ x <= y @=? (fromIntegral x :: WordN 8) <= (fromIntegral y :: WordN 8)
],
testGroup
"IntN 8 conform to Int8 for Bits instances"
[ testProperty "(.&.)" $ \x y -> ioProperty $ intBinConform (.&.) (.&.) x y,
testProperty "(.|.)" $ \x y -> ioProperty $ intBinConform (.|.) (.|.) x y,
testProperty "xor" $ \x y -> ioProperty $ intBinConform xor xor x y,
testProperty "complement" $ ioProperty . intUnaryConform complement complement,
testProperty "shift" $ \x y -> ioProperty $ intBinIntConform shift shift x y,
testProperty "rotate" $ \x y -> ioProperty $ intBinIntConform rotate rotate x y,
testCase "zeroBits" $ (zeroBits :: IntN 8) @=? 0,
testProperty "bit" $ ioProperty . intUnaryNonNegIntConform bit bit,
testProperty "setBit" $ \x y -> ioProperty $ intBinNonNegIntConform setBit setBit x y,
testProperty "clearBit" $ \x y -> ioProperty $ intBinNonNegIntConform clearBit clearBit x y,
testProperty "complementBit" $ \x y -> ioProperty $ intBinNonNegIntConform complementBit complementBit x y,
testProperty "testBit" $ \(x :: Int8) i -> i < 0 || testBit x i == testBit (fromIntegral x :: IntN 8) i,
testCase "bitSizeMaybe" $ bitSizeMaybe (0 :: IntN 8) @=? Just 8,
testCase "isSigned" $ isSigned (0 :: IntN 8) @=? True,
testProperty "shiftL" $ \x y -> ioProperty $ intBinNonNegIntConform shiftL shiftL x y,
testProperty "shiftR" $ \x y -> ioProperty $ intBinNonNegIntConform shiftR shiftR x y,
testProperty "rotateL" $ \x y -> ioProperty $ intBinNonNegIntConform rotateL rotateL x y,
testProperty "rotateR" $ \x y -> ioProperty $ intBinNonNegIntConform rotateR rotateR x y,
testProperty "popCount" $ ioProperty . \(x :: Int8) -> popCount x @=? popCount (fromIntegral x :: IntN 8)
],
finiteBitsConformTest (Proxy @Int8) (Proxy @(IntN 8)) 8,
boundedConformTest (Proxy @Int8) (Proxy @(IntN 8)),
enumConformTest (Proxy @Int8) (Proxy @(IntN 8)),
realConformTest (Proxy @Int8) (Proxy @(IntN 8)),
integralConformTest (Proxy @Int8) (Proxy @(IntN 8)),
testGroup
"IntN 8 conform to Int8 for Num instances"
[ testProperty "(+)" $ \x y -> ioProperty $ intBinConform (+) (+) x y,
testProperty "(*)" $ \x y -> ioProperty $ intBinConform (*) (*) x y,
testProperty "(-)" $ \x y -> ioProperty $ intBinConform (-) (-) x y,
testProperty "negate" $ ioProperty . wordUnaryConform negate negate,
testProperty "abs" $ ioProperty . wordUnaryConform abs abs,
testProperty "signum" $ ioProperty . wordUnaryConform signum signum,
testProperty "fromInteger" $
ioProperty . \(x :: Integer) ->
intN8eqint8 (fromInteger x :: IntN 8) (fromInteger x :: Int8)
],
testGroup
"IntN 8 conform to IntN for Ord instances"
[ testProperty "(<=)" $ \(x :: Int8) y -> ioProperty $ (fromIntegral x :: IntN 8) <= (fromIntegral y :: IntN 8) @=? x <= y
],
testGroup
"WordN bvops"
[ testProperty "sizedBVConcat" $ \(x :: Integer) (y :: Integer) ->
ioProperty $
sizedBVConcat (fromInteger x :: WordN 5) (fromInteger y :: WordN 7) @=? fromInteger (x * 128 + y `mod` 128),
testProperty "sizedBVZext" $ ioProperty . \(x :: Integer) -> sizedBVZext (Proxy :: Proxy 12) (fromInteger x :: WordN 7) @=? fromInteger (x `mod` 128),
testCase "sizedBVSext" $ do
sizedBVSext (Proxy :: Proxy 12) (0 :: WordN 8) @=? 0
sizedBVSext (Proxy :: Proxy 12) (1 :: WordN 8) @=? 1
sizedBVSext (Proxy :: Proxy 12) (127 :: WordN 8) @=? 127
sizedBVSext (Proxy :: Proxy 12) (128 :: WordN 8) @=? 3968
sizedBVSext (Proxy :: Proxy 12) (255 :: WordN 8) @=? 4095,
testProperty "sizedBVExt is sizedBVZext" $
ioProperty . \(x :: Integer) ->
sizedBVExt (Proxy :: Proxy 12) (fromInteger x :: WordN 8) @=? sizedBVZext (Proxy :: Proxy 12) (fromInteger x :: WordN 8),
testCase "sizedBVSelect" $ do
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b11100 :: WordN 8) @=? 0b11
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b111000 :: WordN 8) @=? 0b111
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b101000 :: WordN 8) @=? 0b101
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b1010000 :: WordN 8) @=? 0b10
],
testGroup
"IntN bvops"
[ testProperty "sizedBVConcat" $ \(x :: Integer) (y :: Integer) ->
ioProperty $
sizedBVConcat (fromInteger x :: IntN 5) (fromInteger y :: IntN 7) @=? fromInteger (x * 128 + y `mod` 128),
testProperty "sizedBVZext" $ ioProperty . \(x :: Integer) -> sizedBVZext (Proxy :: Proxy 12) (fromInteger x :: IntN 7) @=? fromInteger (x `mod` 128),
testCase "sizedBVSext" $ do
sizedBVSext (Proxy :: Proxy 12) (0 :: WordN 8) @=? 0
sizedBVSext (Proxy :: Proxy 12) (1 :: WordN 8) @=? 1
sizedBVSext (Proxy :: Proxy 12) (127 :: WordN 8) @=? 127
sizedBVSext (Proxy :: Proxy 12) (128 :: WordN 8) @=? 3968
sizedBVSext (Proxy :: Proxy 12) (255 :: WordN 8) @=? 4095,
testProperty "sizedBVExt is sizedBVSext" $
ioProperty . \(x :: Integer) ->
sizedBVExt (Proxy :: Proxy 12) (fromInteger x :: IntN 8) @=? sizedBVSext (Proxy :: Proxy 12) (fromInteger x :: IntN 8),
testCase "sizedBVSelect" $ do
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b11100 :: IntN 8) @=? 0b11
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b111000 :: IntN 8) @=? 0b111
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b101000 :: IntN 8) @=? 0b101
sizedBVSelect (Proxy :: Proxy 3) (Proxy :: Proxy 3) (0b1010000 :: IntN 8) @=? 0b10
],
testGroup
"read"
[ testProperty "read . show" $ \(x :: IntN 8) -> read (show x) == x,
testProperty "read . show" $ \(x :: WordN 8) -> read (show x) == x,
testProperty "read . show" $ \(x :: IntN 9) -> read (show x) == x,
testProperty "read . show" $ \(x :: WordN 9) -> read (show x) == x
],
testGroup
"Regression"
[ testCase "division of min bound and minus one for signed bit vector should throw" $ do
shouldThrow "divMod" $ divMod (minBound :: IntN 8) (-1 :: IntN 8)
shouldThrow "div" $ div (minBound :: IntN 8) (-1 :: IntN 8)
shouldThrow "quotRem" $ quotRem (minBound :: IntN 8) (-1 :: IntN 8)
shouldThrow "quot" $ quot (minBound :: IntN 8) (-1 :: IntN 8),
testCase "toInteger for IntN 1" $ do
toInteger (0 :: IntN 1) @=? 0
toInteger (1 :: IntN 1) @=? (-1),
testProperty "WordN shiftL by large amount" $ \(x :: WordN 128) ->
ioProperty $ shiftL x maxBound @=? 0,
testProperty "IntN shiftL by large amount" $ \(x :: IntN 128) ->
ioProperty $ shiftL x maxBound @=? 0
],
testGroup
"Serialize"
[ testProperty "WordN 8" $
\(x :: WordN 8) -> Right x == (decode . encode) x,
testProperty "IntN 8" $
\(x :: IntN 8) -> Right x == (decode . encode) x
]
]
someWordNTests :: Test
someWordNTests =
testGroup
"SomeWordN"
[ testGroup
"BV"
[ testGroup
"bv"
[ testCase "bv 12 21" $
(bv 12 21 :: SomeWordN) @?= SomeWordN (0x015 :: WordN 12)
]
]
]
someIntNTests :: Test
someIntNTests =
testGroup
"SomeIntN"
[ testGroup
"BV"
[ testGroup
"bv"
[ testCase "bv 12 21" $
(bv 12 21 :: SomeIntN) @?= SomeIntN (0x015 :: IntN 12)
]
]
]
bvTests :: Test
bvTests = testGroup "BV" [sizedBVTests, someWordNTests, someIntNTests]