{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE ScopedTypeVariables #-} -- | Tests for Shrinking functions -- -- You will need @TypeApplications@ to use these. module Test.Validity.Shrinking ( shrinkValiditySpec , shrinkValidSpec , shrinkValidSpecWithLimit , shrinkInvalidSpec , shrinkValidPreservesValidOnGenValid , shrinkValidPreservesValidOnGenValidWithLimit , shrinkInvalidPreservesInvalidOnGenInvalid , shrinkPreservesValidOnGenValid , shrinkPreservesInvalidOnGenInvalid , shrinkValidPreservesValid , shrinkInvalidPreservesInvalid , shrinkingStaysValid , shrinkingStaysInvalid , shrinkingPreserves , shrinkUncheckedDoesNotShrinkToItself , shrinkUncheckedDoesNotShrinkToItselfWithLimit , shrinkValidDoesNotShrinkToItself , shrinkValidDoesNotShrinkToItselfWithLimit , shrinkInvalidDoesNotShrinkToItself , shrinkInvalidDoesNotShrinkToItselfWithLimit ) where import Data.Data import Data.GenValidity import Control.Monad import Test.Hspec import Test.QuickCheck import Test.Validity.Shrinking.Property import Test.Validity.Utils shrinkValiditySpec :: forall a. (Show a, Eq a, Typeable a, GenValid a, GenInvalid a) => Spec shrinkValiditySpec = do shrinkValidSpec @a shrinkInvalidSpec @a shrinkValidSpec :: forall a. (Show a, Eq a, Typeable a, GenValid a) => Spec shrinkValidSpec = describe ("shrinkValid :: " ++ nameOf @(a -> [a])) $ do it "preserves validity" $ forAll (genValid @a) $ \a -> forM_ (shrinkValid a) shouldBeValid it "never shrinks to itself for valid values" $ shrinkValidDoesNotShrinkToItself @a shrinkValidSpecWithLimit :: forall a. (Show a, Eq a, Typeable a, GenValid a) => Int -> Spec shrinkValidSpecWithLimit l = describe ("shrinkValid :: " ++ nameOf @(a -> [a])) $ do it (unwords ["preserves validity for the first", show l, "elements"]) $ forAll (genValid @a) $ \a -> forM_ (take l $ shrinkValid a) shouldBeValid it (unwords [ "never shrinks to itself for valid values for the first" , show l , "elements" ]) $ shrinkValidDoesNotShrinkToItselfWithLimit @a l shrinkInvalidSpec :: forall a. (Show a, Typeable a, GenInvalid a) => Spec shrinkInvalidSpec = describe ("shrinkInvalid :: " ++ nameOf @(a -> [a])) $ do it "preserves invalidity" $ forAll (genInvalid @a) $ \a -> forM_ (shrinkInvalid a) shouldBeInvalid shrinkValidPreservesValidOnGenValid :: forall a. (Show a, GenValid a) => Property shrinkValidPreservesValidOnGenValid = shrinkingStaysValid @a genValid shrinkValid shrinkValidPreservesValidOnGenValidWithLimit :: forall a. (Show a, GenValid a) => Int -> Property shrinkValidPreservesValidOnGenValidWithLimit = shrinkingStaysValidWithLimit @a genValid shrinkValid shrinkInvalidPreservesInvalidOnGenInvalid :: forall a. (Show a, GenInvalid a) => Property shrinkInvalidPreservesInvalidOnGenInvalid = shrinkingStaysInvalid @a genInvalid shrinkInvalid shrinkUncheckedDoesNotShrinkToItself :: forall a. (Show a, Eq a, GenUnchecked a) => Property shrinkUncheckedDoesNotShrinkToItself = shrinkDoesNotShrinkToItself @a shrinkUnchecked shrinkValidDoesNotShrinkToItself :: forall a. (Show a, Eq a, GenValid a) => Property shrinkValidDoesNotShrinkToItself = shrinkDoesNotShrinkToItself @a shrinkValid shrinkInvalidDoesNotShrinkToItself :: forall a. (Show a, Eq a, GenInvalid a) => Property shrinkInvalidDoesNotShrinkToItself = shrinkDoesNotShrinkToItself @a shrinkInvalid shrinkInvalidDoesNotShrinkToItselfWithLimit :: forall a. (Show a, Eq a, GenInvalid a) => Int -> Property shrinkInvalidDoesNotShrinkToItselfWithLimit = shrinkDoesNotShrinkToItselfWithLimit @a shrinkInvalid shrinkValidDoesNotShrinkToItselfWithLimit :: forall a. (Show a, Eq a, GenValid a) => Int -> Property shrinkValidDoesNotShrinkToItselfWithLimit = shrinkDoesNotShrinkToItselfWithLimit @a shrinkValid shrinkUncheckedDoesNotShrinkToItselfWithLimit :: forall a. (Show a, Eq a, GenUnchecked a) => Int -> Property shrinkUncheckedDoesNotShrinkToItselfWithLimit = shrinkDoesNotShrinkToItselfWithLimit @a shrinkUnchecked