Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides a framework for testing Plutus contracts built on Test.QuickCheck. The
testing is model based, so to test a contract you define a type modelling the state of the
contract (or set of contracts) and provide an instance of the ContractModel
class. This
instance specifies what operations (Action
s) the contract supports, how they interact with
the model state, and how to execute them in the blockchain emulator (Plutus.Trace.Emulator).
Tests are evaluated by running sequences of actions (random or user-specified) in the emulator
and comparing the state of the blockchain to the model state at the end.
Test cases are written in the DL
monad, which supports mixing fixed sequences of actions with
random actions, making it easy to write properties like
it is always possible to get all funds out of the contract.
Synopsis
- module Plutus.Contract.Test.ContractModel.Internal.ContractInstance
- pattern UnderlyingAction :: Action s -> Action (WithInstances s)
- pattern Unilateral :: Wallet -> Action (WithInstances s)
- data CoverageOptions = CoverageOptions {
- _checkCoverage :: Bool
- _endpointCoverageReq :: ContractInstanceTag -> String -> Double
- _coverageIndex :: CoverageIndex
- _coverageIORef :: Maybe (IORef CoverageData)
- newtype WithInstances s = WithInstances {
- withoutInstances :: s
- type CheckableContractModel state = (RunModel state (SpecificationEmulatorTrace state), ContractInstanceModel state)
- type EmulatorTraceWithInstances s = Eff (State (Handles s) ': EmulatorEffects)
- type SpecificationEmulatorTrace s = Eff (Reader (Handles s) ': BaseEmulatorEffects)
- contractHandle :: (ContractInstanceModel state, Typeable w, Typeable schema, Typeable err, Typeable params) => ContractInstanceKey state w schema err params -> RunMonad (SpecificationEmulatorTrace state) (ContractHandle w schema err)
- activateWallets :: ContractInstanceModel state => (forall t. HasSymbolicRep t => Symbolic t -> t) -> [StartContract state] -> EmulatorTraceWithInstances state ()
- instancesForOtherWallets :: Wallet -> Handles state -> [ContractInstanceId]
- liftSpecificationTrace :: SpecificationEmulatorTrace s a -> EmulatorTraceWithInstances s a
- delay :: Integer -> RunMonad (SpecificationEmulatorTrace state) ()
- newtype Whitelist = Whitelist {
- errorPrefixes :: Set Text
- data NoLockedFundsProofLight model = NoLockedFundsProofLight {
- nlfplMainStrategy :: DL (WithInstances model) ()
- data NoLockedFundsProof model = NoLockedFundsProof {
- nlfpMainStrategy :: DL (WithInstances model) ()
- nlfpWalletStrategy :: Wallet -> DL (WithInstances model) ()
- nlfpOverhead :: ModelState (WithInstances model) -> SymValue
- nlfpErrorMargin :: ModelState (WithInstances model) -> SymValue
- checkCoverage :: Lens' CoverageOptions Bool
- coverageIORef :: Lens' CoverageOptions (Maybe (IORef CoverageData))
- coverageIndex :: Lens' CoverageOptions CoverageIndex
- endpointCoverageReq :: Lens' CoverageOptions (ContractInstanceTag -> String -> Double)
- defaultCoverageOptions :: CoverageOptions
- defaultCheckOptionsContractModel :: CheckOptions
- quickCheckWithCoverage :: Testable prop => Args -> CoverageOptions -> (CoverageOptions -> prop) -> IO CoverageReport
- quickCheckWithCoverageAndResult :: Testable prop => Args -> CoverageOptions -> (CoverageOptions -> prop) -> IO (CoverageReport, Result)
- balanceChangePredicate :: ProtocolParameters -> ContractModelResult state -> Property
- threatModelPredicate :: ThreatModel a -> ProtocolParameters -> ContractModelResult state -> Property
- checkThreatModel :: CheckableContractModel state => ThreatModel a -> Actions (WithInstances state) -> Property
- checkThreatModelWithOptions :: CheckableContractModel state => CheckOptions -> CoverageOptions -> ThreatModel a -> Actions (WithInstances state) -> Property
- propRunActions_ :: CheckableContractModel state => Actions (WithInstances state) -> Property
- propRunActions :: CheckableContractModel state => (ModelState (WithInstances state) -> TracePredicate) -> (ProtocolParameters -> ContractModelResult (WithInstances state) -> Property) -> Actions (WithInstances state) -> Property
- propRunActionsWithOptions :: forall state. CheckableContractModel state => CheckOptions -> CoverageOptions -> (ModelState (WithInstances state) -> TracePredicate) -> (ProtocolParameters -> ContractModelResult (WithInstances state) -> Property) -> Actions (WithInstances state) -> Property
- defaultNLFP :: NoLockedFundsProof model
- checkNoLockedFundsProof :: CheckableContractModel model => NoLockedFundsProof model -> Property
- checkNoLockedFundsProofFast :: CheckableContractModel model => NoLockedFundsProof model -> Property
- checkNoLockedFundsProofWithOptions :: CheckableContractModel model => CheckOptions -> NoLockedFundsProof model -> Property
- checkNoLockedFundsProofFastWithOptions :: CheckableContractModel model => CheckOptions -> NoLockedFundsProof model -> Property
- checkNoLockedFundsProof' :: CheckableContractModel model => (Actions (WithInstances model) -> Property) -> NoLockedFundsProof model -> Property
- actionsFromList :: [Action s] -> Actions s
- walletAddress :: Wallet -> AddressInEra Era
- addressToWallet :: AddressInEra Era -> Maybe Wallet
- checkNoLockedFundsProofLight :: CheckableContractModel model => NoLockedFundsProofLight model -> Property
- isAcceptedBy :: Maybe Text -> Whitelist -> Bool
- whitelistOk :: Whitelist -> Bool
- mkWhitelist :: [Text] -> Whitelist
- defaultWhitelist :: Whitelist
- checkErrorWhitelist :: CheckableContractModel m => Whitelist -> Actions (WithInstances m) -> Property
- checkErrorWhitelistWithOptions :: forall m. CheckableContractModel m => CheckOptions -> CoverageOptions -> Whitelist -> Actions (WithInstances m) -> Property
Documentation
pattern UnderlyingAction :: Action s -> Action (WithInstances s) Source #
pattern Unilateral :: Wallet -> Action (WithInstances s) Source #
data CoverageOptions Source #
Options for controlling coverage checking requirements
checkCoverage
tells you whether or not to run the coverage checks at all.- `endpointCoverageEq instance endpointName` tells us what percentage of tests are required to include
a call to the endpoint
endpointName
in the contract at `instance`. coverIndex
is the coverage index obtained from theCompiledCodeIn
of the validator.
CoverageOptions | |
|
newtype WithInstances s Source #
Instances
type CheckableContractModel state = (RunModel state (SpecificationEmulatorTrace state), ContractInstanceModel state) Source #
type EmulatorTraceWithInstances s = Eff (State (Handles s) ': EmulatorEffects) Source #
type SpecificationEmulatorTrace s = Eff (Reader (Handles s) ': BaseEmulatorEffects) Source #
contractHandle :: (ContractInstanceModel state, Typeable w, Typeable schema, Typeable err, Typeable params) => ContractInstanceKey state w schema err params -> RunMonad (SpecificationEmulatorTrace state) (ContractHandle w schema err) Source #
activateWallets :: ContractInstanceModel state => (forall t. HasSymbolicRep t => Symbolic t -> t) -> [StartContract state] -> EmulatorTraceWithInstances state () Source #
instancesForOtherWallets :: Wallet -> Handles state -> [ContractInstanceId] Source #
Used to freeze other wallets when checking a NoLockedFundsProof
.
delay :: Integer -> RunMonad (SpecificationEmulatorTrace state) () Source #
`delay n` delays emulator execution by n
slots
A whitelist entry tells you what final log entry prefixes are acceptable for a given error
Whitelist | |
|
data NoLockedFundsProofLight model Source #
NoLockedFundsProofLight | |
|
data NoLockedFundsProof model Source #
A "proof" that you can always recover the funds locked by a contract. The first component is a strategy that from any state of the contract can get all the funds out. The second component is a strategy for each wallet that from the same state, shows how that wallet can recover the same (or bigger) amount as using the first strategy, without relying on any actions being taken by the other wallets.
For instance, in a two player game where each player bets some amount of funds and the winner
gets the pot, there needs to be a mechanism for the players to recover their bid if the other
player simply walks away (perhaps after realising the game is lost). If not, it won't be
possible to construct a NoLockedFundsProof
that works in a state where both players need to
move before any funds can be collected.
NoLockedFundsProof | |
|
checkCoverage :: Lens' CoverageOptions Bool Source #
coverageIORef :: Lens' CoverageOptions (Maybe (IORef CoverageData)) Source #
coverageIndex :: Lens' CoverageOptions CoverageIndex Source #
endpointCoverageReq :: Lens' CoverageOptions (ContractInstanceTag -> String -> Double) Source #
defaultCoverageOptions :: CoverageOptions Source #
Default coverage checking options are: * not to check coverage * set the requriements for every endpoint to 20% and * not to cover any source locations in the validator scripts.
defaultCheckOptionsContractModel :: CheckOptions Source #
Default check options that include a large amount of Ada in the initial distributions to avoid having
to write ContractModel
s that keep track of balances.
quickCheckWithCoverage :: Testable prop => Args -> CoverageOptions -> (CoverageOptions -> prop) -> IO CoverageReport Source #
Run QuickCheck on a property that tracks coverage and print its coverage report.
quickCheckWithCoverageAndResult :: Testable prop => Args -> CoverageOptions -> (CoverageOptions -> prop) -> IO (CoverageReport, Result) Source #
balanceChangePredicate :: ProtocolParameters -> ContractModelResult state -> Property Source #
threatModelPredicate :: ThreatModel a -> ProtocolParameters -> ContractModelResult state -> Property Source #
:: CheckableContractModel state | |
=> ThreatModel a | |
-> Actions (WithInstances state) | The actions to run |
-> Property |
Check a threat model on all transactions produced by the given actions.
checkThreatModelWithOptions Source #
:: CheckableContractModel state | |
=> CheckOptions | Emulator options |
-> CoverageOptions | Coverage options |
-> ThreatModel a | |
-> Actions (WithInstances state) | The actions to run |
-> Property |
Check a threat model on all transactions produced by the given actions.
:: CheckableContractModel state | |
=> Actions (WithInstances state) | The actions to run |
-> Property |
Run a Actions
in the emulator and check that the model and the emulator agree on the final
wallet balance changes. Equivalent to
propRunActions_ hs actions =propRunActions
hs (const
$
pure
True
) actions
:: CheckableContractModel state | |
=> (ModelState (WithInstances state) -> TracePredicate) | Predicate to check at the end |
-> (ProtocolParameters -> ContractModelResult (WithInstances state) -> Property) | Predicate to run on the contract model |
-> Actions (WithInstances state) | The actions to run |
-> Property |
Run a Actions
in the emulator and check that the model and the emulator agree on the final
wallet balance changes, and that the given TracePredicate
holds at the end. Equivalent to:
propRunActions =propRunActionsWithOptions
defaultCheckOptionsContractModel
defaultCoverageOptions
propRunActionsWithOptions Source #
:: forall state. CheckableContractModel state | |
=> CheckOptions | Emulator options |
-> CoverageOptions | Coverage options |
-> (ModelState (WithInstances state) -> TracePredicate) | Predicate to check at the end of execution |
-> (ProtocolParameters -> ContractModelResult (WithInstances state) -> Property) | Predicate to run on the contract model |
-> Actions (WithInstances state) | The actions to run |
-> Property |
defaultNLFP :: NoLockedFundsProof model Source #
The default skeleton of a NoLockedFundsProof - doesn't permit any overhead or error margin.
checkNoLockedFundsProof :: CheckableContractModel model => NoLockedFundsProof model -> Property Source #
Check a NoLockedFundsProof
. Each test will generate an arbitrary sequence of actions
(anyActions_
) and ask the nlfpMainStrategy
to recover all funds locked by the contract
after performing those actions. This results in some distribution of the contract funds to the
wallets, and the test then asks each nlfpWalletStrategy
to show how to recover their
allotment of funds without any assistance from the other wallets (assuming the main strategy
did not execute). When executing wallet strategies, the off-chain instances for other wallets
are killed and their private keys are deleted from the emulator state.
checkNoLockedFundsProofFast :: CheckableContractModel model => NoLockedFundsProof model -> Property Source #
checkNoLockedFundsProofWithOptions :: CheckableContractModel model => CheckOptions -> NoLockedFundsProof model -> Property Source #
checkNoLockedFundsProofFastWithOptions :: CheckableContractModel model => CheckOptions -> NoLockedFundsProof model -> Property Source #
checkNoLockedFundsProof' :: CheckableContractModel model => (Actions (WithInstances model) -> Property) -> NoLockedFundsProof model -> Property Source #
actionsFromList :: [Action s] -> Actions s Source #
walletAddress :: Wallet -> AddressInEra Era Source #
addressToWallet :: AddressInEra Era -> Maybe Wallet Source #
checkNoLockedFundsProofLight :: CheckableContractModel model => NoLockedFundsProofLight model -> Property Source #
isAcceptedBy :: Maybe Text -> Whitelist -> Bool Source #
Check that the last entry in a log is accepted by a whitelist entry
whitelistOk :: Whitelist -> Bool Source #
Check that a whitelist does not accept any partial functions
mkWhitelist :: [Text] -> Whitelist Source #
checkErrorWhitelist :: CheckableContractModel m => Whitelist -> Actions (WithInstances m) -> Property Source #
Check that running a contract model does not result in validation failures that are not accepted by the whitelist.
checkErrorWhitelistWithOptions :: forall m. CheckableContractModel m => CheckOptions -> CoverageOptions -> Whitelist -> Actions (WithInstances m) -> Property Source #
Check that running a contract model does not result in validation failures that are not accepted by the whitelist.
Orphan instances
HasVariables Wallet Source # | |
getAllVariables :: Wallet -> Set (Any Var) | |
(HasChainIndex (Eff effs), Member Waiting effs) => IsRunnable (Eff effs) Source # | |
awaitSlot :: SlotNo -> Eff effs () | |
Member EmulatorControl effs => HasChainIndex (Eff effs) Source # | |
getChainIndex :: Eff effs ChainIndex getChainState :: Eff effs ChainState |