packages feed

blockchain-0.0.0.1: test/TestUtil.hs

module TestUtil
    ( module X
    , Proxy.Proxy(..)
    , propWithSize
    , propNumTests
    , roundTripJSONSpec
    , safeJSONDeserializeSpec
    ) where

import           Test.Hspec               as X
import           Test.Hspec.QuickCheck    as X
import           Test.QuickCheck          as X hiding (Result, generate, labels, reason, theException)
import           Test.QuickCheck.Property as X

import           Control.DeepSeq
import qualified Data.Aeson               as Aeson
import qualified Data.ByteString          as BS
import qualified Data.Data                as Data
import           Data.Monoid              ((<>))
import qualified Data.Proxy               as Proxy

import           ArbitraryInstances       as X
import           TestData                 as X


propWithSize :: Testable prop => Int -> String -> prop -> Spec
propWithSize n tag = modifyMaxSize (const n) . prop tag

propNumTests :: Testable prop => Int -> String -> prop -> Spec
propNumTests n tag = modifyMaxSuccess (const n) . prop tag

-- Serialization Utils

roundTripJSONSpec :: (Arbitrary a, Aeson.FromJSON a, Aeson.ToJSON a, Data.Typeable a, Show a, Eq a) => Proxy.Proxy a -> Spec
roundTripJSONSpec proxy = prop ("should round-trip json serialize " <> tag) $ testRoundTripJSON proxy
  where
    tag = show (Data.typeRep proxy)

testRoundTripJSON :: (Aeson.FromJSON a, Aeson.ToJSON a, Show a, Eq a) => Proxy.Proxy a -> a -> Property
testRoundTripJSON _ x = Aeson.decode (Aeson.encode x) === Just x

safeJSONDeserializeSpec :: (Aeson.FromJSON a, Show a, Data.Typeable a) => Proxy.Proxy a -> Spec
safeJSONDeserializeSpec proxy = prop ("should be safe when deserializing " <> tag) $ testSafeJSONDeserialize proxy
  where
    tag = show (Data.typeRep proxy)

testSafeJSONDeserialize :: forall a. (Aeson.FromJSON a, Show a) => Proxy.Proxy a -> BS.ByteString -> Bool
testSafeJSONDeserialize _ bs = canEval $ show (Aeson.decodeStrict' json :: Maybe [a])
  where
    json = mconcat [ "[\"", bs, "\"]" ]

canEval :: NFData a => a -> Bool
canEval x = deepseq x True