module Test.Validity.Hashable
( hashableSpecOnValid
, hashableSpecOnInvalid
, hashableSpec
, hashableSpecOnArbitrary
, hashableSpecOnGen
) where
import Data.Data
import Data.Hashable
import Control.Monad
import Test.Validity.Utils
import Data.GenValidity
import Test.Hspec
import Test.QuickCheck
hashableSpecOnValid
:: forall a.
(Show a, Eq a, Typeable a, GenValid a, Hashable a)
=> Spec
hashableSpecOnValid = hashableSpecOnGen @a genValid "valid"
hashableSpecOnInvalid
:: forall a.
(Show a, Eq a, Typeable a, GenInvalid a, Hashable a)
=> Spec
hashableSpecOnInvalid = hashableSpecOnGen @a genInvalid "invalid"
hashableSpec
:: forall a.
(Show a, Eq a, Typeable a, GenUnchecked a, Hashable a)
=> Spec
hashableSpec = hashableSpecOnGen @a genUnchecked "unchecked"
hashableSpecOnArbitrary
:: forall a.
(Show a, Eq a, Typeable a, Arbitrary a, Hashable a)
=> Spec
hashableSpecOnArbitrary = hashableSpecOnGen @a arbitrary "arbitrary"
hashableSpecOnGen
:: forall a.
(Show a, Eq a, Typeable a, Hashable a)
=> Gen a -> String -> Spec
hashableSpecOnGen gen genname = checkGen gen2 genname
where gen2 = (,) <$> gen <*> gen
checkGen
:: forall a.
(Show a, Eq a, Typeable a, Hashable a)
=> Gen (a, a) -> String -> Spec
checkGen gen genname = parallel $ do
let name = nameOf @a
hashablestr = (unwords
["hashWithSalt :: Int ->"
, name
, "-> Int"])
describe ("Hashable " ++ name) $ do
describe hashablestr $ do
it
(unwords
[ "satisfies (a == b) => (hashWithSalt n a) =="
,"(hashWithSalt n b), for every n and for"
, genname
, name
]) $
forAll gen $ \(a1, a2) ->
forAll arbitrary $ \int ->
when (a1 == a2) $
let hash = hashWithSalt int
in hash a1 `shouldBe` hash a2