{-|
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

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
@==- :: a -> a -> Assertion m
(@==-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual -> String
"Expected " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@== :: a -> m a -> Assertion m
(@==) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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
@/=- :: a -> a -> Assertion m
(@/=-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(/=) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Expected other than " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@/= :: a -> m a -> Assertion m
(@/=) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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
@<- :: a -> a -> Assertion m
(@<-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(<) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Lower bound (open) is " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@< :: a -> m a -> Assertion m
(@<) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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
@>- :: a -> a -> Assertion m
(@>-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(>) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Upper bound (open) is " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@> :: a -> m a -> Assertion m
(@>) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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
@<=- :: a -> a -> Assertion m
(@<=-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(<=) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Lower bound (closed) is " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@<= :: a -> m a -> Assertion m
(@<=) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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
@>=- :: a -> a -> Assertion m
(@>=-) = (a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Bool) -> (a -> a -> String) -> a -> a -> Assertion m
liftAssertion2Pure a -> a -> Bool
forall a. Ord a => a -> a -> Bool
(>=) ((a -> a -> String) -> a -> a -> Assertion m)
-> (a -> a -> String) -> a -> a -> Assertion m
forall a b. (a -> b) -> a -> b
$
  \ a
exp a
actual ->
    String
"Upper bound (closed) is " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
exp String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" but got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
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
@>= :: a -> m a -> Assertion m
(@>=) = (a -> a -> Assertion m) -> a -> m a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> a -> Assertion m) -> a -> m a -> Assertion m
assertion2PtoM a -> a -> Assertion m
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 :: t a -> Assertion m
emptyP = (t a -> Bool) -> (t a -> String) -> t a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure t a -> Bool
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 :: m (t a) -> Assertion m
empty = (t a -> Assertion m) -> m (t a) -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM t a -> Assertion m
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 :: t a -> Assertion m
nonemptyP = (t a -> Bool) -> (t a -> String) -> t a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure (Bool -> Bool
not (Bool -> Bool) -> (t a -> Bool) -> t a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t a -> Bool
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 :: m (t a) -> Assertion m
nonempty = (t a -> Assertion m) -> m (t a) -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM t a -> Assertion m
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 :: Maybe a -> Assertion m
nothingP = (Maybe a -> Bool) -> (Maybe a -> String) -> Maybe a -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> (a -> String) -> a -> Assertion m
liftAssertionPure Maybe a -> Bool
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 :: m (Maybe a) -> Assertion m
nothing = (Maybe a -> Assertion m) -> m (Maybe a) -> Assertion m
forall (m :: * -> *) a.
Monad m =>
(a -> Assertion m) -> m a -> Assertion m
assertionPtoM Maybe a -> Assertion m
forall (m :: * -> *) a. Monad m => Maybe a -> Assertion m
nothingP