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 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
|
{-# LANGUAGE CPP, ScopedTypeVariables, DataKinds, TypeSynonymInstances #-}
module Main ( main ) where
#if MIN_VERSION_base(4,8,0)
#define HAS_NATURAL
#endif
#if MIN_VERSION_base(4,7,0)
#define HAS_FIXED_CONSTRUCTOR
#endif
import Control.Applicative
import Control.Exception as C (SomeException,
catch, evaluate)
import Control.Monad (unless, liftM2)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Internal as L
#if MIN_VERSION_bytestring(0,10,4)
import Data.ByteString.Short (ShortByteString)
#endif
import Data.Int
import Data.Ratio
import Data.Typeable
import System.IO.Unsafe
import Data.Orphans ()
#ifdef HAS_NATURAL
import Numeric.Natural
#endif
import GHC.Fingerprint
import qualified Data.Fixed as Fixed
import Test.Framework
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck hiding (total)
import qualified Action (tests)
import Arbitrary ()
import Data.Binary
import Data.Binary.Get
import Data.Binary.Put
------------------------------------------------------------------------
roundTrip :: (Eq a, Binary a) => a -> (L.ByteString -> L.ByteString) -> Bool
roundTrip a f = a ==
{-# SCC "decode.refragment.encode" #-} decode (f (encode a))
roundTripWith :: Eq a => (a -> Put) -> Get a -> a -> Property
roundTripWith putter getter x =
forAll positiveList $ \xs ->
x == runGet getter (refragment xs (runPut (putter x)))
-- make sure that a test fails
mustThrowError :: B a
mustThrowError a = unsafePerformIO $
C.catch (do _ <- C.evaluate a
return False)
(\(_e :: SomeException) -> return True)
-- low level ones:
--
-- Words
prop_Word8 :: Word8 -> Property
prop_Word8 = roundTripWith putWord8 getWord8
prop_Word16be :: Word16 -> Property
prop_Word16be = roundTripWith putWord16be getWord16be
prop_Word16le :: Word16 -> Property
prop_Word16le = roundTripWith putWord16le getWord16le
prop_Word16host :: Word16 -> Property
prop_Word16host = roundTripWith putWord16host getWord16host
prop_Word32be :: Word32 -> Property
prop_Word32be = roundTripWith putWord32be getWord32be
prop_Word32le :: Word32 -> Property
prop_Word32le = roundTripWith putWord32le getWord32le
prop_Word32host :: Word32 -> Property
prop_Word32host = roundTripWith putWord32host getWord32host
prop_Word64be :: Word64 -> Property
prop_Word64be = roundTripWith putWord64be getWord64be
prop_Word64le :: Word64 -> Property
prop_Word64le = roundTripWith putWord64le getWord64le
prop_Word64host :: Word64 -> Property
prop_Word64host = roundTripWith putWord64host getWord64host
prop_Wordhost :: Word -> Property
prop_Wordhost = roundTripWith putWordhost getWordhost
-- Ints
prop_Int8 :: Int8 -> Property
prop_Int8 = roundTripWith putInt8 getInt8
prop_Int16be :: Int16 -> Property
prop_Int16be = roundTripWith putInt16be getInt16be
prop_Int16le :: Int16 -> Property
prop_Int16le = roundTripWith putInt16le getInt16le
prop_Int16host :: Int16 -> Property
prop_Int16host = roundTripWith putInt16host getInt16host
prop_Int32be :: Int32 -> Property
prop_Int32be = roundTripWith putInt32be getInt32be
prop_Int32le :: Int32 -> Property
prop_Int32le = roundTripWith putInt32le getInt32le
prop_Int32host :: Int32 -> Property
prop_Int32host = roundTripWith putInt32host getInt32host
prop_Int64be :: Int64 -> Property
prop_Int64be = roundTripWith putInt64be getInt64be
prop_Int64le :: Int64 -> Property
prop_Int64le = roundTripWith putInt64le getInt64le
prop_Int64host :: Int64 -> Property
prop_Int64host = roundTripWith putInt64host getInt64host
prop_Inthost :: Int -> Property
prop_Inthost = roundTripWith putInthost getInthost
-- Floats and Doubles
prop_Floatbe :: Float -> Property
prop_Floatbe = roundTripWith putFloatbe getFloatbe
prop_Floatle :: Float -> Property
prop_Floatle = roundTripWith putFloatle getFloatle
prop_Floathost :: Float -> Property
prop_Floathost = roundTripWith putFloathost getFloathost
prop_Doublebe :: Double -> Property
prop_Doublebe = roundTripWith putDoublebe getDoublebe
prop_Doublele :: Double -> Property
prop_Doublele = roundTripWith putDoublele getDoublele
prop_Doublehost :: Double -> Property
prop_Doublehost = roundTripWith putDoublehost getDoublehost
#if MIN_VERSION_base(4,10,0)
testTypeable :: Test
testTypeable = testProperty "TypeRep" prop_TypeRep
prop_TypeRep :: TypeRep -> Property
prop_TypeRep = roundTripWith put get
atomicTypeReps :: [TypeRep]
atomicTypeReps =
[ typeRep (Proxy :: Proxy ())
, typeRep (Proxy :: Proxy String)
, typeRep (Proxy :: Proxy Int)
, typeRep (Proxy :: Proxy (,))
, typeRep (Proxy :: Proxy ((,) (Maybe Int)))
, typeRep (Proxy :: Proxy Maybe)
, typeRep (Proxy :: Proxy 'Nothing)
, typeRep (Proxy :: Proxy 'Left)
, typeRep (Proxy :: Proxy "Hello")
, typeRep (Proxy :: Proxy 42)
, typeRep (Proxy :: Proxy '[1,2,3,4])
, typeRep (Proxy :: Proxy ('Left Int))
, typeRep (Proxy :: Proxy (Either Int String))
, typeRep (Proxy :: Proxy (() -> ()))
]
instance Arbitrary TypeRep where
arbitrary = oneof (map pure atomicTypeReps)
#else
testTypeable :: Test
testTypeable = testGroup "Skipping Typeable tests" []
#endif
-- done, partial and fail
-- | Test partial results.
-- May or may not use the whole input, check conditions for the different
-- outcomes.
prop_partial :: L.ByteString -> Property
prop_partial lbs = forAll (choose (0, L.length lbs * 2)) $ \skipN ->
let result = pushChunks (runGetIncremental decoder) lbs
decoder = do
s <- getByteString (fromIntegral skipN)
return (L.fromChunks [s])
in case result of
Partial _ -> L.length lbs < skipN
Done unused _pos value ->
and [ L.length value == skipN
, L.append value (L.fromChunks [unused]) == lbs
]
Fail _ _ _ -> False
-- | Fail a decoder and make sure the result is sane.
prop_fail :: L.ByteString -> String -> Property
prop_fail lbs msg = forAll (choose (0, L.length lbs)) $ \pos ->
let result = pushChunks (runGetIncremental decoder) lbs
decoder = do
-- use part of the input...
_ <- getByteString (fromIntegral pos)
-- ... then fail
fail msg
in case result of
Fail unused pos' msg' ->
and [ pos == pos'
, msg == msg'
, L.length lbs - pos == fromIntegral (B.length unused)
, L.fromChunks [unused] `L.isSuffixOf` lbs
]
_ -> False -- wuut?
-- read negative length
prop_getByteString_negative :: Int -> Property
prop_getByteString_negative n =
n < 1 ==>
runGet (getByteString n) L.empty == B.empty
prop_bytesRead :: L.ByteString -> Property
prop_bytesRead lbs =
forAll (makeChunks 0 totalLength) $ \chunkSizes ->
let result = pushChunks (runGetIncremental decoder) lbs
decoder = do
-- Read some data and invoke bytesRead several times.
-- Each time, check that the values are what we expect.
flip mapM_ chunkSizes $ \(total, step) -> do
_ <- getByteString (fromIntegral step)
n <- bytesRead
unless (n == total) $ fail "unexpected position"
bytesRead
in case result of
Done unused pos value ->
and [ value == totalLength
, pos == value
, B.null unused
]
Partial _ -> False
Fail _ _ _ -> False
where
totalLength = L.length lbs
makeChunks total i
| i == 0 = return []
| otherwise = do
n <- choose (0,i)
let total' = total + n
rest <- makeChunks total' (i - n)
return ((total',n):rest)
-- | We're trying to guarantee that the Decoder will not ask for more input
-- with Partial if it has been given Nothing once.
-- In this test we're making the decoder return 'Partial' to get more
-- input, and to get knownledge of the current position using 'BytesRead'.
-- Both of these operations, when used with the <|> operator, result internally
-- in that the decoder return with Partial and BytesRead multiple times,
-- in which case we need to keep track of if the user has passed Nothing to a
-- Partial in the past.
prop_partialOnlyOnce :: Property
prop_partialOnlyOnce = property $
let result = runGetIncremental (decoder <|> decoder)
decoder = do
0 <- bytesRead
_ <- getWord8 -- this will make the decoder return with Partial
return "shouldn't get here"
in case result of
-- we expect Partial followed by Fail
Partial k -> case k Nothing of -- push down a Nothing
Fail _ _ _ -> True
Partial _ -> error $ "partial twice! oh noes!"
Done _ _ _ -> error $ "we're not supposed to be done."
_ -> error $ "not partial, error!"
-- read too much
prop_readTooMuch :: (Eq a, Binary a) => a -> Bool
prop_readTooMuch x = mustThrowError $ x == a && x /= b
where
-- encode 'a', but try to read 'b' too
(a,b) = decode (encode x)
_types = [a,b]
-- In binary-0.5 the Get monad looked like
--
-- > data S = S {-# UNPACK #-} !B.ByteString
-- > L.ByteString
-- > {-# UNPACK #-} !Int64
-- >
-- > newtype Get a = Get { unGet :: S -> (# a, S #) }
--
-- with a helper function
--
-- > mkState :: L.ByteString -> Int64 -> S
-- > mkState l = case l of
-- > L.Empty -> S B.empty L.empty
-- > L.Chunk x xs -> S x xs
--
-- Note that mkState is strict in its first argument. This goes wrong in this
-- function:
--
-- > getBytes :: Int -> Get B.ByteString
-- > getBytes n = do
-- > S s ss bytes <- traceNumBytes n $ get
-- > if n <= B.length s
-- > then do let (consume,rest) = B.splitAt n s
-- > put $! S rest ss (bytes + fromIntegral n)
-- > return $! consume
-- > else
-- > case L.splitAt (fromIntegral n) (s `join` ss) of
-- > (consuming, rest) ->
-- > do let now = B.concat . L.toChunks $ consuming
-- > put $ mkState rest (bytes + fromIntegral n)
-- > -- forces the next chunk before this one is returned
-- > if (B.length now < n)
-- > then
-- > fail "too few bytes"
-- > else
-- > return now
--
-- Consider the else-branch of this function; suppose we ask for n bytes;
-- the call to L.splitAt gives us a lazy bytestring 'consuming' of precisely @n@
-- bytes (unless we don't have enough data, in which case we fail); but then
-- the strict evaluation of mkState on 'rest' means we look ahead too far.
--
-- Although this is all done completely differently in binary-0.7 it is
-- important that the same bug does not get introduced in some other way. The
-- test is basically the same test that already exists in this test suite,
-- verifying that
--
-- > decode . refragment . encode == id
--
-- However, we use a different 'refragment', one that introduces an exception
-- as the tail of the bytestring after rechunking. If we don't look ahead too
-- far then this should make no difference, but if we do then this will throw
-- an exception (for instance, in binary-0.5, this will throw an exception for
-- certain rechunkings, but not for others).
--
-- To make sure that the property holds no matter what refragmentation we use,
-- we test exhaustively for a single chunk, and all ways to break the string
-- into 2, 3 and 4 chunks.
prop_lookAheadIndepOfChunking :: (Eq a, Binary a) => a -> Property
prop_lookAheadIndepOfChunking testInput =
forAll (testCuts (L.length (encode testInput))) $
roundTrip testInput . rechunk
where
testCuts :: forall a. (Num a, Enum a) => a -> Gen [a]
testCuts len = elements $ [ [] ]
++ [ [i]
| i <- [0 .. len] ]
++ [ [i, j]
| i <- [0 .. len]
, j <- [0 .. len - i] ]
++ [ [i, j, k]
| i <- [0 .. len]
, j <- [0 .. len - i]
, k <- [0 .. len - i - j] ]
-- Rechunk a bytestring, leaving the tail as an exception rather than Empty
rechunk :: forall a. Integral a => [a] -> L.ByteString -> L.ByteString
rechunk cuts = fromChunks . cut cuts . B.concat . L.toChunks
where
cut :: [a] -> B.ByteString -> [B.ByteString]
cut [] bs = [bs]
cut (i:is) bs = let (bs0, bs1) = B.splitAt (fromIntegral i) bs
in bs0 : cut is bs1
fromChunks :: [B.ByteString] -> L.ByteString
fromChunks [] = error "Binary should not have to ask for this chunk!"
fromChunks (bs:bss) = L.Chunk bs (fromChunks bss)
-- String utilities
prop_getLazyByteString :: L.ByteString -> Property
prop_getLazyByteString lbs = forAll (choose (0, 2 * L.length lbs)) $ \len ->
let result = pushChunks (runGetIncremental decoder) lbs
decoder = getLazyByteString len
in case result of
Done unused _pos value ->
and [ value == L.take len lbs
, L.fromChunks [unused] == L.drop len lbs
]
Partial _ -> len > L.length lbs
_ -> False
prop_getLazyByteStringNul :: Word16 -> [Int] -> Property
prop_getLazyByteStringNul count0 fragments = count >= 0 ==>
forAll (choose (0, count)) $ \pos ->
let lbs = case L.splitAt pos (L.replicate count 65) of
(start,end) -> refragment fragments $ L.concat [start, L.singleton 0, end]
result = pushEndOfInput $ pushChunks (runGetIncremental getLazyByteStringNul) lbs
in case result of
Done unused pos' value ->
and [ value == L.take pos lbs
, pos + 1 == pos' -- 1 for the NUL
, L.fromChunks [unused] == L.drop (pos + 1) lbs
]
_ -> False
where
count = fromIntegral count0 -- to make the generated numbers a bit smaller
-- | Same as prop_getLazyByteStringNul, but without any NULL in the string.
prop_getLazyByteStringNul_noNul :: Word16 -> [Int] -> Property
prop_getLazyByteStringNul_noNul count0 fragments = count >= 0 ==>
let lbs = refragment fragments $ L.replicate count 65
result = pushEndOfInput $ pushChunks (runGetIncremental getLazyByteStringNul) lbs
in case result of
Fail _ _ _ -> True
_ -> False
where
count = fromIntegral count0 -- to make the generated numbers a bit smaller
prop_getRemainingLazyByteString :: L.ByteString -> Property
prop_getRemainingLazyByteString lbs = property $
let result = pushEndOfInput $ pushChunks (runGetIncremental getRemainingLazyByteString) lbs
in case result of
Done unused pos value ->
and [ value == lbs
, B.null unused
, fromIntegral pos == L.length lbs
]
_ -> False
-- sanity:
invariant_lbs :: L.ByteString -> Bool
invariant_lbs (L.Empty) = True
invariant_lbs (L.Chunk x xs) = not (B.null x) && invariant_lbs xs
prop_invariant :: (Binary a) => a -> Bool
prop_invariant = invariant_lbs . encode
-- refragment a lazy bytestring's chunks
refragment :: [Int] -> L.ByteString -> L.ByteString
refragment [] lbs = lbs
refragment (x:xs) lbs =
let x' = fromIntegral . (+1) . abs $ x
rest = refragment xs (L.drop x' lbs) in
L.append (L.fromChunks [B.concat . L.toChunks . L.take x' $ lbs]) rest
-- check identity of refragmentation
prop_refragment :: L.ByteString -> [Int] -> Bool
prop_refragment lbs xs = lbs == refragment xs lbs
-- check that refragmention still hold invariant
prop_refragment_inv :: L.ByteString -> [Int] -> Bool
prop_refragment_inv lbs xs = invariant_lbs $ refragment xs lbs
main :: IO ()
main = defaultMain tests
------------------------------------------------------------------------
genInteger :: Gen Integer
genInteger = do
b <- arbitrary
if b then genIntegerSmall else genIntegerSmall
genIntegerSmall :: Gen Integer
genIntegerSmall = arbitrary
genIntegerBig :: Gen Integer
genIntegerBig = do
x <- arbitrarySizedIntegral :: Gen Integer
-- arbitrarySizedIntegral generates numbers smaller than
-- (maxBound :: Word32), so let's make them bigger to better test
-- the Binary instance.
return (x + fromIntegral (maxBound :: Word32))
#ifdef HAS_NATURAL
genNatural :: Gen Natural
genNatural = do
b <- arbitrary
if b then genNaturalSmall else genNaturalBig
genNaturalSmall :: Gen Natural
genNaturalSmall = arbitrarySizedNatural
genNaturalBig :: Gen Natural
genNaturalBig = do
x <- arbitrarySizedNatural :: Gen Natural
-- arbitrarySizedNatural generates numbers smaller than
-- (maxBound :: Word64), so let's make them bigger to better test
-- the Binary instance.
return (x + fromIntegral (maxBound :: Word64))
#endif
------------------------------------------------------------------------
genFingerprint :: Gen Fingerprint
genFingerprint = liftM2 Fingerprint arbitrary arbitrary
------------------------------------------------------------------------
#ifdef HAS_FIXED_CONSTRUCTOR
fixedPut :: forall a. Fixed.HasResolution a => Fixed.Fixed a -> Put
fixedPut x = put (truncate (x * fromInteger (Fixed.resolution (undefined :: Maybe a))) :: Integer)
fixedGet :: forall a. Fixed.HasResolution a => Get (Fixed.Fixed a)
fixedGet = (\x -> fromInteger x / fromInteger (Fixed.resolution (undefined :: Maybe a))) `liftA` get
-- | Serialise using base >=4.7 and <4.7 methods agree
prop_fixed_ser :: Fixed.Fixed Fixed.E3 -> Bool
prop_fixed_ser x = runPut (put x) == runPut (fixedPut x)
-- | Serialised with base >=4.7, unserialised with base <4.7 method roundtrip
prop_fixed_constr_resolution :: Fixed.Fixed Fixed.E3 -> Bool
prop_fixed_constr_resolution x = runGet fixedGet (runPut (put x)) == x
-- | Serialised with base <4.7, unserialised with base >=4.7 method roundtrip
prop_fixed_resolution_constr :: Fixed.Fixed Fixed.E3 -> Bool
prop_fixed_resolution_constr x = runGet get (runPut (fixedPut x)) == x
#endif
------------------------------------------------------------------------
type T a = a -> Property
type B a = a -> Bool
p :: (Testable p) => p -> Property
p = property
test :: (Eq a, Binary a) => a -> Property
test a = forAll positiveList (roundTrip a . refragment)
test' :: (Show a, Arbitrary a) => String -> (a -> Property) -> ([a] -> Property) -> Test
test' desc prop propList =
testGroup desc [
testProperty desc prop,
testProperty ("[" ++ desc ++ "]") propList
]
testWithGen :: (Show a, Eq a, Binary a) => String -> Gen a -> Test
testWithGen desc gen =
testGroup desc [
testProperty desc (forAll gen test),
testProperty ("[" ++ desc ++ "]") (forAll (listOf gen) test)
]
positiveList :: Gen [Int]
positiveList = fmap (filter (/=0) . map abs) $ arbitrary
tests :: [Test]
tests =
[ testGroup "Utils"
[ testProperty "refragment id" (p prop_refragment)
, testProperty "refragment invariant" (p prop_refragment_inv)
]
, testGroup "Boundaries"
[ testProperty "read to much" (p (prop_readTooMuch :: B Word8))
, testProperty "read negative length" (p (prop_getByteString_negative :: T Int))
, -- Arbitrary test input
let testInput :: [Int] ; testInput = [0 .. 10]
in testProperty "look-ahead independent of chunking" (p (prop_lookAheadIndepOfChunking testInput))
]
, testGroup "Partial"
[ testProperty "partial" (p prop_partial)
, testProperty "fail" (p prop_fail)
, testProperty "bytesRead" (p prop_bytesRead)
, testProperty "partial only once" (p prop_partialOnlyOnce)
]
, testGroup "Model"
Action.tests
, testGroup "Primitives"
[ testProperty "Word8" (p prop_Word8)
, testProperty "Word16be" (p prop_Word16be)
, testProperty "Word16le" (p prop_Word16le)
, testProperty "Word16host" (p prop_Word16host)
, testProperty "Word32be" (p prop_Word32be)
, testProperty "Word32le" (p prop_Word32le)
, testProperty "Word32host" (p prop_Word32host)
, testProperty "Word64be" (p prop_Word64be)
, testProperty "Word64le" (p prop_Word64le)
, testProperty "Word64host" (p prop_Word64host)
, testProperty "Wordhost" (p prop_Wordhost)
-- Int
, testProperty "Int8" (p prop_Int8)
, testProperty "Int16be" (p prop_Int16be)
, testProperty "Int16le" (p prop_Int16le)
, testProperty "Int16host" (p prop_Int16host)
, testProperty "Int32be" (p prop_Int32be)
, testProperty "Int32le" (p prop_Int32le)
, testProperty "Int32host" (p prop_Int32host)
, testProperty "Int64be" (p prop_Int64be)
, testProperty "Int64le" (p prop_Int64le)
, testProperty "Int64host" (p prop_Int64host)
, testProperty "Inthost" (p prop_Inthost)
-- Float/Double
, testProperty "Floatbe" (p prop_Floatbe)
, testProperty "Floatle" (p prop_Floatle)
, testProperty "Floathost" (p prop_Floathost)
, testProperty "Doublebe" (p prop_Doublebe)
, testProperty "Doublele" (p prop_Doublele)
, testProperty "Doublehost" (p prop_Doublehost)
]
, testGroup "String utils"
[ testProperty "getLazyByteString" prop_getLazyByteString
, testProperty "getLazyByteStringNul" prop_getLazyByteStringNul
, testProperty "getLazyByteStringNul No Null" prop_getLazyByteStringNul_noNul
, testProperty "getRemainingLazyByteString" prop_getRemainingLazyByteString
]
, testGroup "Using Binary class, refragmented ByteString"
[ test' "()" (test :: T () ) test
, test' "Bool" (test :: T Bool ) test
, test' "Char" (test :: T Char ) test
, test' "Ordering" (test :: T Ordering ) test
, test' "Ratio Int" (test :: T (Ratio Int)) test
, test' "Word" (test :: T Word ) test
, test' "Word8" (test :: T Word8 ) test
, test' "Word16" (test :: T Word16) test
, test' "Word32" (test :: T Word32) test
, test' "Word64" (test :: T Word64) test
, test' "Int" (test :: T Int ) test
, test' "Int8" (test :: T Int8 ) test
, test' "Int16" (test :: T Int16) test
, test' "Int32" (test :: T Int32) test
, test' "Int64" (test :: T Int64) test
, testWithGen "Integer mixed" genInteger
, testWithGen "Integer small" genIntegerSmall
, testWithGen "Integer big" genIntegerBig
, test' "Fixed" (test :: T (Fixed.Fixed Fixed.E3) ) test
#ifdef HAS_NATURAL
, testWithGen "Natural mixed" genNatural
, testWithGen "Natural small" genNaturalSmall
, testWithGen "Natural big" genNaturalBig
#endif
, testWithGen "GHC.Fingerprint" genFingerprint
, test' "Float" (test :: T Float ) test
, test' "Double" (test :: T Double) test
, test' "((), ())" (test :: T ((), ()) ) test
, test' "(Word8, Word32)" (test :: T (Word8, Word32) ) test
, test' "(Int8, Int32)" (test :: T (Int8, Int32) ) test
, test' "(Int32, [Int])" (test :: T (Int32, [Int]) ) test
, test' "Maybe Int8" (test :: T (Maybe Int8) ) test
, test' "Either Int8 Int16" (test :: T (Either Int8 Int16) ) test
, test' "(Int, ByteString)"
(test :: T (Int, B.ByteString) ) test
, test' "[(Int, ByteString)]"
(test :: T [(Int, B.ByteString)] ) test
, test' "(Maybe Int64, Bool, [Int])"
(test :: T (Maybe Int64, Bool, [Int])) test
, test' "(Maybe Word8, Bool, [Int], Either Bool Word8)"
(test :: T (Maybe Word8, Bool, [Int], Either Bool Word8)) test
, test' "(Maybe Word16, Bool, [Int], Either Bool Word16, Int)"
(test :: T (Maybe Word16, Bool, [Int], Either Bool Word16, Int)) test
, test' "(Int,Int,Int,Int,Int,Int)"
(test :: T (Int,Int,Int,Int,Int,Int)) test
, test' "(Int,Int,Int,Int,Int,Int,Int)"
(test :: T (Int,Int,Int,Int,Int,Int,Int)) test
, test' "(Int,Int,Int,Int,Int,Int,Int,Int)"
(test :: T (Int,Int,Int,Int,Int,Int,Int,Int)) test
, test' "(Int,Int,Int,Int,Int,Int,Int,Int,Int)"
(test :: T (Int,Int,Int,Int,Int,Int,Int,Int,Int)) test
, test' "(Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)"
(test :: T (Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)) test
, test' "B.ByteString" (test :: T B.ByteString) test
, test' "L.ByteString" (test :: T L.ByteString) test
#if MIN_VERSION_bytestring(0,10,4)
, test' "ShortByteString" (test :: T ShortByteString) test
#endif
]
, testGroup "Invariants" $ map (uncurry testProperty)
[ ("B.ByteString invariant", p (prop_invariant :: B B.ByteString ))
, ("[B.ByteString] invariant", p (prop_invariant :: B [B.ByteString] ))
, ("L.ByteString invariant", p (prop_invariant :: B L.ByteString ))
, ("[L.ByteString] invariant", p (prop_invariant :: B [L.ByteString] ))
#if MIN_VERSION_bytestring(0,10,4)
, ("ShortByteString invariant", p (prop_invariant :: B ShortByteString ))
, ("[ShortByteString] invariant", p (prop_invariant :: B [ShortByteString] ))
#endif
]
#ifdef HAS_FIXED_CONSTRUCTOR
, testGroup "Fixed"
[ testProperty "Serialisation same" $ p prop_fixed_ser
, testProperty "MkFixed -> HasResolution" $ p prop_fixed_constr_resolution
, testProperty "HasResolution -> MkFixed" $ p prop_fixed_resolution_constr
]
#endif
, testTypeable
]
|