morley-1.0.0: Developer tools for the Michelson Language

Safe HaskellNone
LanguageHaskell2010

Michelson.Test

Contents

Description

Module containing some utilities for testing Michelson contracts using Haskell testing frameworks (hspec and QuickCheck in particular). It's Morley testing EDSL.

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.

testTreesWithContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> ((Contract, Contract cp st) -> IO [TestTree]) -> IO [TestTree] Source #

Import contract and use to create test trees. Both versions of contract are passed to the callback function (untyped and typed).

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

testTreesWithUntypedContract :: HasCallStack => FilePath -> (Contract -> IO [TestTree]) -> IO [TestTree] Source #

Like testTreesWithContract but supplies only untyped contract.

testTreesWithTypedContract :: (Each [Typeable, SingI] [cp, st], HasCallStack) => FilePath -> (Contract cp st -> IO [TestTree]) -> IO [TestTree] Source #

Like testTreesWithContract but supplies only typed contract.

importContract :: forall cp st. Each [Typeable, SingI] [cp, st] => FilePath -> IO (Contract, Contract cp st) Source #

Import contract from a given file path.

This function reads file, parses and type checks a contract. Within the typechecking we assume that no contracts are originated, otherwise a type checking error will be caused.

This function may throw IOException and ImportContractError.

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.

validateStorageIs :: IsoValue st => st -> ContractPropValidator (ToT st) Assertion Source #

ContractPropValidator that expects contract execution to succeed and update storage to a particular constant value.

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.

originate :: Contract -> Text -> Value -> Mutez -> IntegrationalScenarioM Address Source #

Originate a contract with given initial storage and balance. Its address is returned.

tOriginate :: (ParameterScope cp, StorageScope st) => FullContract cp st -> Text -> Value st -> Mutez -> IntegrationalScenarioM Address Source #

Like originate, but for typed contract and value.

transfer :: TxData -> Address -> IntegrationalScenarioM () Source #

Transfer tokens to a given address.

tTransfer :: forall arg. ParameterScope arg => ("from" :! Address) -> ("to" :! Address) -> Mutez -> EpName -> Value arg -> IntegrationalScenarioM () Source #

Similar to transfer, for typed values. Note that it works with untyped Address and does not check that entrypoint with given name is present and has the expected type. Passed value must correspond to the entrypoint argument type, not the parameter type of the contract (and must be unit for implicit accounts).

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.

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.

expectStorageUpdate :: Address -> (Value -> Either ValidationError ()) -> SuccessValidator Source #

Check that storage value is updated for given address. Takes a predicate that is used to check the value.

It works even if updates are not filtered (i. e. a value can be updated more than once).

expectBalance :: Address -> Mutez -> SuccessValidator Source #

Check that eventually address has some particular balance.

expectStorage :: Address -> (Value -> Either ValidationError ()) -> SuccessValidator Source #

Check that storage value satisfies the given predicate.

expectStorageConst :: Address -> Value -> SuccessValidator Source #

Check that eventually address has some particular storage value.

tExpectStorageConst :: forall st. StorageScope st => Address -> Value st -> SuccessValidator Source #

Similar to expectStorageConst, for typed stuff.

expectGasExhaustion :: ExecutorError -> Bool Source #

Check that interpreter failed due to gas exhaustion.

expectMichelsonFailed :: (MichelsonFailed -> Bool) -> Address -> ExecutorError -> Bool Source #

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

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

genesisAddress :: Address Source #

One of genesis addresses.

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`.

Autodoc testing

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

Finalize test suites.

testDocBasic :: [DocTest] Source #

Base properties which should comply for all documentations.

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

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

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).