Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- specWithContract :: forall (cp :: T) (st :: T). (Each '[KnownT] '[cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec
- specWithTypedContract :: forall (cp :: T) (st :: T). (Each '[KnownT] '[cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec
- specWithUntypedContract :: FilePath -> (Contract -> Spec) -> Spec
- type ContractReturn (st :: T) = (Either MichelsonFailed ([Operation], Value st), InterpreterState)
- type ContractPropValidator (st :: T) prop = ContractReturn st -> prop
- contractProp :: forall param storage (cp :: T) (st :: T) prop. (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st, ParameterScope cp) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop
- contractPropVal :: forall (cp :: T) (st :: T) prop. ParameterScope cp => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop
- expectContractEntrypoints :: forall expectedEps contractEps st. (NiceParameterFull expectedEps, NiceParameterFull contractEps, NiceStorage st) => Contract contractEps st -> Assertion
- type IntegrationalScenario = IntegrationalScenarioM ()
- type IntegrationalScenarioM = StateT InternalState (Except ScenarioError)
- data TestError
- = InterpreterError IntegrationalExecutorError
- | UnexpectedInterpreterError Text IntegrationalExecutorError
- | UnexpectedTypeCheckError TCError
- | ExpectingInterpreterToFail
- | IncorrectUpdates TestError [GStateUpdate]
- | IncorrectStorageUpdate AddressName Text
- | InvalidStorage AddressName ExpectedStorage Text
- | StoragePredicateMismatch AddressName Text
- | InvalidBalance AddressName ExpectedBalance Text
- | UnexpectedUpdates (NonEmpty GStateUpdate)
- | ValidatingEmptyScenario
- | CustomTestError Text
- integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation
- integrationalTestProp :: MonadTest m => IntegrationalScenario -> m ()
- lOriginate :: forall cp st. (NiceParameterFull cp, NiceStorage st) => Contract cp st -> Text -> st -> Mutez -> IntegrationalScenarioM (TAddress cp)
- lOriginateEmpty :: (NiceParameterFull cp, NiceStorage st, Default st) => Contract cp st -> Text -> IntegrationalScenarioM (TAddress cp)
- lTransfer :: forall cp epRef epArg addr. (HasEntryPointArg cp epRef epArg, IsoValue epArg, ToTAddress cp addr) => ("from" :! Address) -> ("to" :! addr) -> Mutez -> epRef -> epArg -> IntegrationalScenarioM ()
- lCall :: forall cp defEpName addr. (HasDefEntryPointArg cp defEpName cp, IsoValue cp, ToTAddress cp addr) => addr -> cp -> IntegrationalScenarioM ()
- lCallEP :: forall cp epRef epArg addr. (HasEntryPointArg cp epRef epArg, IsoValue epArg, ToTAddress cp addr) => addr -> epRef -> epArg -> IntegrationalScenarioM ()
- data EntryPointRef (mname :: Maybe Symbol) where
- CallDefault :: EntryPointRef 'Nothing
- Call :: NiceEntryPointName name => EntryPointRef ('Just name)
- lCallDef :: forall cp defEpName defArg addr. (HasDefEntryPointArg cp defEpName defArg, IsoValue defArg, ToTAddress cp addr) => addr -> defArg -> IntegrationalScenarioM ()
- integrationalFail :: TestError -> IntegrationalScenarioM anything
- unexpectedInterpreterError :: ExecutorError -> Text -> IntegrationalScenarioM a
- setMaxSteps :: RemainingSteps -> IntegrationalScenarioM ()
- setNow :: Timestamp -> IntegrationalScenarioM ()
- rewindTime :: Integer -> IntegrationalScenarioM ()
- withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a
- setChainId :: ChainId -> IntegrationalScenarioM ()
- branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario
- (?-) :: Text -> a -> (Text, a)
- offshoot :: Text -> IntegrationalScenario -> IntegrationalScenario
- expectNoUpdates :: IntegrationalScenario
- expectNoStorageUpdates :: IntegrationalScenario
- lExpectStorageUpdate :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either TestError ()) -> IntegrationalScenario
- lExpectBalance :: ToAddress addr => addr -> Mutez -> IntegrationalScenario
- lExpectStorage :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either TestError ()) -> IntegrationalScenario
- lExpectStorageConst :: forall st addr. (NiceStorage st, ToAddress addr) => addr -> st -> IntegrationalScenario
- attempt :: IntegrationalScenarioM a -> IntegrationalScenarioM (Either ExecutorError a)
- expectError :: IntegrationalScenarioM a -> IntegrationalScenarioM ExecutorError
- catchExpectedError :: IntegrationalScenarioM a -> (ExecutorError -> IntegrationalScenarioM b) -> IntegrationalScenarioM b
- lExpectMichelsonFailed :: forall addr. ToAddress addr => (MichelsonFailed -> Bool) -> addr -> ExecutorError -> IntegrationalScenario
- lExpectFailWith :: forall e. IsoValue e => (e -> Bool) -> ExecutorError -> IntegrationalScenario
- lExpectError :: forall e. IsError e => (e -> Bool) -> ExecutorError -> IntegrationalScenario
- lExpectErrorNumeric :: forall e. IsError e => ErrorTagMap -> (e -> Bool) -> ExecutorError -> IntegrationalScenario
- lExpectCustomError :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => Label tag -> arg -> ExecutorError -> IntegrationalScenario
- lExpectCustomErrorNumeric :: forall tag arg. (IsError (CustomError tag), arg ~ ErrorArg tag, Eq arg) => ErrorTagMap -> Label tag -> arg -> ExecutorError -> IntegrationalScenario
- lExpectCustomError_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => Label tag -> ExecutorError -> IntegrationalScenario
- lExpectCustomErrorNumeric_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => ErrorTagMap -> Label tag -> ExecutorError -> IntegrationalScenario
- lExpectConsumerStorage :: forall cp st addr. (st ~ [cp], NiceStorage st, ToTAddress cp addr) => addr -> (st -> Either TestError ()) -> IntegrationalScenario
- lExpectViewConsumerStorage :: (st ~ [cp], Eq cp, Buildable cp, NiceStorage st, ToTAddress cp addr) => addr -> [cp] -> IntegrationalScenario
- data TxData = TxData {}
- genesisAddresses :: NonEmpty Address
- genesisAddress :: Address
- genesisAddress1 :: Address
- genesisAddress2 :: Address
- genesisAddress3 :: Address
- genesisAddress4 :: Address
- genesisAddress5 :: Address
- genesisAddress6 :: Address
- runDocTests :: HasCallStack => [DocTest] -> ContractDoc -> [TestTree]
- testLorentzDoc :: [DocTest]
- excludeDocTests :: [DocTest] -> [DocTest] -> [DocTest]
- failedTest :: (HasCallStack, MonadTest m) => Text -> m ()
- succeededTest :: MonadTest m => m ()
- eitherIsLeft :: (Show b, MonadTest m, HasCallStack) => Either a b -> m ()
- eitherIsRight :: (Show a, MonadTest m, HasCallStack) => Either a b -> m ()
- total :: (MonadTest m, NFData a, HasCallStack) => a -> m a
- meanTimeUpperBoundProp :: forall (unit :: Rat) a b. (KnownDivRat unit Second, KnownUnitName unit, HasCallStack) => Time unit -> (a -> b) -> a -> Property
- meanTimeUpperBoundPropNF :: forall (unit :: Rat) b a. (KnownDivRat unit Second, KnownUnitName unit, HasCallStack, NFData b) => Time unit -> (a -> b) -> a -> Property
- mcs :: RatioNat -> Time Microsecond
- ms :: RatioNat -> Time Millisecond
- sec :: RatioNat -> Time Second
- minute :: RatioNat -> Time Minute
- dummyContractEnv :: ContractEnv
- minTimestamp :: Timestamp
- maxTimestamp :: Timestamp
- midTimestamp :: Timestamp
- contractConsumer :: Contract cp [cp]
- integrationalTestProperty :: IntegrationalScenario -> Property
- failedProp :: Text -> Property
- succeededProp :: Property
- qcIsLeft :: Show b => Either a b -> Property
- qcIsRight :: Show a => Either a b -> Property
Importing a contract
specWithContract :: forall (cp :: T) (st :: T). (Each '[KnownT] '[cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> Spec) -> Spec #
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 :: forall (cp :: T) (st :: T). (Each '[KnownT] '[cp, st], HasCallStack) => FilePath -> (Contract cp st -> Spec) -> Spec #
A version of specWithContract
which passes only the typed
representation of the contract.
Unit testing
type ContractReturn (st :: T) = (Either MichelsonFailed ([Operation], Value st), InterpreterState) #
type ContractPropValidator (st :: T) prop = ContractReturn st -> prop #
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 :: forall param storage (cp :: T) (st :: T) prop. (IsoValue param, IsoValue storage, ToT param ~ cp, ToT storage ~ st, ParameterScope cp) => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> param -> storage -> prop #
ContractCode's property tester against given input. Takes contract environment, initial storage and parameter, interprets contract on this input and invokes validation function.
contractPropVal :: forall (cp :: T) (st :: T) prop. ParameterScope cp => Contract cp st -> ContractPropValidator st prop -> ContractEnv -> Value cp -> Value st -> prop #
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 IntegrationalScenario = IntegrationalScenarioM () #
type IntegrationalScenarioM = StateT InternalState (Except ScenarioError) #
A monad inside which integrational tests can be described using do-notation.
InterpreterError IntegrationalExecutorError | |
UnexpectedInterpreterError Text IntegrationalExecutorError | |
UnexpectedTypeCheckError TCError | |
ExpectingInterpreterToFail | |
IncorrectUpdates TestError [GStateUpdate] | |
IncorrectStorageUpdate AddressName Text | |
InvalidStorage AddressName ExpectedStorage Text | |
StoragePredicateMismatch AddressName Text | |
InvalidBalance AddressName ExpectedBalance Text | |
UnexpectedUpdates (NonEmpty GStateUpdate) | |
ValidatingEmptyScenario | |
CustomTestError Text |
Instances
Show TestError | |
Exception TestError | |
Defined in Michelson.Test.Integrational toException :: TestError -> SomeException # fromException :: SomeException -> Maybe TestError # displayException :: TestError -> String # | |
Buildable TestError | |
Defined in Michelson.Test.Integrational |
integrationalTestExpectation :: HasCallStack => IntegrationalScenario -> Expectation #
Integrational test that executes given operations and validates
them. 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.
integrationalTestProp :: MonadTest m => IntegrationalScenario -> m () #
Integrational test similar to integrationalTestExpectation
.
It can fail using Property
capability.
It can be used with Hedgehog'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 #
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.
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 # | |
Defined in Lorentz.EntryPoints.Core useHasEntryPointArg :: EntryPointRef mname -> (Dict (ParameterScope (ToT arg)), EpName) Source # |
lCallDef :: forall cp defEpName defArg addr. (HasDefEntryPointArg cp defEpName defArg, IsoValue defArg, ToTAddress cp addr) => addr -> defArg -> IntegrationalScenarioM () Source #
lCallEP
for default entrypoint.
integrationalFail :: TestError -> IntegrationalScenarioM anything #
Just fail with given error.
unexpectedInterpreterError :: ExecutorError -> Text -> IntegrationalScenarioM a #
Fail a test because an interpreter error happened unexpectedly, with the given reason.
setMaxSteps :: RemainingSteps -> IntegrationalScenarioM () #
Make all further interpreter calls use the given gas limit.
setNow :: Timestamp -> IntegrationalScenarioM () #
Make all further interpreter calls use the given timestamp as the current one.
rewindTime :: Integer -> IntegrationalScenarioM () #
Increase current time by the given number of seconds.
withSender :: Address -> IntegrationalScenarioM a -> IntegrationalScenarioM a #
Pretend that given address initiates all the transfers within the
code block (i.e. SENDER
instruction will return this address).
setChainId :: ChainId -> IntegrationalScenarioM () #
Make all further interpreter calls use the given chain id.
branchout :: HasCallStack => [(Text, IntegrationalScenario)] -> IntegrationalScenario #
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.
offshoot :: Text -> IntegrationalScenario -> IntegrationalScenario #
Test given scenario with the state gathered till this moment; if this scenario passes, go on as if it never happened.
Validators
expectNoUpdates :: IntegrationalScenario #
Check that there were no updates.
expectNoStorageUpdates :: IntegrationalScenario #
Check that there were no storage updates.
lExpectStorageUpdate :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either TestError ()) -> IntegrationalScenario Source #
Similar to expectStorageUpdate
, but for Lorentz values.
lExpectBalance :: ToAddress addr => addr -> Mutez -> IntegrationalScenario Source #
Like expectBalance
, for Lorentz values.
lExpectStorage :: forall st addr. (NiceStorage st, ToAddress addr, HasCallStack) => addr -> (st -> Either TestError ()) -> IntegrationalScenario Source #
Similar to expectStorage
, but for Lorentz values.
lExpectStorageConst :: forall st addr. (NiceStorage st, ToAddress addr) => addr -> st -> IntegrationalScenario Source #
Similar to expectStorageConst
, for Lorentz values.
Errors
attempt :: IntegrationalScenarioM a -> IntegrationalScenarioM (Either ExecutorError a) #
Attempt to run an action and return its result or, if interpretation fails, an error.
expectError :: IntegrationalScenarioM a -> IntegrationalScenarioM ExecutorError #
Run an action that is expected to fail. If the action fails, the test succeeds and the error is returned. If the action succeeds, the test fails.
catchExpectedError :: IntegrationalScenarioM a -> (ExecutorError -> IntegrationalScenarioM b) -> IntegrationalScenarioM b #
Run an action that is expected to fail.
In action
:
If the action fails, catchExpectedError
ff
is applied to the error.
If the action succeeds, the test fails.
lExpectMichelsonFailed :: forall addr. ToAddress addr => (MichelsonFailed -> Bool) -> addr -> ExecutorError -> IntegrationalScenario Source #
Expect that interpretation of contract with given address ended with [FAILED].
lExpectFailWith :: forall e. IsoValue e => (e -> Bool) -> ExecutorError -> IntegrationalScenario 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 -> IntegrationalScenario Source #
Expect contract to fail with given error.
lExpectErrorNumeric :: forall e. IsError e => ErrorTagMap -> (e -> Bool) -> ExecutorError -> IntegrationalScenario 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 -> IntegrationalScenario 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 -> IntegrationalScenario 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 -> IntegrationalScenario Source #
Specialization of lExpectCustomError
for non-arg error case.
lExpectCustomErrorNumeric_ :: forall tag. (IsError (CustomError tag), ErrorArg tag ~ ()) => ErrorTagMap -> Label tag -> ExecutorError -> IntegrationalScenario 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 TestError ()) -> IntegrationalScenario Source #
Version of lExpectStorageUpdate
specialized to "consumer" contract
(see contractConsumer
).
lExpectViewConsumerStorage :: (st ~ [cp], Eq cp, Buildable cp, NiceStorage st, ToTAddress cp addr) => addr -> [cp] -> IntegrationalScenario 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 associated with a particular transaction.
TxData | |
|
genesisAddresses :: NonEmpty Address #
Initially these addresses have a lot of money.
One of genesis addresses.
More genesis addresses
We know size of genesisAddresses
, so it is safe to use !!
More genesis addresses
We know size of genesisAddresses
, so it is safe to use !!
More genesis addresses
We know size of genesisAddresses
, so it is safe to use !!
Autodoc testing
runDocTests :: HasCallStack => [DocTest] -> ContractDoc -> [TestTree] #
Finalize test suites.
testLorentzDoc :: [DocTest] Source #
Tests all properties.
excludeDocTests :: [DocTest] -> [DocTest] -> [DocTest] #
Calling excludeDocTests tests toExclude
returns all test suites from
tests
which are not present in toExclude
.
General utilities
failedTest :: (HasCallStack, MonadTest m) => Text -> m () #
A Property
that always fails with given message.
succeededTest :: MonadTest m => m () #
A Property
that always succeeds.
eitherIsLeft :: (Show b, MonadTest m, HasCallStack) => Either a b -> m () #
The Property
holds on `Left a`.
eitherIsRight :: (Show a, MonadTest m, HasCallStack) => Either a b -> m () #
The Property
holds on `Right b`.
total :: (MonadTest m, NFData a, HasCallStack) => a -> m a #
Checks that a value is total, i.e., doesn't crash when evaluated, by reducing it to its normal form.
Equivalent to QuickCheck's total
.
meanTimeUpperBoundProp :: forall (unit :: Rat) a b. (KnownDivRat unit Second, KnownUnitName unit, HasCallStack) => Time unit -> (a -> b) -> a -> Property #
Benchmarks the given function and checks that the mean time to evaluate to weak head normal form is under the given amount of time.
This test fails if the benchmark takes longer than 30 seconds to run.
meanTimeUpperBoundPropNF :: forall (unit :: Rat) b a. (KnownDivRat unit Second, KnownUnitName unit, HasCallStack, NFData b) => Time unit -> (a -> b) -> a -> Property #
Benchmarks the given function and checks that the mean time to evaluate to normal form is under the given amount of time.
This test aborts and fails if the benchmark takes longer than 120 seconds to run.
Re-exports
These functions from Time are re-exported here to make it convenient to call
meanTimeUpperBoundProp
and meanTimeUpperBoundPropNF
.
mcs :: RatioNat -> Time Microsecond #
Creates Microsecond
from given Natural
.
>>>
mcs 42
42mcs
ms :: RatioNat -> Time Millisecond #
Creates Millisecond
from given Natural
.
>>>
ms 42
42ms
Dummy values
dummyContractEnv :: ContractEnv #
Dummy ContractEnv
with some reasonable hardcoded values. You
can override values you are interested in using record update
syntax.
Arbitrary data
Minimal (earliest) timestamp used for Arbitrary (CValue 'CTimestamp)
Maximal (latest) timestamp used for Arbitrary (CValue 'CTimestamp)
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.
Deprecated
integrationalTestProperty :: IntegrationalScenario -> Property #
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.
failedProp :: Text -> Property #
A Property
that always fails with given message.
A Property
that always succeeds.