-- | Context
--
-- Intended for qualified import.
--
-- > import Test.Falsify
-- > import Test.Falsify.Context (Context)
-- > import qualified Test.Falsify.Context as Context
module Test.Falsify.Context (
    -- * Context
    Context(..)
  , Static(..)
  , Iteration(..)
  , Execution(..)
  ) where

-- | Contextual data for a single test case
--
-- Properties can access contextual data pertaining to the current test case in
-- a test run. An example of its use is varying the range of generated values
-- depending on how many tests we have already done, generating a smaller range
-- in the beginning but widening the range later on.
data Context = Context{
      Context -> Static
static    :: Static
    , Context -> Iteration
iteration :: Iteration
    , Context -> Execution
execution :: Execution
    }
  deriving stock (Int -> Context -> ShowS
[Context] -> ShowS
Context -> String
(Int -> Context -> ShowS)
-> (Context -> String) -> ([Context] -> ShowS) -> Show Context
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Context -> ShowS
showsPrec :: Int -> Context -> ShowS
$cshow :: Context -> String
show :: Context -> String
$cshowList :: [Context] -> ShowS
showList :: [Context] -> ShowS
Show, Context -> Context -> Bool
(Context -> Context -> Bool)
-> (Context -> Context -> Bool) -> Eq Context
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Context -> Context -> Bool
== :: Context -> Context -> Bool
$c/= :: Context -> Context -> Bool
/= :: Context -> Context -> Bool
Eq)

-- | Static context
--
-- The part of the context that does not change between test iterations.
data Static = Static{
      -- | Number of test cases to generate
      Static -> Word
tests :: Word

      -- | Number of shrinks allowed before failing a test
    , Static -> Maybe Word
maxShrinks :: Maybe Word

      -- | Maximum number of discarded tests per successful test
    , Static -> Word
maxRatio :: Word
    }
  deriving stock (Int -> Static -> ShowS
[Static] -> ShowS
Static -> String
(Int -> Static -> ShowS)
-> (Static -> String) -> ([Static] -> ShowS) -> Show Static
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Static -> ShowS
showsPrec :: Int -> Static -> ShowS
$cshow :: Static -> String
show :: Static -> String
$cshowList :: [Static] -> ShowS
showList :: [Static] -> ShowS
Show, Static -> Static -> Bool
(Static -> Static -> Bool)
-> (Static -> Static -> Bool) -> Eq Static
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Static -> Static -> Bool
== :: Static -> Static -> Bool
$c/= :: Static -> Static -> Bool
/= :: Static -> Static -> Bool
Eq)

-- | Iteration context
--
-- Information about the current test iteration specifically.
data Iteration = Iteration{
      -- | Number of current test case, 0-based
      Iteration -> Word
thisTest :: Word
    }
  deriving stock (Int -> Iteration -> ShowS
[Iteration] -> ShowS
Iteration -> String
(Int -> Iteration -> ShowS)
-> (Iteration -> String)
-> ([Iteration] -> ShowS)
-> Show Iteration
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Iteration -> ShowS
showsPrec :: Int -> Iteration -> ShowS
$cshow :: Iteration -> String
show :: Iteration -> String
$cshowList :: [Iteration] -> ShowS
showList :: [Iteration] -> ShowS
Show, Iteration -> Iteration -> Bool
(Iteration -> Iteration -> Bool)
-> (Iteration -> Iteration -> Bool) -> Eq Iteration
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Iteration -> Iteration -> Bool
== :: Iteration -> Iteration -> Bool
$c/= :: Iteration -> Iteration -> Bool
/= :: Iteration -> Iteration -> Bool
Eq)

-- | Test execution context
--
-- NOTE: This should not affect whether the test passes or fails; if it does,
-- you will get undefined shrinking behaviour.
data Execution =
    -- | Initial test execution
    Initial

    -- | Shrink step
    --
    -- We record the index of the shrink step (0-based)
  | Shrinking Word

    -- | Final test execution
    --
    -- We always end a test execution with one more final run, which is a repeat
    -- of the run that came just before it.
    --
    -- We record how many shrink steps we took in between 'Initial' and 'Final';
    -- this may be zero, if the initial test happened to be minimal already or
    -- shrinking is disabled.
  | Final Word
  deriving stock (Int -> Execution -> ShowS
[Execution] -> ShowS
Execution -> String
(Int -> Execution -> ShowS)
-> (Execution -> String)
-> ([Execution] -> ShowS)
-> Show Execution
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Execution -> ShowS
showsPrec :: Int -> Execution -> ShowS
$cshow :: Execution -> String
show :: Execution -> String
$cshowList :: [Execution] -> ShowS
showList :: [Execution] -> ShowS
Show, Execution -> Execution -> Bool
(Execution -> Execution -> Bool)
-> (Execution -> Execution -> Bool) -> Eq Execution
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Execution -> Execution -> Bool
== :: Execution -> Execution -> Bool
$c/= :: Execution -> Execution -> Bool
/= :: Execution -> Execution -> Bool
Eq)