1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
|
{-# LANGUAGE CPP #-}
module Tests.Vector
( vectorTests
) where
import Support
import Prelude hiding (and, or)
import Control.Exception
import Data.Bit
import Data.Bits
import Data.List (findIndex)
import qualified Data.Vector.Primitive as P
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Base as UB
import Data.Word
import Test.Tasty
import Test.Tasty.QuickCheck (Property, NonNegative(..), Positive(..), testProperty, Large(..), (===), property, once, (==>), ioProperty, (.&&.), counterexample)
#include "MachDeps.h"
vectorTests :: TestTree
vectorTests = testGroup "Data.Vector.Unboxed.Bit"
[ testGroup "Data.Vector.Unboxed functions"
[ testProperty "toList . fromList == id" prop_toList_fromList
, mkGroup "fromList . toList == id" prop_fromList_toList
, testProperty "slice" prop_slice_def
]
, tenTimesLess $
testProperty "cloneFromWords" prop_cloneFromWords_def
, mkGroup "cloneToWords" prop_cloneToWords_def
, tenTimesLess $
testProperty "castToWords_1" prop_castToWords_1
, tenTimesLess $
testProperty "castToWords_2" prop_castToWords_2
, tenTimesLess $
testProperty "cloneFromWords8" prop_cloneFromWords8_def
, mkGroup "cloneToWords8" prop_cloneToWords8_def
, tenTimesLess $
testProperty "castToWords8_1" prop_castToWords8_1
, tenTimesLess $
testProperty "castToWords8_2" prop_castToWords8_2
, testProperty "cloneToByteString" prop_cloneToByteString
, mkGroup "reverse" prop_reverse_def
, testGroup "countBits"
[ testProperty "special case 1" case_countBits_1
, mkGroup "matches definition" prop_countBits_def
]
, testGroup "listBits"
[ testProperty "special case 1" case_listBits_1
, testProperty "special case 2" case_listBits_2
, mkGroup "matches definition" prop_listBits_def
]
, mkGroup "and" prop_and_def
, mkGroup "or" prop_or_def
, testGroup "bitIndex"
[ testProperty "special case 1" case_bitIndex_1
, testProperty "special case 2" case_bitIndex_2
, testProperty "special case 3" case_bitIndex_3
, testProperty "special case 4" case_bitIndex_4
, testProperty "special case 5" case_bitIndex_5
, testProperty "special case 6" case_bitIndex_6
, testProperty "special case 7" case_bitIndex_7
, mkGroup "True" (prop_bitIndex_1 (Bit True))
, mkGroup "False" (prop_bitIndex_1 (Bit False))
]
, testGroup "nthBitIndex"
[ testProperty "special case 1" case_nthBit_1
, testProperty "special case 2" case_nthBit_2
, testProperty "special case 3" case_nthBit_3
, testProperty "special case 4" case_nthBit_4
, testProperty "special case 5" case_nthBit_5
, testProperty "special case 6" case_nthBit_6
, testProperty "special case 7" case_nthBit_7
, mkGroup "matches bitIndex True" prop_nthBit_1
, mkGroup "matches bitIndex False" prop_nthBit_2
, testProperty "matches sequence of bitIndex True" prop_nthBit_3
, testProperty "matches sequence of bitIndex False" prop_nthBit_4
, testProperty "matches countBits" prop_nthBit_5
, testProperty "negative argument" prop_nthBit_6
]
, testGroup "Bits instance"
[ testProperty "rotate is reversible" prop_rotate
, testProperty "bit" prop_bit
, testProperty "shiftL" prop_shiftL
, testProperty "shiftR" prop_shiftR
, testProperty "zeroBits" prop_zeroBits
, testProperty "bitSize" prop_bitSize
, testProperty "isSigned" prop_isSigned
, testProperty "setBit" prop_setBit
, testProperty "clearBit" prop_clearBit
, testProperty "complementBit" prop_complementBit
]
]
mkGroup :: String -> (U.Vector Bit -> Property) -> TestTree
mkGroup name prop = testGroup name
[ testProperty "simple" prop
, testProperty "simple_long" (prop . getLarge)
, testProperty "middle" propMiddle
, testProperty "middle_long" propMiddleLong
]
where
f m = let n = fromIntegral m :: Double in
odd (truncate (exp (abs (sin n) * 10)) :: Integer)
propMiddle (NonNegative from) (NonNegative len) (NonNegative excess) =
prop (U.slice from len (U.generate (from + len + excess) (Bit . f)))
propMiddleLong (NonNegative x) (NonNegative y) (NonNegative z) =
propMiddle (NonNegative $ x * 31) (NonNegative $ y * 37) (NonNegative $ z * 29)
prop_toList_fromList :: [Bit] -> Property
prop_toList_fromList xs = U.toList (U.fromList xs) === xs
prop_fromList_toList :: U.Vector Bit -> Property
prop_fromList_toList xs = U.fromList (U.toList xs) === xs
prop_slice_def :: Int -> Int -> U.Vector Bit -> Property
prop_slice_def s n xs =
sliceList s' n' (U.toList xs) === U.toList (U.slice s' n' xs)
where
(s', n') = trimSlice s n (U.length xs)
prop_cloneFromWords_def :: U.Vector Word -> Property
prop_cloneFromWords_def ws =
U.toList (castFromWords ws) === concatMap wordToBitList (U.toList ws)
prop_cloneToWords_def :: U.Vector Bit -> Property
prop_cloneToWords_def xs = U.toList (cloneToWords xs) === loop (U.toList xs)
where
loop [] = []
loop bs = case packBitsToWord bs of
(w, bs') -> w : loop bs'
prop_castToWords_1 :: U.Vector Word -> Property
prop_castToWords_1 ws =
Just ws === castToWords (castFromWords ws)
prop_castToWords_2 :: U.Vector Bit -> Property
prop_castToWords_2 xs = case castToWords xs of
Nothing -> property True
Just ws -> castFromWords ws === xs
prop_cloneFromWords8_def :: U.Vector Word8 -> Property
prop_cloneFromWords8_def ws
= counterexample ("offset = " ++ show off ++ " len = " ++ show len)
$ U.toList (castFromWords8 ws) === concatMap wordToBitList (U.toList ws)
where
UB.V_Word8 (P.Vector off len _) = ws
prop_cloneToWords8_def :: U.Vector Bit -> Property
prop_cloneToWords8_def xs@(BitVec off len _)
= counterexample ("offset = " ++ show off ++ " len = " ++ show len)
$ U.toList (cloneToWords8 xs) === loop (U.toList xs)
where
loop [] = []
loop bs = case packBitsToWord bs of
(w, bs') -> w : loop bs'
prop_castToWords8_1 :: U.Vector Word8 -> Property
#ifdef WORDS_BIGENDIAN
prop_castToWords8_1 ws = Nothing === castToWords8 (castFromWords8 ws)
#else
prop_castToWords8_1 ws
= counterexample ("offset = " ++ show off ++ " len = " ++ show len)
$ Just ws === castToWords8 (castFromWords8 ws)
where
UB.V_Word8 (P.Vector off len _) = ws
#endif
prop_castToWords8_2 :: U.Vector Bit -> Property
prop_castToWords8_2 xs = case castToWords8 xs of
Nothing -> property True
Just ws -> castFromWords8 ws === xs
prop_reverse_def :: U.Vector Bit -> Property
prop_reverse_def xs =
reverse (U.toList xs) === U.toList (U.modify reverseInPlace xs)
prop_countBits_def :: U.Vector Bit -> Property
prop_countBits_def xs = countBits xs === length (filter unBit (U.toList xs))
case_countBits_1 :: Property
case_countBits_1 = once $
countBits (U.drop 64 (U.replicate 128 (Bit False))) === 0
prop_listBits_def :: U.Vector Bit -> Property
prop_listBits_def xs =
listBits xs === [ i | (i, x) <- zip [0 ..] (U.toList xs), unBit x ]
case_listBits_1 :: Property
case_listBits_1 = once $
listBits (U.drop 24 (U.replicate 64 (Bit False))) === []
case_listBits_2 :: Property
case_listBits_2 = once $
listBits (U.drop 24 (U.replicate 128 (Bit True))) === [0..103]
and :: U.Vector Bit -> Bool
and xs = case bitIndex (Bit False) xs of
Nothing -> True
Just{} -> False
prop_and_def :: U.Vector Bit -> Property
prop_and_def xs = and xs === all unBit (U.toList xs)
or :: U.Vector Bit -> Bool
or xs = case bitIndex (Bit True) xs of
Nothing -> False
Just{} -> True
prop_or_def :: U.Vector Bit -> Property
prop_or_def xs = or xs === any unBit (U.toList xs)
case_bitIndex_1 :: Property
case_bitIndex_1 = once $
bitIndex (Bit True) (U.generate 128 (Bit . (== 64))) === Just 64
case_bitIndex_2 :: Property
case_bitIndex_2 = once $
bitIndex (Bit False) (U.generate 128 (Bit . (/= 64))) === Just 64
case_bitIndex_3 :: Property
case_bitIndex_3 = once $
bitIndex (Bit True) (U.drop 63 (U.generate 128 (Bit . (== 64)))) === Just 1
case_bitIndex_4 :: Property
case_bitIndex_4 = once $
bitIndex (Bit False) (U.drop 63 (U.generate 128 (Bit . (/= 64)))) === Just 1
case_bitIndex_5 :: Property
case_bitIndex_5 = once $
bitIndex (Bit False) (U.drop 63 (U.replicate 65 (Bit True))) === Nothing
case_bitIndex_6 :: Property
case_bitIndex_6 = once $
bitIndex (Bit False) (U.drop 63 (U.generate 66 (Bit . (== 63)))) === Just 1
case_bitIndex_7 :: Property
case_bitIndex_7 = once $
bitIndex (Bit False) (U.drop 1023 (U.generate 1097 (Bit . (/= 1086)))) === Just 63
prop_bitIndex_1 :: Bit -> U.Vector Bit -> Property
prop_bitIndex_1 b xs = bitIndex b xs === findIndex (b ==) (U.toList xs)
prop_nthBit_1 :: U.Vector Bit -> Property
prop_nthBit_1 xs = bitIndex (Bit True) xs === nthBitIndex (Bit True) 1 xs
prop_nthBit_2 :: U.Vector Bit -> Property
prop_nthBit_2 xs = bitIndex (Bit False) xs === nthBitIndex (Bit False) 1 xs
prop_nthBit_3 :: Positive Int -> U.Vector Bit -> Property
prop_nthBit_3 (Positive n) xs = case nthBitIndex (Bit True) (n + 1) xs of
Nothing -> property True
Just i -> case bitIndex (Bit True) xs of
Nothing -> property False
Just j -> case nthBitIndex (Bit True) n (U.drop (j + 1) xs) of
Nothing -> property False
Just k -> i === j + k + 1
prop_nthBit_4 :: Positive Int -> U.Vector Bit -> Property
prop_nthBit_4 (Positive n) xs = case nthBitIndex (Bit False) (n + 1) xs of
Nothing -> property True
Just i -> case bitIndex (Bit False) xs of
Nothing -> property False
Just j -> case nthBitIndex (Bit False) n (U.drop (j + 1) xs) of
Nothing -> property False
Just k -> i === j + k + 1
prop_nthBit_5 :: Positive Int -> U.Vector Bit -> Property
prop_nthBit_5 (Positive n) xs = count > 0 ==>
case nthBitIndex (Bit True) n' xs of
Nothing -> property False
Just i -> countBits (U.take (i + 1) xs) === n'
where
count = countBits xs
n' = n `mod` count + 1
prop_nthBit_6 :: NonNegative Int -> U.Vector Bit -> Property
prop_nthBit_6 (NonNegative n) xs = ioProperty $ do
ret <- try (evaluate (nthBitIndex (Bit True) (-n) xs))
pure $ property $ case ret of
Left ErrorCallWithLocation{} -> True
_ -> False
case_nthBit_1 :: Property
case_nthBit_1 = once $
nthBitIndex (Bit True) 1 (U.slice 61 4 (U.replicate 100 (Bit False))) === Nothing
case_nthBit_2 :: Property
case_nthBit_2 = once $
nthBitIndex (Bit False) 1 (U.slice 61 4 (U.replicate 100 (Bit True))) === Nothing
case_nthBit_3 :: Property
case_nthBit_3 = once $
nthBitIndex (Bit True) 1 (U.drop 63 (U.generate 128 (Bit . (== 64)))) === Just 1
case_nthBit_4 :: Property
case_nthBit_4 = once $
nthBitIndex (Bit False) 1 (U.drop 63 (U.generate 128 (Bit . (/= 64)))) === Just 1
case_nthBit_5 :: Property
case_nthBit_5 = once $
nthBitIndex (Bit False) 1 (U.drop 63 (U.replicate 65 (Bit True))) === Nothing
case_nthBit_6 :: Property
case_nthBit_6 = once $
nthBitIndex (Bit False) 1 (U.drop 63 (U.generate 66 (Bit . (== 63)))) === Just 1
case_nthBit_7 :: Property
case_nthBit_7 = once $
nthBitIndex (Bit False) 1 (U.drop 1023 (U.generate 1097 (Bit . (/= 1086)))) === Just 63
prop_rotate :: Int -> U.Vector Bit -> Property
prop_rotate n v = v === (v `rotate` n) `rotate` (-n)
prop_bit :: Int -> Property
prop_bit n
| n >= 0
= testBit v n .&&. popCount v === 1 .&&. U.length v === n + 1
| otherwise
= not (testBit v n) .&&. popCount v === 0 .&&. U.length v === 0
where
v :: U.Vector Bit
v = bit n
prop_shiftL :: NonNegative Int -> U.Vector Bit -> Property
prop_shiftL (NonNegative n) v = v === u
where
u = (v `shiftL` n) `shiftR` n
prop_shiftR :: NonNegative Int -> U.Vector Bit -> Property
prop_shiftR (NonNegative n) v = U.drop n v === U.drop n u .&&. popCount (U.take n u) === 0
where
u = (v `shiftR` n) `shiftL` n
prop_zeroBits :: Property
prop_zeroBits = once $
U.length (zeroBits :: U.Vector Bit) === 0
prop_bitSize :: U.Vector Bit -> Property
prop_bitSize v = bitSizeMaybe v === Nothing
prop_isSigned :: U.Vector Bit -> Property
prop_isSigned v = isSigned v === False
prop_setBit :: Int -> U.Vector Bit -> Property
prop_setBit n v = v `setBit` n === U.imap ((.|.) . Bit . (== n)) v
prop_clearBit :: Int -> U.Vector Bit -> Property
prop_clearBit n v = v `clearBit` n === U.imap ((.&.) . Bit . (/= n)) v
prop_complementBit :: Int -> U.Vector Bit -> Property
prop_complementBit n v = v `complementBit` n === U.imap (xor . Bit . (== n)) v
prop_cloneToByteString :: U.Vector Bit -> Property
prop_cloneToByteString v@(BitVec off len _)
= counterexample ("offset = " ++ show off ++ " len = " ++ show len)
$ cloneToByteString (cloneFromByteString bs) === bs
where
bs = cloneToByteString v
|