{-|
Module      : Standard
Description : Standard test operations for TLT
Copyright   : (c) John Maraist, 2022
License     : GPL3
Maintainer  : haskell-tlt@maraist.org
Stability   : experimental
Portability : POSIX

Standard assertion vocabulary for the @TLT@ testing system.  See
`Test.TLT` for more information.

-}

module Test.TLT.Standard where
import Data.Maybe
import Test.TLT.Assertion
import Control.Monad.Trans.Except

infix 1 @==,  @/=,  @<,  @>,  @<=,  @>=
infix 1 @==-, @/=-, @<-, @>-, @<=-, @>=-

-- |Assert that two values are equal.  This assertion takes an
-- expected and an actual /value/; see `(@==)` to compare the result
-- of a /monadic computation/ to an expected value.
--
-- ===== Examples
--
-- > test :: Monad m => TLT m ()
-- > test = do
-- >   "Make sure that 2 is still equal to itself" ~: 2 @==- 2
-- >   "Make sure that there are four lights" ~: 4 @==- length lights
(@==-) :: (Monad m, Eq a, Show a) => a -> a -> Assertion m
@==- :: forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> a -> Assertion m
(@==-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Eq a => a -> a -> Bool
(==) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual -> String
"Expected " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a calculated value is as expected.  This assertion
-- compare the result of a /monadic computation/ to an expected value;
-- see `(@==-)` to compare an /actual value/ to the expected value.
--
-- ===== Examples
--
-- > test :: Monad m => TLT m ()
-- > test = do
-- >   "Make sure that 2 is still equal to itself" ~: 2 @== return 2
-- >   "Make sure that there are four lights" ~: 4 @== countLights
-- >                                             -- where countLights :: m Int
(@==) :: (Monad m, Eq a, Show a) => a -> m a -> Assertion m
@== :: forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> m a -> Assertion m
(@==) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> a -> Assertion m
(@==-)

-- |Assert that two values are not equal.  This assertion takes an
-- expected and an actual /value/; see `(@/=)` to compare the result
-- of a /monadic computation/ to an expected value.
(@/=-) :: (Monad m, Eq a, Show a) => a -> a -> Assertion m
@/=- :: forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> a -> Assertion m
(@/=-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Eq a => a -> a -> Bool
(/=) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Expected other than " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a calculated value differs from some known value.
-- This assertion compares the result of a /monadic computation/ to an
-- expected value; see `(@/=-)` to compare an /actual value/ to the
-- expected value.
(@/=) :: (Monad m, Eq a, Show a) => a -> m a -> Assertion m
@/= :: forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> m a -> Assertion m
(@/=) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Eq a, Show a) =>
a -> a -> Assertion m
(@/=-)

-- |Assert that a given boundary is strictly less than some value.
-- This assertion takes an expected and an actual /value/; see `(@<)`
-- to compare the result of a /monadic computation/ to an expected
-- value.
(@<-) :: (Monad m, Ord a, Show a) => a -> a -> Assertion m
@<- :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@<-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Ord a => a -> a -> Bool
(<) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Lower bound (open) is " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a given, constant boundary is strictly less than some
-- calculated value.  This assertion compares the result of a /monadic
-- computation/ to an expected value; see `(@<-)` to compare an
-- /actual value/ to the expected value.
(@<) :: (Monad m, Ord a, Show a) => a -> m a -> Assertion m
@< :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> m a -> Assertion m
(@<) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@<-)

-- |Assert that a given boundary is strictly less than some value.
-- This assertion takes an expected and an actual /value/; see `(@>)`
-- to compare the result of a /monadic computation/ to an expected
-- value.
(@>-) :: (Monad m, Ord a, Show a) => a -> a -> Assertion m
@>- :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@>-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Ord a => a -> a -> Bool
(>) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Upper bound (open) is " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a given, constant boundary is strictly less than some
-- calculated value.  This assertion compares the result of a /monadic
-- computation/ to an expected value; see `(@>-)` to compare an
-- /actual value/ to the expected value.
(@>) :: (Monad m, Ord a, Show a) => a -> m a -> Assertion m
@> :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> m a -> Assertion m
(@>) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@>-)

-- |Assert that a given boundary is strictly less than some value.
-- This assertion takes an expected and an actual /value/; see `(@<=)`
-- to compare the result of a /monadic computation/ to an expected
-- value.
(@<=-) :: (Monad m, Ord a, Show a) => a -> a -> Assertion m
@<=- :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@<=-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Ord a => a -> a -> Bool
(<=) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Lower bound (closed) is " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a given, constant boundary is strictly less than some
-- calculated value.  This assertion compares the result of a /monadic
-- computation/ to an expected value; see `(@<=-)` to compare an
-- /actual value/ to the expected value.
(@<=) :: (Monad m, Ord a, Show a) => a -> m a -> Assertion m
@<= :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> m a -> Assertion m
(@<=) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@<=-)

-- |Assert that a given boundary is strictly less than some value.
-- This assertion takes an expected and an actual /value/; see `(@>=)`
-- to compare the result of a /monadic computation/ to an expected
-- value.
(@>=-) :: (Monad m, Ord a, Show a) => a -> a -> Assertion m
@>=- :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@>=-) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure forall a. Ord a => a -> a -> Bool
(>=) forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Upper bound (closed) is " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
exp forall a. [a] -> [a] -> [a]
++ String
" but got " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
actual

-- |Assert that a given, constant boundary is strictly less than some
-- calculated value.  This assertion compares the result of a /monadic
-- computation/ to an expected value; see `(@>=-)` to compare an
-- /actual value/ to the expected value.
(@>=) :: (Monad m, Ord a, Show a) => a -> m a -> Assertion m
@>= :: forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> m a -> Assertion m
(@>=) = forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM forall (m :: * -> *) a.
(Monad m, Ord a, Show a) =>
a -> a -> Assertion m
(@>=-)

-- |Assert that a pure traversable structure (such as a list) is
-- empty.
emptyP :: (Monad m, Traversable t) => t a -> Assertion m
emptyP :: forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
t a -> Assertion m
emptyP = forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure forall (t :: * -> *) a. Foldable t => t a -> Bool
null
           (\ t a
_ -> String
"Expected empty structure but got non-empty")

-- |Assert that a traversable structure (such as a list) returned from
-- a computation is empty.
empty :: (Monad m, Traversable t) => m (t a) -> Assertion m
empty :: forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
m (t a) -> Assertion m
empty = forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
t a -> Assertion m
emptyP

-- |Assert that a pure traversable structure (such as a list) is
-- nonempty.
nonemptyP :: (Monad m, Traversable t) => t a -> Assertion m
nonemptyP :: forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
t a -> Assertion m
nonemptyP = forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null)
              (\ t a
_ -> String
"Expected non-empty structure but got empty")

-- |Assert that a traversable structure (such as a list) returned from
-- a computation is non-empty.
nonempty :: (Monad m, Traversable t) => m (t a) -> Assertion m
nonempty :: forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
m (t a) -> Assertion m
nonempty = forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM forall (m :: * -> *) (t :: * -> *) a.
(Monad m, Traversable t) =>
t a -> Assertion m
nonemptyP

-- |Assert that a `Maybe` value is `Nothing`.
nothingP :: Monad m => Maybe a -> Assertion m
nothingP :: forall (m :: * -> *) a. Monad m => Maybe a -> Assertion m
nothingP = forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure forall a. Maybe a -> Bool
isNothing
           (\ Maybe a
_ -> String
"Expected empty Maybe value but got non-Nothing")

-- |Assert that a `Maybe` result of a computation is `Nothing`.
nothing :: Monad m => m (Maybe a) -> Assertion m
nothing :: forall (m :: * -> *) a. Monad m => m (Maybe a) -> Assertion m
nothing = forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM forall (m :: * -> *) a. Monad m => Maybe a -> Assertion m
nothingP