{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} -- | Tests for RelativeValidity instances -- -- You will need @TypeApplications@ to use these. module Test.Validity.RelativeValidity ( relativeValiditySpec , relativeValidityImpliesValidA , relativeValidityImpliesValidB ) where import Data.Data import Data.GenRelativeValidity import Data.GenValidity import Test.Hspec import Test.QuickCheck import Test.Validity.Property.Utils import Test.Validity.Utils -- | A @Spec@ that specifies that @isValidFor@ implies @isValid@ -- -- In general it is a good idea to add this spec to your test suite if -- the @a@ and @b@ in @RelativeValidity a b@ also have a @Validity@ instance. -- -- Example usage: -- -- > relativeValiditySpec @MyDataFor @MyOtherData relativeValiditySpec :: forall a b. ( Typeable a , Typeable b , Show a , Show b , Validity a , Validity b , GenUnchecked a , GenUnchecked b , RelativeValidity a b ) => Spec relativeValiditySpec = parallel $ do let nameOne = nameOf @a nameTwo = nameOf @b describe ("RelativeValidity " ++ nameOne ++ " " ++ nameTwo) $ describe ("isValidFor :: " ++ nameOne ++ " -> " ++ nameTwo ++ " -> Bool") $ do it ("implies isValid " ++ nameOne ++ " for any " ++ nameTwo) $ relativeValidityImpliesValidA @a @b it ("implies isValid " ++ nameTwo ++ " for any " ++ nameOne) $ relativeValidityImpliesValidB @a @b -- | @isValidFor a b@ implies @isValid a@ for all @b@ relativeValidityImpliesValidA :: forall a b. ( Show a , Show b , Validity a , GenUnchecked a , GenUnchecked b , RelativeValidity a b ) => Property relativeValidityImpliesValidA = forAllUnchecked $ \(a :: a) -> forAllUnchecked $ \(b :: b) -> (a `isValidFor` b) ===> isValid a -- | @isValidFor a b@ implies @isValid b@ for all @a@ relativeValidityImpliesValidB :: forall a b. ( Show a , Show b , Validity b , GenUnchecked a , GenUnchecked b , RelativeValidity a b ) => Property relativeValidityImpliesValidB = forAllUnchecked $ \(a :: a) -> forAllUnchecked $ \(b :: b) -> (a `isValidFor` b) ===> isValid b