morley-0.7.0: Developer tools for the Michelson Language

Safe HaskellNone
LanguageHaskell2010

Lorentz.Test

Contents

Synopsis

Importing a contract

specWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec Source #

Import contract and use it in the spec. Both versions of contract are passed to the callback function (untyped and typed).

If contract's import fails, a spec with single failing expectation will be generated (so tests will likely run unexceptionally, but a failing result will notify about problem).

specWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec Source #

A version of specWithContract which passes only the typed representation of the contract.

Unit testing

type ContractPropValidator st prop = ContractReturn st -> prop Source #

Type for contract execution validation.

It's a function which is supplied with contract execution output (failure or new storage with operation list).

Function returns a property which type is designated by type variable prop and might be Property or Expectation or anything else relevant.

contractProp :: (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st, ParameterScope cp) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop Source #

Contract's property tester against given input. Takes contract environment, initial storage and parameter, interprets contract on this input and invokes validation function.

contractPropVal :: ParameterScope cp => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop Source #

Version of contractProp which takes Val as arguments instead of regular Haskell values.

This function assumes that contract has no explicit default entrypoints and you always have to construct parameter manually; if you need to test contract calling specific entrypoints, use integrational testing defined by Michelson.Test.Integrational module.

expectContractEntrypoints :: forall expectedEps contractEps st. (NiceParameterFull expectedEps, NiceParameterFull contractEps, NiceStorage st) => Contract contractEps st -> Assertion Source #

Expect the given contract to have some specific entrypoints.

Integrational testing

Testing engine

type IntegrationalValidator = Either (ExecutorError -> Bool) SuccessValidator Source #

Validator for integrational testing. If an error is expected, it should be Left with validator for errors. Otherwise it should check final global state and its updates.

type SuccessValidator = InternalState -> GState -> [GStateUpdate] -> Either ValidationError () Source #

Validator for integrational testing that expects successful execution.

type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) Source #

A monad inside which integrational tests can be described using do-notation.

integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation Source #

Integrational test that executes given operations and validates them using given validator. It can fail using Expectation capability. It starts with initGState and some reasonable dummy values for gas limit and current timestamp. You can update blockchain state by performing some operations.

integrationalTestProperty :: IntegrationalScenario -> Property Source #

Integrational test similar to integrationalTestExpectation. It can fail using Property capability. It can be used with QuickCheck's forAll to make a property-based test with arbitrary data.

lOriginate :: forall cp st. (NiceParameterFull cp, NiceStorage st) => Contract cp st -> Text -> st -> Mutez -> IntegrationalScenarioM (TAddress cp) Source #

Like originate, but for Lorentz contracts.

lOriginateEmpty :: (NiceParameterFull cp, NiceStorage st, Default st) => Contract cp st -> Text -> IntegrationalScenarioM (TAddress cp) Source #

Originate a contract with empty balance and default storage.

lTransfer :: forall cp epRef epArg addr. (HasEntryPointArg cp epRef epArg, IsoValue epArg, ToTAddress cp addr) => ("from" :! Address) -> ("to" :! addr) -> Mutez -> epRef -> epArg -> IntegrationalScenarioM () Source #

Similar to transfer, for Lorentz values.

lCall :: forall cp defEpName addr. (HasDefEntryPointArg cp defEpName cp, IsoValue cp, ToTAddress cp addr) => addr -> cp -> IntegrationalScenarioM () Source #

Deprecated: lCall will likely be replaced with lCallEP in future version

Legacy version of lCallEP function. Calls default entrypoint of a contract assuming its argument is the same as contract parameter (which is equivalent to absence of explicit default entrypoint).

This function is DEPRECATED and exists only for backwards compatibility.

lCallEP :: forall cp epRef epArg addr. (HasEntryPointArg cp epRef epArg, IsoValue epArg, ToTAddress cp addr) => addr -> epRef -> epArg -> IntegrationalScenarioM () Source #

Call an entrypoint of a contract without caring about the source address. Transfers 0 mutez.

data EntryPointRef (mname :: Maybe Symbol) where Source #

Which entrypoint to call.

We intentionally distinguish default and non-default cases because this makes API more details-agnostic.

Constructors

CallDefault :: EntryPointRef Nothing

Call the default entrypoint, or root if no explicit default is assigned.

Call :: NiceEntryPointName name => EntryPointRef (Just name)

Call the given entrypoint; calling default is not treated specially. You have to provide entrypoint name via passing it as type argument.

Unfortunatelly, here we cannot accept a label because in most cases our entrypoints begin from capital letter (being derived from constructor name), while labels must start from a lower-case letter, and there is no way to make a conversion at type-level.

Instances
(GetEntryPointArgCustom cp mname ~ arg, ParameterDeclaresEntryPoints cp) => HasEntryPointArg (cp :: Type) (EntryPointRef mname) arg Source # 
Instance details

Defined in Lorentz.EntryPoints.Core

lCallDef :: forall cp defEpName defArg addr. (HasDefEntryPointArg cp defEpName defArg, IsoValue defArg, ToTAddress cp addr) => addr -> defArg -> IntegrationalScenarioM () Source #

lCallEP for default entrypoint.

validate :: IntegrationalValidator -> IntegrationalScenario Source #

Validate the execution result.

integrationalFail :: ValidationError -> IntegrationalScenarioM anything Source #

Just fail with given error.

setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () Source #

Make all further interpreter calls (which are triggered by the validate function) use given gas limit.

setNow :: Timestamp -> IntegrationalScenarioM () Source #

Make all further interpreter calls (which are triggered by the validate function) use given timestamp as the current one.

rewindTime :: Integer -> IntegrationalScenarioM () Source #

Increase current time by the given number of seconds.

withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a Source #

Pretend that given address initiates all the transfers within the code block (i.e. SENDER instruction will return this address).

setChainId :: ChainId -> IntegrationalScenarioM () Source #

Make all further interpreter calls (which are triggered by the validate function) use given chain id.

branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario Source #

Execute multiple testing scenarios independently, basing them on scenario built till this point.

The following property holds for this function:

pre >> branchout [a, b, c] = branchout [pre >> a, pre >> b, pre >> c] .

In case of property failure in one of the branches no following branch is executed.

Providing empty list of scenarios to this function causes error; we do not require NonEmpty here though for convenience.

(?-) :: Text -> a -> (Text, a) infixr 0 Source #

Make a tuple with name without extra syntactic noise.

offshoot :: Text -> IntegrationalScenario -> IntegrationalScenarioM () Source #

Test given scenario with the state gathered till this moment; if this scenario passes, go on as if it never happened.

Validators

composeValidators :: SuccessValidator -> SuccessValidator -> SuccessValidator Source #

Compose two success validators.

For example:

expectBalance bal addr composeValidators expectStorageUpdateConst addr2 ValueUnit

composeValidatorsList :: [SuccessValidator] -> SuccessValidator Source #

Compose a list of success validators.

expectNoUpdates :: SuccessValidator Source #

Check that there were no updates.

expectNoStorageUpdates :: SuccessValidator Source #

Check that there were no storage updates.

lExpectStorageUpdate :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either ValidationError ()) -> SuccessValidator Source #

Similar to expectStorageUpdate, but for Lorentz values.

lExpectBalance :: ToAddress addr => addr -> Mutez -> SuccessValidator Source #

Like expectBalance, for Lorentz values.

lExpectStorage :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either ValidationError ()) -> SuccessValidator Source #

Similar to expectStorage, but for Lorentz values.

lExpectStorageConst :: forall st addr. (NiceStorage st, ToAddress addr) => addr -> st -> SuccessValidator Source #

Similar to expectStorageConst, for Lorentz values.

lExpectMichelsonFailed :: forall addr. ToAddress addr => (MichelsonFailed -> Bool) -> addr -> ExecutorError -> Bool Source #

Expect that interpretation of contract with given address ended with [FAILED].

lExpectFailWith :: forall e. (Typeable (ToT e), IsoValue e) => (e -> Bool) -> ExecutorError -> Bool Source #

Expect contract to fail with FAILWITH instruction and provided value to match against the given predicate.

lExpectError :: forall e. IsError e => (e -> Bool) -> ExecutorError -> Bool Source #

Expect contract to fail with given error.

lExpectErrorNumeric :: forall e. IsError e => ErrorTagMap -> (e -> Bool) -> ExecutorError -> Bool Source #

Version of lExpectError for the case when numeric representation of errors is used.

lExpectCustomError :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => Label tag -> arg -> ExecutorError -> Bool Source #

Expect contract to fail with given CustomError.

lExpectCustomErrorNumeric :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => ErrorTagMap -> Label tag -> arg -> ExecutorError -> Bool Source #

Version of lExpectCustomError for the case when numeric representation of errors is used.

lExpectCustomError_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => Label tag -> ExecutorError -> Bool Source #

Specialization of lExpectCustomError for non-arg error case.

lExpectCustomErrorNumeric_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => ErrorTagMap -> Label tag -> ExecutorError -> Bool Source #

Version of lExpectCustomError_ for the case when numeric representation of errors is used.

lExpectConsumerStorage :: forall cp st addr. (st ~ [cp], NiceStorage st, ToTAddress cp addr) => addr -> (st -> Either ValidationError ()) -> SuccessValidator Source #

Version of lExpectStorageUpdate specialized to "consumer" contract (see contractConsumer).

lExpectViewConsumerStorage :: (st ~ [cp], Eq cp, Buildable cp, NiceStorage st, ToTAddress cp addr) => addr -> [cp] -> SuccessValidator Source #

Assuming that "consumer" contract receives a value from View, expect this view return value to be the given one.

Despite consumer stores parameters it was called with in reversed order, this function cares about it, so you should provide a list of expected values in the same order in which the corresponding events were happenning.

Various

data TxData Source #

Data associated with a particular transaction.

Instances
Eq TxData Source # 
Instance details

Defined in Michelson.Runtime.TxData

Methods

(==) :: TxData -> TxData -> Bool #

(/=) :: TxData -> TxData -> Bool #

Show TxData Source # 
Instance details

Defined in Michelson.Runtime.TxData

genesisAddresses :: NonEmpty Address Source #

Initially these addresses have a lot of money.

genesisAddress :: Address Source #

One of genesis addresses.

genesisAddress1 :: Address Source #

More genesis addresses

We know size of genesisAddresses, so it is safe to use !!

genesisAddress2 :: Address Source #

More genesis addresses

We know size of genesisAddresses, so it is safe to use !!

genesisAddress3 :: Address Source #

More genesis addresses

We know size of genesisAddresses, so it is safe to use !!

Autodoc testing

runDocTests :: HasCallStack => [DocTest] -> ContractDoc -> [TestTree] Source #

Finalize test suites.

testLorentzDoc :: [DocTest] Source #

Tests all properties.

excludeDocTests :: [DocTest] -> [DocTest] -> [DocTest] Source #

Calling excludeDocTests tests toExclude returns all test suites from tests which are not present in toExclude.

General utilities

failedProp :: Text -> Property Source #

A Property that always failes with given message.

succeededProp :: Property Source #

A Property that always succeeds.

qcIsLeft :: Show b => Either a b -> Property Source #

The Property holds on `Left a`.

qcIsRight :: Show a => Either a b -> Property Source #

The Property holds on `Right b`.

Dummy values

dummyContractEnv :: ContractEnv Source #

Dummy ContractEnv with some reasonable hardcoded values. You can override values you are interested in using record update syntax.

Arbitrary data

minTimestamp :: Timestamp Source #

Minimal (earliest) timestamp used for Arbitrary (CValue 'CTimestamp)

maxTimestamp :: Timestamp Source #

Maximal (latest) timestamp used for Arbitrary (CValue 'CTimestamp)

midTimestamp :: Timestamp Source #

Median of minTimestamp and maxTimestamp. Useful for testing (exactly half of generated dates will be before and after this date).

Special contracts for testing

contractConsumer :: Contract cp [cp] Source #

Remembers parameters it was called with, last goes first.