serialise-0.1.0.0: tests/Tests/Negative.hs
module Tests.Negative
( testTree -- :: TestTree
) where
import Data.Monoid
import Data.Version
import Test.Tasty
import Test.Tasty.HUnit
import Codec.Serialise
import Codec.Serialise.Encoding
import Codec.CBOR.Write as CBOR.Write
--------------------------------------------------------------------------------
-- Tests and properties
testInvalidMaybe :: Assertion
testInvalidMaybe = assertIsBad "properly decoded invalid Maybe!" val
where
enc = encodeListLen 2 -- only 'ListLen 0' and 'ListLen 1' are used
val = badRoundTrip enc :: Failed (Maybe Int)
testInvalidEither :: Assertion
testInvalidEither = assertIsBad "properly decoded invalid Either!" val
where
-- expects a list of length two, with a tag of 0 or 1 only
enc = encodeListLen 2
<> encodeWord 2 -- invalid tag
<> encodeWord 0
val = badRoundTrip enc :: Failed (Either Int Int)
testInvalidVersion :: Assertion
testInvalidVersion = assertIsBad "properly decoded invalid Version!" val
where
-- expects a tag of 0 and length of 3, not 4
enc = encodeListLen 4
<> encodeWord 0 -- tag is zero
<> encodeWord 0
<> encodeWord 0
<> encodeWord 0
val = badRoundTrip enc :: Failed Version
--------------------------------------------------------------------------------
-- TestTree API
testTree :: TestTree
testTree = testGroup "Negative tests"
[ testCase "decoding invalid Maybe" testInvalidMaybe
, testCase "decoding invalid Either" testInvalidEither
, testCase "decoding invalid Version" testInvalidVersion
]
--------------------------------------------------------------------------------
-- Utilities
-- Simple utility to take an @'Encoding'@ and try to deserialise it as
-- some user specified type. Useful for writing 'bad' encoders that give
-- some bad output we attempt to deserialise.
type Failed a = Either DeserialiseFailure a
badRoundTrip :: Serialise a => Encoding -> Failed a
badRoundTrip enc = deserialiseOrFail (CBOR.Write.toLazyByteString enc)
-- | Check if a @'Failed' a@ actually failed.
didFail :: Failed a -> Bool
didFail (Left _) = True
didFail (Right _) = False
-- | Assert that a @'Failed' a@ actually failed.
assertIsBad :: String -> Failed a -> Assertion
assertIsBad msg v = assertBool msg (didFail v)