    -- | This package lets you test Hedgehog properties with tasty.
    --
    -- Typical usage would look like this:
    --
    -- @
    -- testGroup "tasty-hedgehog tests" [
    --    testPropertyNamed "reverse involutive" "prop_reverse_involutive" prop_reverse_involutive
    --  , testPropertyNamed "sort idempotent"    "prop_sort_idempotent"    prop_sort_idempotent
    --  ]
    -- @
    --
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    module Test.Tasty.Hedgehog (
        testProperty
      , testPropertyNamed
      , fromGroup
      -- * Options you can pass in via tasty
      , HedgehogReplay(..)
      , HedgehogShowReplay(..)
      , HedgehogTestLimit(..)
      , HedgehogDiscardLimit(..)
      , HedgehogShrinkLimit(..)
      , HedgehogShrinkRetries(..)
      ) where

    import Data.Maybe (fromMaybe)
    import Data.Typeable

    import qualified Test.Tasty as T
    import qualified Test.Tasty.Providers as T
    import Test.Tasty.Options

    import Hedgehog
    import Hedgehog.Internal.Config (UseColor, detectColor)
    import Hedgehog.Internal.Property
    import Hedgehog.Internal.Runner as H
    import Hedgehog.Internal.Report
    import Hedgehog.Internal.Seed as Seed

    data HP = HP T.TestName (Maybe PropertyName) Property
      deriving (Typeable)

    -- | Create a 'T.TestTree' from a Hedgehog 'Property'.
    testProperty :: T.TestName -> Property -> T.TestTree
    testProperty :: TestName -> Property -> TestTree
    testProperty TestName
    name Property
    prop = TestName -> HP -> TestTree
    forall t. IsTest t => TestName -> t -> TestTree
    T.singleTest TestName
    name (TestName -> Maybe PropertyName -> Property -> HP
    HP TestName
    name Maybe PropertyName
    forall a. Maybe a
    Nothing Property
    prop)

    -- | `testPropertyNamed` @testName propertyName property@ creates a
    -- 'T.TestTree' from @property@ using @testName@ as the displayed
    -- description for the property. The @propertyName@ is used by Hedgehog
    -- when a failure occurs to provide instructions for how to re-run
    -- the property and should normally be set to a string representation
    -- of the @property@ argument.
    --
    -- @
    -- testPropertyNamed
    --  "reverse is involutive"
    --  "prop_reverse_involutive"
    --  prop_reverse_involutive
    -- @
    --
    -- @since 1.2.0.0
    testPropertyNamed :: T.TestName -> PropertyName -> Property -> T.TestTree
    testPropertyNamed :: TestName -> PropertyName -> Property -> TestTree
    testPropertyNamed TestName
    name PropertyName
    propName Property
    prop =
      TestName -> HP -> TestTree
    forall t. IsTest t => TestName -> t -> TestTree
    T.singleTest TestName
    name (TestName -> Maybe PropertyName -> Property -> HP
    HP TestName
    name (PropertyName -> Maybe PropertyName
    forall a. a -> Maybe a
    Just PropertyName
    propName) Property
    prop)

    -- | Create a 'T.TestTree' from a Hedgehog 'Group'.
    fromGroup :: Group -> T.TestTree
    fromGroup :: Group -> TestTree
    fromGroup Group
    group =
        TestName -> [TestTree] -> TestTree
    T.testGroup (GroupName -> TestName
    unGroupName (GroupName -> TestName) -> GroupName -> TestName
    forall a b. (a -> b) -> a -> b
    $ Group -> GroupName
    groupName Group
    group) ([TestTree] -> TestTree) -> [TestTree] -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          ((PropertyName, Property) -> TestTree)
    -> [(PropertyName, Property)] -> [TestTree]
    forall a b. (a -> b) -> [a] -> [b]
    map (PropertyName, Property) -> TestTree
    mkTestTree (Group -> [(PropertyName, Property)]
    groupProperties Group
    group)
      where
        mkTestTree :: (PropertyName, Property) -> T.TestTree
        mkTestTree :: (PropertyName, Property) -> TestTree
    mkTestTree (PropertyName
    propName, Property
    prop) = TestName -> Property -> TestTree
    testProperty (PropertyName -> TestName
    unPropertyName PropertyName
    propName) Property
    prop

    -- | The replay token to use for replaying a previous test run
    newtype HedgehogReplay = HedgehogReplay (Maybe (Skip, Seed))
      deriving (Typeable)

    instance IsOption HedgehogReplay where
      defaultValue :: HedgehogReplay
    defaultValue = Maybe (Skip, Seed) -> HedgehogReplay
    HedgehogReplay Maybe (Skip, Seed)
    forall a. Maybe a
    Nothing
      parseValue :: TestName -> Maybe HedgehogReplay
    parseValue TestName
    v = Maybe (Skip, Seed) -> HedgehogReplay
    HedgehogReplay (Maybe (Skip, Seed) -> HedgehogReplay)
    -> ((Skip, Seed) -> Maybe (Skip, Seed))
    -> (Skip, Seed)
    -> HedgehogReplay
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Skip, Seed) -> Maybe (Skip, Seed)
    forall a. a -> Maybe a
    Just ((Skip, Seed) -> HedgehogReplay)
    -> Maybe (Skip, Seed) -> Maybe HedgehogReplay
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Skip, Seed)
    replay
        -- Reads a replay token in the form "{skip} {seed}"
        where replay :: Maybe (Skip, Seed)
    replay = (,) (Skip -> Seed -> (Skip, Seed))
    -> Maybe Skip -> Maybe (Seed -> (Skip, Seed))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> TestName -> Maybe Skip
    skipDecompress ([TestName] -> TestName
    unwords [TestName]
    skip) Maybe (Seed -> (Skip, Seed)) -> Maybe Seed -> Maybe (Skip, Seed)
    forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> TestName -> Maybe Seed
    forall a. Read a => TestName -> Maybe a
    safeRead ([TestName] -> TestName
    unwords [TestName]
    seed)
              ([TestName]
    skip, [TestName]
    seed) = Int -> [TestName] -> ([TestName], [TestName])
    forall a. Int -> [a] -> ([a], [a])
    splitAt Int
    1 ([TestName] -> ([TestName], [TestName]))
    -> [TestName] -> ([TestName], [TestName])
    forall a b. (a -> b) -> a -> b
    $ TestName -> [TestName]
    words TestName
    v
      optionName :: Tagged HedgehogReplay TestName
    optionName = TestName -> Tagged HedgehogReplay TestName
    forall a. a -> Tagged HedgehogReplay a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-replay"
      optionHelp :: Tagged HedgehogReplay TestName
    optionHelp = TestName -> Tagged HedgehogReplay TestName
    forall a. a -> Tagged HedgehogReplay a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Replay token to use for replaying a previous test run"

    -- | If a test case fails, show a replay token for replaying tests
    newtype HedgehogShowReplay = HedgehogShowReplay Bool
      deriving (Typeable)

    instance IsOption HedgehogShowReplay where
      defaultValue :: HedgehogShowReplay
    defaultValue = Bool -> HedgehogShowReplay
    HedgehogShowReplay Bool
    True
      parseValue :: TestName -> Maybe HedgehogShowReplay
    parseValue = (Bool -> HedgehogShowReplay)
    -> Maybe Bool -> Maybe HedgehogShowReplay
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Bool -> HedgehogShowReplay
    HedgehogShowReplay (Maybe Bool -> Maybe HedgehogShowReplay)
    -> (TestName -> Maybe Bool) -> TestName -> Maybe HedgehogShowReplay
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestName -> Maybe Bool
    forall a. Read a => TestName -> Maybe a
    safeRead
      optionName :: Tagged HedgehogShowReplay TestName
    optionName = TestName -> Tagged HedgehogShowReplay TestName
    forall a. a -> Tagged HedgehogShowReplay a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-show-replay"
      optionHelp :: Tagged HedgehogShowReplay TestName
    optionHelp = TestName -> Tagged HedgehogShowReplay TestName
    forall a. a -> Tagged HedgehogShowReplay a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Show a replay token for replaying tests"

    -- | The number of successful test cases required before Hedgehog will pass a test
    newtype HedgehogTestLimit = HedgehogTestLimit (Maybe TestLimit)
      deriving (HedgehogTestLimit -> HedgehogTestLimit -> Bool
    (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> Eq HedgehogTestLimit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    == :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    $c/= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    /= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    Eq, Eq HedgehogTestLimit
    Eq HedgehogTestLimit =>
    (HedgehogTestLimit -> HedgehogTestLimit -> Ordering)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> Bool)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit)
    -> (HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit)
    -> Ord HedgehogTestLimit
    HedgehogTestLimit -> HedgehogTestLimit -> Bool
    HedgehogTestLimit -> HedgehogTestLimit -> Ordering
    HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: HedgehogTestLimit -> HedgehogTestLimit -> Ordering
    compare :: HedgehogTestLimit -> HedgehogTestLimit -> Ordering
    $c< :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    < :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    $c<= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    <= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    $c> :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    > :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    $c>= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    >= :: HedgehogTestLimit -> HedgehogTestLimit -> Bool
    $cmax :: HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit
    max :: HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit
    $cmin :: HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit
    min :: HedgehogTestLimit -> HedgehogTestLimit -> HedgehogTestLimit
    Ord, Int -> HedgehogTestLimit -> ShowS
    [HedgehogTestLimit] -> ShowS
    HedgehogTestLimit -> TestName
    (Int -> HedgehogTestLimit -> ShowS)
    -> (HedgehogTestLimit -> TestName)
    -> ([HedgehogTestLimit] -> ShowS)
    -> Show HedgehogTestLimit
    forall a.
    (Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HedgehogTestLimit -> ShowS
    showsPrec :: Int -> HedgehogTestLimit -> ShowS
    $cshow :: HedgehogTestLimit -> TestName
    show :: HedgehogTestLimit -> TestName
    $cshowList :: [HedgehogTestLimit] -> ShowS
    showList :: [HedgehogTestLimit] -> ShowS
    Show, Typeable)

    instance IsOption HedgehogTestLimit where
      defaultValue :: HedgehogTestLimit
    defaultValue = Maybe TestLimit -> HedgehogTestLimit
    HedgehogTestLimit Maybe TestLimit
    forall a. Maybe a
    Nothing
      parseValue :: TestName -> Maybe HedgehogTestLimit
    parseValue = (Int -> HedgehogTestLimit) -> Maybe Int -> Maybe HedgehogTestLimit
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe TestLimit -> HedgehogTestLimit
    HedgehogTestLimit (Maybe TestLimit -> HedgehogTestLimit)
    -> (Int -> Maybe TestLimit) -> Int -> HedgehogTestLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestLimit -> Maybe TestLimit
    forall a. a -> Maybe a
    Just (TestLimit -> Maybe TestLimit)
    -> (Int -> TestLimit) -> Int -> Maybe TestLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> TestLimit
    TestLimit) (Maybe Int -> Maybe HedgehogTestLimit)
    -> (TestName -> Maybe Int) -> TestName -> Maybe HedgehogTestLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestName -> Maybe Int
    forall a. Read a => TestName -> Maybe a
    safeRead
      optionName :: Tagged HedgehogTestLimit TestName
    optionName = TestName -> Tagged HedgehogTestLimit TestName
    forall a. a -> Tagged HedgehogTestLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-tests"
      optionHelp :: Tagged HedgehogTestLimit TestName
    optionHelp = TestName -> Tagged HedgehogTestLimit TestName
    forall a. a -> Tagged HedgehogTestLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Number of successful test cases required before Hedgehog will pass a test"

    -- | The number of discarded cases allowed before Hedgehog will fail a test
    newtype HedgehogDiscardLimit = HedgehogDiscardLimit (Maybe DiscardLimit)
      deriving (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> Eq HedgehogDiscardLimit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    == :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    $c/= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    /= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    Eq, Eq HedgehogDiscardLimit
    Eq HedgehogDiscardLimit =>
    (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Ordering)
    -> (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> (HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool)
    -> (HedgehogDiscardLimit
        -> HedgehogDiscardLimit -> HedgehogDiscardLimit)
    -> (HedgehogDiscardLimit
        -> HedgehogDiscardLimit -> HedgehogDiscardLimit)
    -> Ord HedgehogDiscardLimit
    HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    HedgehogDiscardLimit -> HedgehogDiscardLimit -> Ordering
    HedgehogDiscardLimit
    -> HedgehogDiscardLimit -> HedgehogDiscardLimit
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Ordering
    compare :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Ordering
    $c< :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    < :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    $c<= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    <= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    $c> :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    > :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    $c>= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    >= :: HedgehogDiscardLimit -> HedgehogDiscardLimit -> Bool
    $cmax :: HedgehogDiscardLimit
    -> HedgehogDiscardLimit -> HedgehogDiscardLimit
    max :: HedgehogDiscardLimit
    -> HedgehogDiscardLimit -> HedgehogDiscardLimit
    $cmin :: HedgehogDiscardLimit
    -> HedgehogDiscardLimit -> HedgehogDiscardLimit
    min :: HedgehogDiscardLimit
    -> HedgehogDiscardLimit -> HedgehogDiscardLimit
    Ord, Int -> HedgehogDiscardLimit -> ShowS
    [HedgehogDiscardLimit] -> ShowS
    HedgehogDiscardLimit -> TestName
    (Int -> HedgehogDiscardLimit -> ShowS)
    -> (HedgehogDiscardLimit -> TestName)
    -> ([HedgehogDiscardLimit] -> ShowS)
    -> Show HedgehogDiscardLimit
    forall a.
    (Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HedgehogDiscardLimit -> ShowS
    showsPrec :: Int -> HedgehogDiscardLimit -> ShowS
    $cshow :: HedgehogDiscardLimit -> TestName
    show :: HedgehogDiscardLimit -> TestName
    $cshowList :: [HedgehogDiscardLimit] -> ShowS
    showList :: [HedgehogDiscardLimit] -> ShowS
    Show, Typeable)

    instance IsOption HedgehogDiscardLimit where
      defaultValue :: HedgehogDiscardLimit
    defaultValue = Maybe DiscardLimit -> HedgehogDiscardLimit
    HedgehogDiscardLimit Maybe DiscardLimit
    forall a. Maybe a
    Nothing
      parseValue :: TestName -> Maybe HedgehogDiscardLimit
    parseValue = (Int -> HedgehogDiscardLimit)
    -> Maybe Int -> Maybe HedgehogDiscardLimit
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe DiscardLimit -> HedgehogDiscardLimit
    HedgehogDiscardLimit (Maybe DiscardLimit -> HedgehogDiscardLimit)
    -> (Int -> Maybe DiscardLimit) -> Int -> HedgehogDiscardLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DiscardLimit -> Maybe DiscardLimit
    forall a. a -> Maybe a
    Just (DiscardLimit -> Maybe DiscardLimit)
    -> (Int -> DiscardLimit) -> Int -> Maybe DiscardLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> DiscardLimit
    DiscardLimit) (Maybe Int -> Maybe HedgehogDiscardLimit)
    -> (TestName -> Maybe Int)
    -> TestName
    -> Maybe HedgehogDiscardLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestName -> Maybe Int
    forall a. Read a => TestName -> Maybe a
    safeRead
      optionName :: Tagged HedgehogDiscardLimit TestName
    optionName = TestName -> Tagged HedgehogDiscardLimit TestName
    forall a. a -> Tagged HedgehogDiscardLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-discards"
      optionHelp :: Tagged HedgehogDiscardLimit TestName
    optionHelp = TestName -> Tagged HedgehogDiscardLimit TestName
    forall a. a -> Tagged HedgehogDiscardLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Number of discarded cases allowed before Hedgehog will fail a test"

    -- | The number of shrinks allowed before Hedgehog will fail a test
    newtype HedgehogShrinkLimit = HedgehogShrinkLimit (Maybe ShrinkLimit)
      deriving (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> Eq HedgehogShrinkLimit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    == :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    $c/= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    /= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    Eq, Eq HedgehogShrinkLimit
    Eq HedgehogShrinkLimit =>
    (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Ordering)
    -> (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> (HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool)
    -> (HedgehogShrinkLimit
        -> HedgehogShrinkLimit -> HedgehogShrinkLimit)
    -> (HedgehogShrinkLimit
        -> HedgehogShrinkLimit -> HedgehogShrinkLimit)
    -> Ord HedgehogShrinkLimit
    HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    HedgehogShrinkLimit -> HedgehogShrinkLimit -> Ordering
    HedgehogShrinkLimit -> HedgehogShrinkLimit -> HedgehogShrinkLimit
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Ordering
    compare :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Ordering
    $c< :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    < :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    $c<= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    <= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    $c> :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    > :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    $c>= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    >= :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> Bool
    $cmax :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> HedgehogShrinkLimit
    max :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> HedgehogShrinkLimit
    $cmin :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> HedgehogShrinkLimit
    min :: HedgehogShrinkLimit -> HedgehogShrinkLimit -> HedgehogShrinkLimit
    Ord, Int -> HedgehogShrinkLimit -> ShowS
    [HedgehogShrinkLimit] -> ShowS
    HedgehogShrinkLimit -> TestName
    (Int -> HedgehogShrinkLimit -> ShowS)
    -> (HedgehogShrinkLimit -> TestName)
    -> ([HedgehogShrinkLimit] -> ShowS)
    -> Show HedgehogShrinkLimit
    forall a.
    (Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HedgehogShrinkLimit -> ShowS
    showsPrec :: Int -> HedgehogShrinkLimit -> ShowS
    $cshow :: HedgehogShrinkLimit -> TestName
    show :: HedgehogShrinkLimit -> TestName
    $cshowList :: [HedgehogShrinkLimit] -> ShowS
    showList :: [HedgehogShrinkLimit] -> ShowS
    Show, Typeable)

    instance IsOption HedgehogShrinkLimit where
      defaultValue :: HedgehogShrinkLimit
    defaultValue = Maybe ShrinkLimit -> HedgehogShrinkLimit
    HedgehogShrinkLimit Maybe ShrinkLimit
    forall a. Maybe a
    Nothing
      parseValue :: TestName -> Maybe HedgehogShrinkLimit
    parseValue = (Int -> HedgehogShrinkLimit)
    -> Maybe Int -> Maybe HedgehogShrinkLimit
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe ShrinkLimit -> HedgehogShrinkLimit
    HedgehogShrinkLimit (Maybe ShrinkLimit -> HedgehogShrinkLimit)
    -> (Int -> Maybe ShrinkLimit) -> Int -> HedgehogShrinkLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShrinkLimit -> Maybe ShrinkLimit
    forall a. a -> Maybe a
    Just (ShrinkLimit -> Maybe ShrinkLimit)
    -> (Int -> ShrinkLimit) -> Int -> Maybe ShrinkLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> ShrinkLimit
    ShrinkLimit) (Maybe Int -> Maybe HedgehogShrinkLimit)
    -> (TestName -> Maybe Int) -> TestName -> Maybe HedgehogShrinkLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestName -> Maybe Int
    forall a. Read a => TestName -> Maybe a
    safeRead
      optionName :: Tagged HedgehogShrinkLimit TestName
    optionName = TestName -> Tagged HedgehogShrinkLimit TestName
    forall a. a -> Tagged HedgehogShrinkLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-shrinks"
      optionHelp :: Tagged HedgehogShrinkLimit TestName
    optionHelp = TestName -> Tagged HedgehogShrinkLimit TestName
    forall a. a -> Tagged HedgehogShrinkLimit a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Number of shrinks allowed before Hedgehog will fail a test"

    -- | The number of times to re-run a test during shrinking
    newtype HedgehogShrinkRetries = HedgehogShrinkRetries (Maybe ShrinkRetries)
      deriving (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> Eq HedgehogShrinkRetries
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    == :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    $c/= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    /= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    Eq, Eq HedgehogShrinkRetries
    Eq HedgehogShrinkRetries =>
    (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Ordering)
    -> (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> (HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool)
    -> (HedgehogShrinkRetries
        -> HedgehogShrinkRetries -> HedgehogShrinkRetries)
    -> (HedgehogShrinkRetries
        -> HedgehogShrinkRetries -> HedgehogShrinkRetries)
    -> Ord HedgehogShrinkRetries
    HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    HedgehogShrinkRetries -> HedgehogShrinkRetries -> Ordering
    HedgehogShrinkRetries
    -> HedgehogShrinkRetries -> HedgehogShrinkRetries
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Ordering
    compare :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Ordering
    $c< :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    < :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    $c<= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    <= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    $c> :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    > :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    $c>= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    >= :: HedgehogShrinkRetries -> HedgehogShrinkRetries -> Bool
    $cmax :: HedgehogShrinkRetries
    -> HedgehogShrinkRetries -> HedgehogShrinkRetries
    max :: HedgehogShrinkRetries
    -> HedgehogShrinkRetries -> HedgehogShrinkRetries
    $cmin :: HedgehogShrinkRetries
    -> HedgehogShrinkRetries -> HedgehogShrinkRetries
    min :: HedgehogShrinkRetries
    -> HedgehogShrinkRetries -> HedgehogShrinkRetries
    Ord, Int -> HedgehogShrinkRetries -> ShowS
    [HedgehogShrinkRetries] -> ShowS
    HedgehogShrinkRetries -> TestName
    (Int -> HedgehogShrinkRetries -> ShowS)
    -> (HedgehogShrinkRetries -> TestName)
    -> ([HedgehogShrinkRetries] -> ShowS)
    -> Show HedgehogShrinkRetries
    forall a.
    (Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HedgehogShrinkRetries -> ShowS
    showsPrec :: Int -> HedgehogShrinkRetries -> ShowS
    $cshow :: HedgehogShrinkRetries -> TestName
    show :: HedgehogShrinkRetries -> TestName
    $cshowList :: [HedgehogShrinkRetries] -> ShowS
    showList :: [HedgehogShrinkRetries] -> ShowS
    Show, Typeable)

    instance IsOption HedgehogShrinkRetries where
      defaultValue :: HedgehogShrinkRetries
    defaultValue = Maybe ShrinkRetries -> HedgehogShrinkRetries
    HedgehogShrinkRetries Maybe ShrinkRetries
    forall a. Maybe a
    Nothing
      parseValue :: TestName -> Maybe HedgehogShrinkRetries
    parseValue = (Int -> HedgehogShrinkRetries)
    -> Maybe Int -> Maybe HedgehogShrinkRetries
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe ShrinkRetries -> HedgehogShrinkRetries
    HedgehogShrinkRetries (Maybe ShrinkRetries -> HedgehogShrinkRetries)
    -> (Int -> Maybe ShrinkRetries) -> Int -> HedgehogShrinkRetries
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShrinkRetries -> Maybe ShrinkRetries
    forall a. a -> Maybe a
    Just (ShrinkRetries -> Maybe ShrinkRetries)
    -> (Int -> ShrinkRetries) -> Int -> Maybe ShrinkRetries
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> ShrinkRetries
    ShrinkRetries) (Maybe Int -> Maybe HedgehogShrinkRetries)
    -> (TestName -> Maybe Int)
    -> TestName
    -> Maybe HedgehogShrinkRetries
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TestName -> Maybe Int
    forall a. Read a => TestName -> Maybe a
    safeRead
      optionName :: Tagged HedgehogShrinkRetries TestName
    optionName = TestName -> Tagged HedgehogShrinkRetries TestName
    forall a. a -> Tagged HedgehogShrinkRetries a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "hedgehog-retries"
      optionHelp :: Tagged HedgehogShrinkRetries TestName
    optionHelp = TestName -> Tagged HedgehogShrinkRetries TestName
    forall a. a -> Tagged HedgehogShrinkRetries a
    forall (m :: * -> *) a. Monad m => a -> m a
    return TestName
    "Number of times to re-run a test during shrinking"

    propertyTestLimit :: PropertyConfig -> TestLimit
    propertyTestLimit :: PropertyConfig -> TestLimit
    propertyTestLimit =
      let
        getTestLimit :: TerminationCriteria -> TestLimit
    getTestLimit (EarlyTermination Confidence
    _ TestLimit
    tests) = TestLimit
    tests
        getTestLimit (NoEarlyTermination Confidence
    _ TestLimit
    tests) = TestLimit
    tests
        getTestLimit (NoConfidenceTermination TestLimit
    tests) = TestLimit
    tests
      in
        TerminationCriteria -> TestLimit
    getTestLimit (TerminationCriteria -> TestLimit)
    -> (PropertyConfig -> TerminationCriteria)
    -> PropertyConfig
    -> TestLimit
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PropertyConfig -> TerminationCriteria
    propertyTerminationCriteria

    reportToProgress :: PropertyConfig
                     -> Report Progress
                     -> T.Progress
    reportToProgress :: PropertyConfig -> Report Progress -> Progress
    reportToProgress PropertyConfig
    config Report{
        reportTests :: forall a. Report a -> TestCount
    reportTests = TestCount
    testsDone,
        reportStatus :: forall a. Report a -> a
    reportStatus = Progress
    status
      } =
      let
        TestLimit Int
    testLimit = PropertyConfig -> TestLimit
    propertyTestLimit PropertyConfig
    config
        ShrinkLimit Int
    shrinkLimit = PropertyConfig -> ShrinkLimit
    propertyShrinkLimit PropertyConfig
    config
        ratio :: a -> a -> a
    ratio a
    x a
    y = a
    1.0 a -> a -> a
    forall a. Num a => a -> a -> a
    * a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    x a -> a -> a
    forall a. Fractional a => a -> a -> a
    / a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    y
      in
        -- TODO add details for tests run / discarded / shrunk
        case Progress
    status of
          Progress
    Running ->
            TestName -> Float -> Progress
    T.Progress TestName
    "Running" (TestCount -> Int -> Float
    forall {a} {a} {a}.
    (Fractional a, Integral a, Integral a) =>
    a -> a -> a
    ratio TestCount
    testsDone Int
    testLimit)
          Shrinking FailureReport
    fr ->
            TestName -> Float -> Progress
    T.Progress TestName
    "Shrinking" (ShrinkCount -> Int -> Float
    forall {a} {a} {a}.
    (Fractional a, Integral a, Integral a) =>
    a -> a -> a
    ratio (FailureReport -> ShrinkCount
    failureShrinks FailureReport
    fr) Int
    shrinkLimit)

    reportOutput :: Bool
                 -> UseColor
                 -> T.TestName
                 -> Maybe PropertyName
                 -> Report Result
                 -> IO String
    reportOutput :: Bool
    -> UseColor
    -> TestName
    -> Maybe PropertyName
    -> Report Result
    -> IO TestName
    reportOutput Bool
    showReplay UseColor
    useColor TestName
    testName Maybe PropertyName
    name Report Result
    report = do
      s <- UseColor -> Maybe PropertyName -> Report Result -> IO TestName
    forall (m :: * -> *).
    MonadIO m =>
    UseColor -> Maybe PropertyName -> Report Result -> m TestName
    renderResult UseColor
    useColor Maybe PropertyName
    name Report Result
    report
      pure $ case reportStatus report of
        Failed FailureReport
    fr ->
          let
            count :: TestCount
    count = Report Result -> TestCount
    forall a. Report a -> TestCount
    reportTests Report Result
    report
            seed :: Seed
    seed = Report Result -> Seed
    forall a. Report a -> Seed
    reportSeed Report Result
    report
            discards :: DiscardCount
    discards = Report Result -> DiscardCount
    forall a. Report a -> DiscardCount
    reportDiscards Report Result
    report
            shrinkPath :: ShrinkPath
    shrinkPath = FailureReport -> ShrinkPath
    failureShrinkPath FailureReport
    fr
            replayStr :: TestName
    replayStr =
              if Bool
    showReplay
              then
                TestName
    "\nUse \"--pattern \'$NF ~ /" TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                TestName
    testName TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                TestName
    "/\' --hedgehog-replay \'" TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                Skip -> TestName
    skipCompress (TestCount -> DiscardCount -> ShrinkPath -> Skip
    SkipToShrink TestCount
    count DiscardCount
    discards ShrinkPath
    shrinkPath) TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                TestName
    " " TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                Seed -> TestName
    forall a. Show a => a -> TestName
    show Seed
    seed TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++
                TestName
    "\'\" to reproduce from the command-line."
              else TestName
    ""
          in
            TestName
    s TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TestName
    replayStr TestName -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ TestName
    "\n"
        Result
    _ -> TestName
    s

    instance T.IsTest HP where
      testOptions :: Tagged HP [OptionDescription]
    testOptions =
        [OptionDescription] -> Tagged HP [OptionDescription]
    forall a. a -> Tagged HP a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [ Proxy HedgehogReplay -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogReplay
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogReplay)
               , Proxy HedgehogShowReplay -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogShowReplay
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogShowReplay)
               , Proxy HedgehogTestLimit -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogTestLimit
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogTestLimit)
               , Proxy HedgehogDiscardLimit -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogDiscardLimit
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogDiscardLimit)
               , Proxy HedgehogShrinkLimit -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogShrinkLimit
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogShrinkLimit)
               , Proxy HedgehogShrinkRetries -> OptionDescription
    forall v. IsOption v => Proxy v -> OptionDescription
    Option (Proxy HedgehogShrinkRetries
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy HedgehogShrinkRetries)
               ]

      run :: OptionSet -> HP -> (Progress -> IO ()) -> IO Result
    run OptionSet
    opts (HP TestName
    testName Maybe PropertyName
    name (Property PropertyConfig
    pConfig PropertyT IO ()
    pTest)) Progress -> IO ()
    yieldProgress = do
        useColor <- IO UseColor
    forall (m :: * -> *). MonadIO m => m UseColor
    detectColor
        let
          HedgehogReplay         replay = lookupOption opts
          HedgehogShowReplay showReplay = lookupOption opts
          HedgehogTestLimit       mTests = lookupOption opts
          HedgehogDiscardLimit mDiscards = lookupOption opts
          HedgehogShrinkLimit   mShrinks = lookupOption opts
          HedgehogShrinkRetries mRetries = lookupOption opts
          config =
            DiscardLimit
    -> ShrinkLimit
    -> ShrinkRetries
    -> TerminationCriteria
    -> Maybe Skip
    -> PropertyConfig
    PropertyConfig
              (DiscardLimit -> Maybe DiscardLimit -> DiscardLimit
    forall a. a -> Maybe a -> a
    fromMaybe (PropertyConfig -> DiscardLimit
    propertyDiscardLimit PropertyConfig
    pConfig) Maybe DiscardLimit
    mDiscards)
              (ShrinkLimit -> Maybe ShrinkLimit -> ShrinkLimit
    forall a. a -> Maybe a -> a
    fromMaybe (PropertyConfig -> ShrinkLimit
    propertyShrinkLimit PropertyConfig
    pConfig) Maybe ShrinkLimit
    mShrinks)
              (ShrinkRetries -> Maybe ShrinkRetries -> ShrinkRetries
    forall a. a -> Maybe a -> a
    fromMaybe (PropertyConfig -> ShrinkRetries
    propertyShrinkRetries PropertyConfig
    pConfig) Maybe ShrinkRetries
    mRetries)
              (TestLimit -> TerminationCriteria
    NoConfidenceTermination (TestLimit -> TerminationCriteria)
    -> TestLimit -> TerminationCriteria
    forall a b. (a -> b) -> a -> b
    $ TestLimit -> Maybe TestLimit -> TestLimit
    forall a. a -> Maybe a -> a
    fromMaybe (PropertyConfig -> TestLimit
    propertyTestLimit PropertyConfig
    pConfig) Maybe TestLimit
    mTests)
              (Maybe Skip
    -> ((Skip, Seed) -> Maybe Skip) -> Maybe (Skip, Seed) -> Maybe Skip
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Maybe Skip
    forall a. Maybe a
    Nothing (Skip -> Maybe Skip
    forall a. a -> Maybe a
    Just (Skip -> Maybe Skip)
    -> ((Skip, Seed) -> Skip) -> (Skip, Seed) -> Maybe Skip
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Skip, Seed) -> Skip
    forall a b. (a, b) -> a
    fst) Maybe (Skip, Seed)
    replay)

        randSeed <- Seed.random
        let seed = Seed -> ((Skip, Seed) -> Seed) -> Maybe (Skip, Seed) -> Seed
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Seed
    randSeed (Skip, Seed) -> Seed
    forall a b. (a, b) -> b
    snd Maybe (Skip, Seed)
    replay

        report <- checkReport config 0 seed pTest (yieldProgress . reportToProgress config)

        let
          resultFn = if Report Result -> Result
    forall a. Report a -> a
    reportStatus Report Result
    report Result -> Result -> Bool
    forall a. Eq a => a -> a -> Bool
    == Result
    OK
                     then TestName -> Result
    T.testPassed
                     else TestName -> Result
    T.testFailed

        out <- reportOutput showReplay useColor testName name report
        return $ resultFn out