module Cooked.MockChain.Testing where
import Control.Exception qualified as E
import Control.Monad
import Cooked.InitialDistribution
import Cooked.MockChain.BlockChain
import Cooked.MockChain.Direct
import Cooked.MockChain.Staged
import Cooked.MockChain.UtxoState
import Cooked.Pretty
import Cooked.Wallet
import Data.Default
import Data.List (isInfixOf)
import Data.Set qualified as Set
import Data.Text qualified as T
import Ledger qualified
import PlutusLedgerApi.V1.Value qualified as Api
import Test.QuickCheck qualified as QC
import Test.Tasty qualified as HU
import Test.Tasty.HUnit qualified as HU
import Test.Tasty.QuickCheck qualified as QC
class IsProp prop where
testCounterexample :: String -> prop -> prop
testConjoin :: [prop] -> prop
testDisjoin :: [prop] -> prop
testFailure :: prop
testFailure = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testDisjoin []
testSuccess :: prop
testSuccess = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testConjoin []
testFailureMsg :: String -> prop
testFailureMsg String
msg = String -> prop -> prop
forall prop. IsProp prop => String -> prop -> prop
testCounterexample String
msg prop
forall prop. IsProp prop => prop
testFailure
testBool :: (IsProp prop) => Bool -> prop
testBool :: forall prop. IsProp prop => Bool -> prop
testBool Bool
True = prop
forall prop. IsProp prop => prop
testSuccess
testBool Bool
False = prop
forall prop. IsProp prop => prop
testFailure
testAll :: (IsProp prop) => (a -> prop) -> [a] -> prop
testAll :: forall prop a. IsProp prop => (a -> prop) -> [a] -> prop
testAll a -> prop
f = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testConjoin ([prop] -> prop) -> ([a] -> [prop]) -> [a] -> prop
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> prop) -> [a] -> [prop]
forall a b. (a -> b) -> [a] -> [b]
map a -> prop
f
testAny :: (IsProp prop) => (a -> prop) -> [a] -> prop
testAny :: forall prop a. IsProp prop => (a -> prop) -> [a] -> prop
testAny a -> prop
f = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testDisjoin ([prop] -> prop) -> ([a] -> [prop]) -> [a] -> prop
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> prop) -> [a] -> [prop]
forall a b. (a -> b) -> [a] -> [b]
map a -> prop
f
infix 4 .==.
(.==.) :: (IsProp prop, Eq a) => a -> a -> prop
a
a .==. :: forall prop a. (IsProp prop, Eq a) => a -> a -> prop
.==. a
b = Bool -> prop
forall prop. IsProp prop => Bool -> prop
testBool (Bool -> prop) -> Bool -> prop
forall a b. (a -> b) -> a -> b
$ a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b
infixr 3 .&&.
(.&&.) :: (IsProp prop) => prop -> prop -> prop
prop
a .&&. :: forall prop. IsProp prop => prop -> prop -> prop
.&&. prop
b = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testConjoin [prop
a, prop
b]
infixr 2 .||.
(.||.) :: (IsProp prop) => prop -> prop -> prop
prop
a .||. :: forall prop. IsProp prop => prop -> prop -> prop
.||. prop
b = [prop] -> prop
forall prop. IsProp prop => [prop] -> prop
testDisjoin [prop
a, prop
b]
assertionToMaybe :: HU.Assertion -> IO (Maybe HU.HUnitFailure)
assertionToMaybe :: Assertion -> IO (Maybe HUnitFailure)
assertionToMaybe = (IO (Maybe HUnitFailure)
-> [Handler (Maybe HUnitFailure)] -> IO (Maybe HUnitFailure))
-> [Handler (Maybe HUnitFailure)]
-> IO (Maybe HUnitFailure)
-> IO (Maybe HUnitFailure)
forall a b c. (a -> b -> c) -> b -> a -> c
flip IO (Maybe HUnitFailure)
-> [Handler (Maybe HUnitFailure)] -> IO (Maybe HUnitFailure)
forall a. IO a -> [Handler a] -> IO a
E.catches [(HUnitFailure -> IO (Maybe HUnitFailure))
-> Handler (Maybe HUnitFailure)
forall a e. Exception e => (e -> IO a) -> Handler a
E.Handler ((HUnitFailure -> IO (Maybe HUnitFailure))
-> Handler (Maybe HUnitFailure))
-> (HUnitFailure -> IO (Maybe HUnitFailure))
-> Handler (Maybe HUnitFailure)
forall a b. (a -> b) -> a -> b
$ Maybe HUnitFailure -> IO (Maybe HUnitFailure)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe HUnitFailure -> IO (Maybe HUnitFailure))
-> (HUnitFailure -> Maybe HUnitFailure)
-> HUnitFailure
-> IO (Maybe HUnitFailure)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HUnitFailure -> Maybe HUnitFailure
forall a. a -> Maybe a
Just] (IO (Maybe HUnitFailure) -> IO (Maybe HUnitFailure))
-> (Assertion -> IO (Maybe HUnitFailure))
-> Assertion
-> IO (Maybe HUnitFailure)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Assertion -> IO (Maybe HUnitFailure) -> IO (Maybe HUnitFailure)
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe HUnitFailure -> IO (Maybe HUnitFailure)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe HUnitFailure
forall a. Maybe a
Nothing)
instance IsProp HU.Assertion where
testCounterexample :: String -> Assertion -> Assertion
testCounterexample String
msg = Assertion
-> (HUnitFailure -> Assertion) -> Maybe HUnitFailure -> Assertion
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Assertion
forall prop. IsProp prop => prop
testSuccess (HUnitFailure -> Assertion
forall a e. Exception e => e -> a
E.throw (HUnitFailure -> Assertion)
-> (HUnitFailure -> HUnitFailure) -> HUnitFailure -> Assertion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HUnitFailure -> HUnitFailure
adjustMsg) (Maybe HUnitFailure -> Assertion)
-> (Assertion -> IO (Maybe HUnitFailure)) -> Assertion -> Assertion
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< Assertion -> IO (Maybe HUnitFailure)
assertionToMaybe
where
joinMsg :: String -> String
joinMsg :: String -> String
joinMsg String
rest = String
msg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
rest
adjustMsg :: HU.HUnitFailure -> HU.HUnitFailure
adjustMsg :: HUnitFailure -> HUnitFailure
adjustMsg (HU.HUnitFailure Maybe SrcLoc
loc String
txt) =
Maybe SrcLoc -> String -> HUnitFailure
HU.HUnitFailure Maybe SrcLoc
loc (String -> String
joinMsg String
txt)
testFailure :: Assertion
testFailure = String -> Assertion
forall a. HasCallStack => String -> IO a
HU.assertFailure String
""
testFailureMsg :: String -> Assertion
testFailureMsg = String -> Assertion
forall a. HasCallStack => String -> IO a
HU.assertFailure
testConjoin :: [Assertion] -> Assertion
testConjoin = [Assertion] -> Assertion
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_
testDisjoin :: [Assertion] -> Assertion
testDisjoin [] = Assertion
forall prop. IsProp prop => prop
testFailure
testDisjoin (Assertion
x : [Assertion]
xs) = Assertion -> IO (Maybe HUnitFailure)
assertionToMaybe Assertion
x IO (Maybe HUnitFailure)
-> (Maybe HUnitFailure -> Assertion) -> Assertion
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Assertion
-> (HUnitFailure -> Assertion) -> Maybe HUnitFailure -> Assertion
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Assertion] -> Assertion
forall prop. IsProp prop => [prop] -> prop
testDisjoin [Assertion]
xs) HUnitFailure -> Assertion
forall a e. Exception e => e -> a
E.throw
testSuccess :: Assertion
testSuccess = () -> Assertion
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
instance IsProp QC.Property where
testCounterexample :: String -> Property -> Property
testCounterexample = String -> Property -> Property
forall prop. Testable prop => String -> prop -> Property
QC.counterexample
testFailure :: Property
testFailure = Bool -> Property
forall prop. Testable prop => prop -> Property
QC.property Bool
False
testSuccess :: Property
testSuccess = Bool -> Property
forall prop. Testable prop => prop -> Property
QC.property Bool
True
testConjoin :: [Property] -> Property
testConjoin = [Property] -> Property
forall prop. Testable prop => [prop] -> Property
QC.conjoin
testDisjoin :: [Property] -> Property
testDisjoin = [Property] -> Property
forall prop. Testable prop => [prop] -> Property
QC.disjoin
forAll :: (Show a) => QC.Gen a -> (a -> QC.Property) -> QC.Property
forAll :: forall a. Show a => Gen a -> (a -> Property) -> Property
forAll = Gen a -> (a -> Property) -> Property
forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> prop) -> Property
QC.forAll
assertSubset :: (Show a, Eq a) => [a] -> [a] -> HU.Assertion
assertSubset :: forall a. (Show a, Eq a) => [a] -> [a] -> Assertion
assertSubset [a]
l [a]
r =
[Assertion] -> Assertion
forall prop. IsProp prop => [prop] -> prop
testConjoin
( (a -> Assertion) -> [a] -> [Assertion]
forall a b. (a -> b) -> [a] -> [b]
map
( \a
x ->
HasCallStack => String -> Bool -> Assertion
String -> Bool -> Assertion
HU.assertBool
( String
"not a subset:\n\n"
String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n\nis not an element of\n\n"
String -> String -> String
forall a. [a] -> [a] -> [a]
++ [a] -> String
forall a. Show a => a -> String
show [a]
r
)
(Bool -> Assertion) -> Bool -> Assertion
forall a b. (a -> b) -> a -> b
$ a
x a -> [a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
r
)
[a]
l
)
assertSameSets :: (Show a, Eq a) => [a] -> [a] -> HU.Assertion
assertSameSets :: forall a. (Show a, Eq a) => [a] -> [a] -> Assertion
assertSameSets [a]
l [a]
r =
HasCallStack => String -> Bool -> Assertion
String -> Bool -> Assertion
HU.assertBool
(String
"expected lists of the same length, got " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" and " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
r))
([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
r)
Assertion -> Assertion -> Assertion
forall prop. IsProp prop => prop -> prop -> prop
.&&. [a] -> [a] -> Assertion
forall a. (Show a, Eq a) => [a] -> [a] -> Assertion
assertSubset [a]
l [a]
r
Assertion -> Assertion -> Assertion
forall prop. IsProp prop => prop -> prop -> prop
.&&. [a] -> [a] -> Assertion
forall a. (Show a, Eq a) => [a] -> [a] -> Assertion
assertSubset [a]
r [a]
l
type FailureProp prop = PrettyCookedOpts -> [MockChainLogEntry] -> MockChainError -> UtxoState -> prop
type SuccessProp a prop = PrettyCookedOpts -> [MockChainLogEntry] -> a -> UtxoState -> prop
type SizeProp prop = Integer -> prop
type JournalProp prop = PrettyCookedOpts -> [MockChainLogEntry] -> prop
type StateProp prop = PrettyCookedOpts -> UtxoState -> prop
data Test a prop = Test
{
forall a prop. Test a prop -> StagedMockChain a
testTrace :: StagedMockChain a,
forall a prop. Test a prop -> InitialDistribution
testInitDist :: InitialDistribution,
forall a prop. Test a prop -> SizeProp prop
testSizeProp :: SizeProp prop,
forall a prop. Test a prop -> FailureProp prop
testFailureProp :: FailureProp prop,
forall a prop. Test a prop -> SuccessProp a prop
testSuccessProp :: SuccessProp a prop,
forall a prop. Test a prop -> PrettyCookedOpts
testPrettyOpts :: PrettyCookedOpts
}
testToProp :: (IsProp prop, Show a) => Test a prop -> prop
testToProp :: forall prop a. (IsProp prop, Show a) => Test a prop -> prop
testToProp Test {StagedMockChain a
PrettyCookedOpts
InitialDistribution
SizeProp prop
SuccessProp a prop
FailureProp prop
testTrace :: forall a prop. Test a prop -> StagedMockChain a
testInitDist :: forall a prop. Test a prop -> InitialDistribution
testSizeProp :: forall a prop. Test a prop -> SizeProp prop
testFailureProp :: forall a prop. Test a prop -> FailureProp prop
testSuccessProp :: forall a prop. Test a prop -> SuccessProp a prop
testPrettyOpts :: forall a prop. Test a prop -> PrettyCookedOpts
testTrace :: StagedMockChain a
testInitDist :: InitialDistribution
testSizeProp :: SizeProp prop
testFailureProp :: FailureProp prop
testSuccessProp :: SuccessProp a prop
testPrettyOpts :: PrettyCookedOpts
..} =
let results :: [MockChainReturn a]
results = (forall (m :: * -> *).
Monad m =>
MockChainT m a -> m (MockChainReturn a))
-> StagedMockChain a -> [MockChainReturn a]
forall a res.
(forall (m :: * -> *). Monad m => MockChainT m a -> m res)
-> StagedMockChain a -> [res]
interpretAndRunWith (InitialDistribution -> MockChainT m a -> m (MockChainReturn a)
forall (m :: * -> *) a.
Monad m =>
InitialDistribution -> MockChainT m a -> m (MockChainReturn a)
runMockChainTFrom InitialDistribution
testInitDist) StagedMockChain a
testTrace
in SizeProp prop
testSizeProp (Int -> Integer
forall a. Integral a => a -> Integer
toInteger ([MockChainReturn a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [MockChainReturn a]
results))
prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. (MockChainReturn a -> prop) -> [MockChainReturn a] -> prop
forall prop a. IsProp prop => (a -> prop) -> [a] -> prop
testAll
( \ret :: MockChainReturn a
ret@(MockChainReturn Either MockChainError a
outcome Map TxOutRef (TxSkelOut, Bool)
_ UtxoState
state [MockChainLogEntry]
mcLog Map BuiltinByteString String
names) ->
let pcOpts :: PrettyCookedOpts
pcOpts = Map BuiltinByteString String
-> PrettyCookedOpts -> PrettyCookedOpts
addHashNames Map BuiltinByteString String
names PrettyCookedOpts
testPrettyOpts
in String -> prop -> prop
forall prop. IsProp prop => String -> prop -> prop
testCounterexample
((MockChainReturn a -> DocCooked) -> MockChainReturn a -> String
forall a. (a -> DocCooked) -> a -> String
renderString (PrettyCookedOpts -> MockChainReturn a -> DocCooked
forall a. PrettyCooked a => PrettyCookedOpts -> a -> DocCooked
prettyCookedOpt PrettyCookedOpts
pcOpts) MockChainReturn a
ret)
(prop -> prop) -> prop -> prop
forall a b. (a -> b) -> a -> b
$ case Either MockChainError a
outcome of
Left MockChainError
err -> FailureProp prop
testFailureProp PrettyCookedOpts
pcOpts [MockChainLogEntry]
mcLog MockChainError
err UtxoState
state
Right a
result -> SuccessProp a prop
testSuccessProp PrettyCookedOpts
pcOpts [MockChainLogEntry]
mcLog a
result UtxoState
state
)
[MockChainReturn a]
results
testCooked :: (Show a) => String -> Test a HU.Assertion -> HU.TestTree
testCooked :: forall a. Show a => String -> Test a Assertion -> TestTree
testCooked String
name = String -> Assertion -> TestTree
HU.testCase String
name (Assertion -> TestTree)
-> (Test a Assertion -> Assertion) -> Test a Assertion -> TestTree
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test a Assertion -> Assertion
forall prop a. (IsProp prop, Show a) => Test a prop -> prop
testToProp
testCookedQC :: (Show a) => String -> Test a QC.Property -> HU.TestTree
testCookedQC :: forall a. Show a => String -> Test a Property -> TestTree
testCookedQC String
name = String -> Property -> TestTree
forall a. Testable a => String -> a -> TestTree
QC.testProperty String
name (Property -> TestTree)
-> (Test a Property -> Property) -> Test a Property -> TestTree
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test a Property -> Property
forall prop a. (IsProp prop, Show a) => Test a prop -> prop
testToProp
mustSucceedTest :: (IsProp prop) => StagedMockChain a -> Test a prop
mustSucceedTest :: forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustSucceedTest StagedMockChain a
trace =
Test
{ testTrace :: StagedMockChain a
testTrace = StagedMockChain a
trace,
testInitDist :: InitialDistribution
testInitDist = InitialDistribution
forall a. Default a => a
def,
testSizeProp :: SizeProp prop
testSizeProp = prop -> SizeProp prop
forall a b. a -> b -> a
const prop
forall prop. IsProp prop => prop
testSuccess,
testFailureProp :: FailureProp prop
testFailureProp = \PrettyCookedOpts
_ [MockChainLogEntry]
_ MockChainError
_ UtxoState
_ -> String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg String
"💀 Unexpected failure!",
testSuccessProp :: SuccessProp a prop
testSuccessProp = \PrettyCookedOpts
_ [MockChainLogEntry]
_ a
_ UtxoState
_ -> prop
forall prop. IsProp prop => prop
testSuccess,
testPrettyOpts :: PrettyCookedOpts
testPrettyOpts = PrettyCookedOpts
forall a. Default a => a
def
}
mustFailTest :: (IsProp prop) => StagedMockChain a -> Test a prop
mustFailTest :: forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
trace =
Test
{ testTrace :: StagedMockChain a
testTrace = StagedMockChain a
trace,
testInitDist :: InitialDistribution
testInitDist = InitialDistribution
forall a. Default a => a
def,
testSizeProp :: SizeProp prop
testSizeProp = prop -> SizeProp prop
forall a b. a -> b -> a
const prop
forall prop. IsProp prop => prop
testSuccess,
testFailureProp :: FailureProp prop
testFailureProp = \PrettyCookedOpts
_ [MockChainLogEntry]
_ MockChainError
_ UtxoState
_ -> prop
forall prop. IsProp prop => prop
testSuccess,
testSuccessProp :: SuccessProp a prop
testSuccessProp = \PrettyCookedOpts
_ [MockChainLogEntry]
_ a
_ UtxoState
_ -> String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg String
"💀 Unexpected success!",
testPrettyOpts :: PrettyCookedOpts
testPrettyOpts = PrettyCookedOpts
forall a. Default a => a
def
}
withInitDist :: Test a prop -> InitialDistribution -> Test a prop
withInitDist :: forall a prop. Test a prop -> InitialDistribution -> Test a prop
withInitDist Test a prop
test InitialDistribution
initDist = Test a prop
test {testInitDist = initDist}
withPrettyOpts :: Test a prop -> PrettyCookedOpts -> Test a prop
withPrettyOpts :: forall a prop. Test a prop -> PrettyCookedOpts -> Test a prop
withPrettyOpts Test a prop
test PrettyCookedOpts
opts = Test a prop
test {testPrettyOpts = opts}
withJournalProp :: (IsProp prop) => Test a prop -> JournalProp prop -> Test a prop
withJournalProp :: forall prop a.
IsProp prop =>
Test a prop -> JournalProp prop -> Test a prop
withJournalProp Test a prop
test JournalProp prop
journalProp =
Test a prop
test
{ testFailureProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state -> Test a prop
-> PrettyCookedOpts
-> [MockChainLogEntry]
-> MockChainError
-> UtxoState
-> prop
forall a prop. Test a prop -> FailureProp prop
testFailureProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. JournalProp prop
journalProp PrettyCookedOpts
opts [MockChainLogEntry]
journal,
testSuccessProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state -> Test a prop
-> PrettyCookedOpts
-> [MockChainLogEntry]
-> a
-> UtxoState
-> prop
forall a prop. Test a prop -> SuccessProp a prop
testSuccessProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. JournalProp prop
journalProp PrettyCookedOpts
opts [MockChainLogEntry]
journal
}
withStateProp :: (IsProp prop) => Test a prop -> StateProp prop -> Test a prop
withStateProp :: forall prop a.
IsProp prop =>
Test a prop -> StateProp prop -> Test a prop
withStateProp Test a prop
test StateProp prop
stateProp =
Test a prop
test
{ testFailureProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state -> Test a prop
-> PrettyCookedOpts
-> [MockChainLogEntry]
-> MockChainError
-> UtxoState
-> prop
forall a prop. Test a prop -> FailureProp prop
testFailureProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. StateProp prop
stateProp PrettyCookedOpts
opts UtxoState
state,
testSuccessProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state -> Test a prop
-> PrettyCookedOpts
-> [MockChainLogEntry]
-> a
-> UtxoState
-> prop
forall a prop. Test a prop -> SuccessProp a prop
testSuccessProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. StateProp prop
stateProp PrettyCookedOpts
opts UtxoState
state
}
withSuccessProp :: (IsProp prop) => Test a prop -> SuccessProp a prop -> Test a prop
withSuccessProp :: forall prop a.
IsProp prop =>
Test a prop -> SuccessProp a prop -> Test a prop
withSuccessProp Test a prop
test SuccessProp a prop
successProp =
Test a prop
test
{ testSuccessProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state -> Test a prop -> SuccessProp a prop
forall a prop. Test a prop -> SuccessProp a prop
testSuccessProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. SuccessProp a prop
successProp PrettyCookedOpts
opts [MockChainLogEntry]
journal a
val UtxoState
state
}
withResultProp :: (IsProp prop) => Test a prop -> (a -> prop) -> Test a prop
withResultProp :: forall prop a.
IsProp prop =>
Test a prop -> (a -> prop) -> Test a prop
withResultProp Test a prop
test a -> prop
p = Test a prop -> SuccessProp a prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> SuccessProp a prop -> Test a prop
withSuccessProp Test a prop
test (\PrettyCookedOpts
_ [MockChainLogEntry]
_ a
res UtxoState
_ -> a -> prop
p a
res)
withSizeProp :: (IsProp prop) => Test a prop -> SizeProp prop -> Test a prop
withSizeProp :: forall prop a.
IsProp prop =>
Test a prop -> SizeProp prop -> Test a prop
withSizeProp Test a prop
test SizeProp prop
reqSize =
Test a prop
test
{ testSizeProp = \Integer
size -> Test a prop -> SizeProp prop
forall a prop. Test a prop -> SizeProp prop
testSizeProp Test a prop
test Integer
size prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. SizeProp prop
reqSize Integer
size
}
withFailureProp :: (IsProp prop) => Test a prop -> FailureProp prop -> Test a prop
withFailureProp :: forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
withFailureProp Test a prop
test FailureProp prop
failureProp = Test a prop
test {testFailureProp = \PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state -> Test a prop -> FailureProp prop
forall a prop. Test a prop -> FailureProp prop
testFailureProp Test a prop
test PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state prop -> prop -> prop
forall prop. IsProp prop => prop -> prop -> prop
.&&. FailureProp prop
failureProp PrettyCookedOpts
opts [MockChainLogEntry]
journal MockChainError
err UtxoState
state}
withErrorProp :: (IsProp prop) => Test a prop -> (MockChainError -> prop) -> Test a prop
withErrorProp :: forall prop a.
IsProp prop =>
Test a prop -> (MockChainError -> prop) -> Test a prop
withErrorProp Test a prop
test MockChainError -> prop
errorProp = Test a prop -> FailureProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
withFailureProp Test a prop
test (\PrettyCookedOpts
_ [MockChainLogEntry]
_ MockChainError
err UtxoState
_ -> MockChainError -> prop
errorProp MockChainError
err)
isPhase1Failure :: (IsProp prop) => FailureProp prop
isPhase1Failure :: forall prop. IsProp prop => FailureProp prop
isPhase1Failure PrettyCookedOpts
_ [MockChainLogEntry]
_ (MCEValidationError ValidationPhase
Ledger.Phase1 ValidationError
_) UtxoState
_ = prop
forall prop. IsProp prop => prop
testSuccess
isPhase1Failure PrettyCookedOpts
pcOpts [MockChainLogEntry]
_ MockChainError
e UtxoState
_ = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Expected phase 1 evaluation failure, got: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (MockChainError -> DocCooked) -> MockChainError -> String
forall a. (a -> DocCooked) -> a -> String
renderString (PrettyCookedOpts -> MockChainError -> DocCooked
forall a. PrettyCooked a => PrettyCookedOpts -> a -> DocCooked
prettyCookedOpt PrettyCookedOpts
pcOpts) MockChainError
e
isPhase2Failure :: (IsProp prop) => FailureProp prop
isPhase2Failure :: forall prop. IsProp prop => FailureProp prop
isPhase2Failure PrettyCookedOpts
_ [MockChainLogEntry]
_ (MCEValidationError ValidationPhase
Ledger.Phase2 ValidationError
_) UtxoState
_ = prop
forall prop. IsProp prop => prop
testSuccess
isPhase2Failure PrettyCookedOpts
pcOpts [MockChainLogEntry]
_ MockChainError
e UtxoState
_ = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Expected phase 2 evaluation failure, got: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (MockChainError -> DocCooked) -> MockChainError -> String
forall a. (a -> DocCooked) -> a -> String
renderString (PrettyCookedOpts -> MockChainError -> DocCooked
forall a. PrettyCooked a => PrettyCookedOpts -> a -> DocCooked
prettyCookedOpt PrettyCookedOpts
pcOpts) MockChainError
e
isPhase1FailureWithMsg :: (IsProp prop) => String -> FailureProp prop
isPhase1FailureWithMsg :: forall prop. IsProp prop => String -> FailureProp prop
isPhase1FailureWithMsg String
s PrettyCookedOpts
_ [MockChainLogEntry]
_ (MCEValidationError ValidationPhase
Ledger.Phase1 (Ledger.CardanoLedgerValidationError Text
text)) UtxoState
_ | String
s String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` Text -> String
T.unpack Text
text = prop
forall prop. IsProp prop => prop
testSuccess
isPhase1FailureWithMsg String
_ PrettyCookedOpts
pcOpts [MockChainLogEntry]
_ MockChainError
e UtxoState
_ = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Expected phase 1 evaluation failure with constrained messages, got: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (MockChainError -> DocCooked) -> MockChainError -> String
forall a. (a -> DocCooked) -> a -> String
renderString (PrettyCookedOpts -> MockChainError -> DocCooked
forall a. PrettyCooked a => PrettyCookedOpts -> a -> DocCooked
prettyCookedOpt PrettyCookedOpts
pcOpts) MockChainError
e
isPhase2FailureWithMsg :: (IsProp prop) => String -> FailureProp prop
isPhase2FailureWithMsg :: forall prop. IsProp prop => String -> FailureProp prop
isPhase2FailureWithMsg String
s PrettyCookedOpts
_ [MockChainLogEntry]
_ (MCEValidationError ValidationPhase
Ledger.Phase2 (Ledger.ScriptFailure (Ledger.EvaluationError [Text]
texts String
_))) UtxoState
_ | (Text -> Bool) -> [Text] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isInfixOf String
s (String -> Bool) -> (Text -> String) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) [Text]
texts = prop
forall prop. IsProp prop => prop
testSuccess
isPhase2FailureWithMsg String
_ PrettyCookedOpts
pcOpts [MockChainLogEntry]
_ MockChainError
e UtxoState
_ = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Expected phase 2 evaluation failure with constrained messages, got: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (MockChainError -> DocCooked) -> MockChainError -> String
forall a. (a -> DocCooked) -> a -> String
renderString (PrettyCookedOpts -> MockChainError -> DocCooked
forall a. PrettyCooked a => PrettyCookedOpts -> a -> DocCooked
prettyCookedOpt PrettyCookedOpts
pcOpts) MockChainError
e
isOfSize :: (IsProp prop) => Integer -> SizeProp prop
isOfSize :: forall prop. IsProp prop => Integer -> SizeProp prop
isOfSize Integer
n1 Integer
n2 | Integer
n1 Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
n2 = prop
forall prop. IsProp prop => prop
testSuccess
isOfSize Integer
n1 Integer
n2 = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Incorrect number of results (expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n1 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" but got: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n2 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
isAtLeastOfSize :: (IsProp prop) => Integer -> SizeProp prop
isAtLeastOfSize :: forall prop. IsProp prop => Integer -> SizeProp prop
isAtLeastOfSize Integer
n1 Integer
n2 | Integer
n1 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
n2 = prop
forall prop. IsProp prop => prop
testSuccess
isAtLeastOfSize Integer
n1 Integer
n2 = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Incorrect number of results (expected at least: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n1 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" but got: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n2 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
isAtMostOfSize :: (IsProp prop) => Integer -> SizeProp prop
isAtMostOfSize :: forall prop. IsProp prop => Integer -> SizeProp prop
isAtMostOfSize Integer
n1 Integer
n2 | Integer
n1 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
n2 = prop
forall prop. IsProp prop => prop
testSuccess
isAtMostOfSize Integer
n1 Integer
n2 = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Incorrect number of results (expected at most: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n1 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" but got: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
n2 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
happened :: (IsProp prop) => String -> JournalProp prop
happened :: forall prop. IsProp prop => String -> JournalProp prop
happened String
eventName PrettyCookedOpts
_ [MockChainLogEntry]
journal
| Set String
allEventNames <- [String] -> Set String
forall a. Ord a => [a] -> Set a
Set.fromList ([String] -> String
forall a. HasCallStack => [a] -> a
head ([String] -> String)
-> (MockChainLogEntry -> [String]) -> MockChainLogEntry -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> [String])
-> (MockChainLogEntry -> String) -> MockChainLogEntry -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MockChainLogEntry -> String
forall a. Show a => a -> String
show (MockChainLogEntry -> String) -> [MockChainLogEntry] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [MockChainLogEntry]
journal) =
if String
eventName String -> Set String -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set String
allEventNames
then prop
forall prop. IsProp prop => prop
testSuccess
else String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"The event " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
eventName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" did not occur (but those did: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Set String -> String
forall a. Show a => a -> String
show Set String
allEventNames String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")"
didNotHappen :: (IsProp prop) => String -> JournalProp prop
didNotHappen :: forall prop. IsProp prop => String -> JournalProp prop
didNotHappen String
eventName PrettyCookedOpts
_ [MockChainLogEntry]
journal | Bool -> Bool
not (String
eventName String -> Set String -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` [String] -> Set String
forall a. Ord a => [a] -> Set a
Set.fromList ([String] -> String
forall a. HasCallStack => [a] -> a
head ([String] -> String)
-> (MockChainLogEntry -> [String]) -> MockChainLogEntry -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> [String])
-> (MockChainLogEntry -> String) -> MockChainLogEntry -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MockChainLogEntry -> String
forall a. Show a => a -> String
show (MockChainLogEntry -> String) -> [MockChainLogEntry] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [MockChainLogEntry]
journal)) = prop
forall prop. IsProp prop => prop
testSuccess
didNotHappen String
eventName PrettyCookedOpts
_ [MockChainLogEntry]
_ = String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"The event " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
eventName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" was forbidden but occurred nonetheless"
isInWallets :: (IsProp prop) => [(Wallet, [(Api.AssetClass, Integer -> Bool)])] -> SuccessProp a prop
isInWallets :: forall prop a.
IsProp prop =>
[(Wallet, [(AssetClass, Integer -> Bool)])] -> SuccessProp a prop
isInWallets [(Wallet, [(AssetClass, Integer -> Bool)])]
walletsReqs PrettyCookedOpts
_ [MockChainLogEntry]
_ a
_ UtxoState
utxoState =
((Wallet, [(AssetClass, Integer -> Bool)]) -> prop)
-> [(Wallet, [(AssetClass, Integer -> Bool)])] -> prop
forall prop a. IsProp prop => (a -> prop) -> [a] -> prop
testAll
( \(Wallet
w, [(AssetClass, Integer -> Bool)]
assetsReqs) ->
let ownedValue :: Value
ownedValue = Wallet -> UtxoState -> Value
forall a. ToAddress a => a -> UtxoState -> Value
holdsInState Wallet
w UtxoState
utxoState
in ((AssetClass, Integer -> Bool) -> prop)
-> [(AssetClass, Integer -> Bool)] -> prop
forall prop a. IsProp prop => (a -> prop) -> [a] -> prop
testAll
( \(AssetClass
ac, Integer -> Bool
nbReq) ->
let amount :: Integer
amount = Value -> AssetClass -> Integer
Api.assetClassValueOf Value
ownedValue AssetClass
ac
in if Integer -> Bool
nbReq Integer
amount
then prop
forall prop. IsProp prop => prop
testSuccess
else String -> prop
forall prop. IsProp prop => String -> prop
testFailureMsg (String -> prop) -> String -> prop
forall a b. (a -> b) -> a -> b
$ String
"Unsatisfied quantity requirement for " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Wallet -> String
forall a. Show a => a -> String
show Wallet
w String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" over asset class " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> AssetClass -> String
forall a. Show a => a -> String
show AssetClass
ac
)
[(AssetClass, Integer -> Bool)]
assetsReqs
)
[(Wallet, [(AssetClass, Integer -> Bool)])]
walletsReqs
isInWallet :: (IsProp prop) => (Wallet, Api.AssetClass, Integer) -> SuccessProp a prop
isInWallet :: forall prop a.
IsProp prop =>
(Wallet, AssetClass, Integer) -> SuccessProp a prop
isInWallet (Wallet
w, AssetClass
ac, Integer
n) = [(Wallet, [(AssetClass, Integer -> Bool)])] -> SuccessProp a prop
forall prop a.
IsProp prop =>
[(Wallet, [(AssetClass, Integer -> Bool)])] -> SuccessProp a prop
isInWallets [(Wallet
w, [(AssetClass
ac, (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
n))])]
mustFailInPhase2Test :: (IsProp prop) => StagedMockChain a -> Test a prop
mustFailInPhase2Test :: forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailInPhase2Test StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
run Test a prop -> FailureProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
`withFailureProp` FailureProp prop
forall prop. IsProp prop => FailureProp prop
isPhase2Failure
mustFailInPhase2WithMsgTest :: (IsProp prop) => String -> StagedMockChain a -> Test a prop
mustFailInPhase2WithMsgTest :: forall prop a.
IsProp prop =>
String -> StagedMockChain a -> Test a prop
mustFailInPhase2WithMsgTest String
msg StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
run Test a prop -> FailureProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
`withFailureProp` String -> FailureProp prop
forall prop. IsProp prop => String -> FailureProp prop
isPhase2FailureWithMsg String
msg
mustFailInPhase1Test :: (IsProp prop) => StagedMockChain a -> Test a prop
mustFailInPhase1Test :: forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailInPhase1Test StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
run Test a prop -> FailureProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
`withFailureProp` FailureProp prop
forall prop. IsProp prop => FailureProp prop
isPhase1Failure
mustFailInPhase1WithMsgTest :: (IsProp prop) => String -> StagedMockChain a -> Test a prop
mustFailInPhase1WithMsgTest :: forall prop a.
IsProp prop =>
String -> StagedMockChain a -> Test a prop
mustFailInPhase1WithMsgTest String
msg StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
run Test a prop -> FailureProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> FailureProp prop -> Test a prop
`withFailureProp` String -> FailureProp prop
forall prop. IsProp prop => String -> FailureProp prop
isPhase1FailureWithMsg String
msg
mustSucceedWithSizeTest :: (IsProp prop) => Integer -> StagedMockChain a -> Test a prop
mustSucceedWithSizeTest :: forall prop a.
IsProp prop =>
Integer -> StagedMockChain a -> Test a prop
mustSucceedWithSizeTest Integer
size StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustSucceedTest StagedMockChain a
run Test a prop -> SizeProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> SizeProp prop -> Test a prop
`withSizeProp` (Bool -> prop
forall prop. IsProp prop => Bool -> prop
testBool (Bool -> prop) -> (Integer -> Bool) -> SizeProp prop
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
size))
mustFailWithSizeTest :: (IsProp prop) => Integer -> StagedMockChain a -> Test a prop
mustFailWithSizeTest :: forall prop a.
IsProp prop =>
Integer -> StagedMockChain a -> Test a prop
mustFailWithSizeTest Integer
size StagedMockChain a
run = StagedMockChain a -> Test a prop
forall prop a. IsProp prop => StagedMockChain a -> Test a prop
mustFailTest StagedMockChain a
run Test a prop -> SizeProp prop -> Test a prop
forall prop a.
IsProp prop =>
Test a prop -> SizeProp prop -> Test a prop
`withSizeProp` Integer -> SizeProp prop
forall prop. IsProp prop => Integer -> SizeProp prop
isOfSize Integer
size