pub struct TestHost<State> { /* private fields */ }
Expand description

A Host implementation used for unit testing smart contracts.

The host provides a way to set up mock responses to transfers, and to contract invocations. This allows testing a specific entrypoint of a contract in isolation, assuming its dependents behave in the way specified by the supplied mock functions.

Additionally, this host provides some inspection capability so that after execution of an entrypoint tests can observe which accounts or contracts were affected.

Implementations§

source§

impl<State: Serial + DeserialWithState<TestStateApi>> TestHost<State>

source

pub fn new(state: State, state_builder: StateBuilder<TestStateApi>) -> Self

Create a new test host. **It is essential that any StateMap, StateSet or StateBox that exists in the provided state was created with the state_builder that is supplied. Otherwise the runtime error in the test.

source

pub fn state_builder(&mut self) -> &mut StateBuilder<TestStateApi>

Retrieve a reference to the underlying state builder.

source

pub fn setup_mock_entrypoint( &mut self, to: ContractAddress, method: OwnedEntrypointName, handler: MockFn<State> )

Set up a mock entrypoint for handling calls to invoke_contract.

If multiple handlers for the same entrypoint (to, method) are set up, the latest handler will be used.

source

pub fn setup_mock_upgrade( &mut self, module: ModuleReference, result: UpgradeResult )

Set up a mock for upgrading to a particular module.

If multiple mocks are setup for the same module, the latest will be used.

source

pub fn set_self_balance(&mut self, amount: Amount)

Set the contract balance. NB: This should be the sum of the contract’s initial balance and the amount you wish to invoke it with.

Example:

host.set_self_balance(Amount::from_ccd(10));
contract_receive(
    &ctx,
    &mut host,
    // This amount is _not_ added to the balance of the contract,
    // so calling `host.self_balance()` will return `10` initially.
    // When a contract is executed by the node the amount that is being sent (`5`)
    // is added to the balance of the contract, so that `host.self_balance()`
    // already observes it.
    Amount::from_ccd(5),
);
source

pub fn set_self_address(&mut self, address: ContractAddress)

Set the contract address. This is used to redirect queries for the balance of the contract itself.

This method panics if the address provided is already setup as a missing contract or for contract balance queries.

source

pub fn setup_query_account_balance( &mut self, address: AccountAddress, account_balance: AccountBalance )

Setup an account balance for an account. This is used to resolve queries for account balances.

This method panics if the address provided is already setup as a missing account.

Note: Setting up the account balance for the same address will overwrite the previous setup for that address.

source

pub fn setup_query_contract_balance( &mut self, address: ContractAddress, balance: Amount )

Setup a balance for a contract. This is used to resolve queries for contract balances.

This method panics if the address provided is already setup as a missing contract or as the self_address.

Note: Setting up the balance for the same address will overwrite the previous setup for that address.

source

pub fn set_exchange_rates(&mut self, exchange_rates: ExchangeRates)

Set the current exchange rates. This is used for resolving a query for the current exchange rates.

Note: Setting this again overwrites the previously set exchange rates.

source

pub fn transfer_occurred(&self, receiver: &AccountAddress, amount: Amount) -> bool

Check whether a given transfer occured.

source

pub fn get_transfers(&self) -> Vec<(AccountAddress, Amount)>

Get a list of all transfers that have occurred, in the order they occurred in.

source

pub fn get_transfers_to(&self, account: AccountAddress) -> Vec<Amount>

Get a list of all transfers to a specific account.

source

pub fn make_account_missing(&mut self, account: AccountAddress)

Set an account to be missing. Any transfers to this account will result in an TransferError::MissingAccount error.

This differs from the default, where all accounts are assumed to exist.

This method panics if the address provided is already setup for a query account balance.

source

pub fn make_contract_missing(&mut self, contract: ContractAddress)

Set a contract to be missing. Any queries for the balance to this contract will result in an QueryContractBalanceError.

This method panics if the address provided is already setup for a query contract balance or as the self_address.

source§

impl<State: StateClone<TestStateApi>> TestHost<State>

source

pub fn with_rollback<R, E>( &mut self, call: impl FnOnce(&mut TestHost<State>) -> Result<R, E> ) -> Result<R, E>

Helper function for invoking receive methods that respects the transactional nature of invocations. That is, if the invocation returns Err(_), then the host and state is rolled back to a checkpoint just before the invocation.

Trait Implementations§

source§

impl<State: Serial + DeserialWithState<TestStateApi> + StateClone<TestStateApi>> HasHost<State> for TestHost<State>

source§

fn invoke_transfer( &self, receiver: &AccountAddress, amount: Amount ) -> TransferResult

Perform a transfer to the given account if the contract has sufficient balance.

By default, all accounts are assumed to exist, and transfers to them will succeed (provided sufficient balance). Use make_account_missing to test out transfers to accounts not on chain.

Possible errors:

source§

fn invoke_contract_raw( &mut self, to: &ContractAddress, parameter: Parameter<'_>, method: EntrypointName<'_>, amount: Amount ) -> CallContractResult<Self::ReturnValueType>

Invoke a contract entrypoint.

This uses the mock entrypoints set up with setup_mock_entrypoint. The method will fail with a panic if no responses were set for the given contract address and method.

If the invocation results in Err(_), the host and state will be rolled back. This means that the state and the logs of, e.g., transactions will look as if the invocation never occurred. See also TestHost::with_rollback.

source§

fn invoke_contract_raw_read_only( &self, to: &ContractAddress, parameter: Parameter<'_>, method: EntrypointName<'_>, amount: Amount ) -> ReadOnlyCallContractResult<Self::ReturnValueType>

Invoke a contract entrypoint.

This uses the mock entrypoints set up with setup_mock_entrypoint. The method will fail with a panic if no responses were set for the given contract address and method.

If the invocation results in Err(_), the host and state will be rolled back. This means that the state and the logs of, e.g., transactions will look as if the invocation never occurred. See also TestHost::with_rollback.

source§

fn state(&self) -> &State

Get an immutable reference to the contract state.

source§

fn state_mut(&mut self) -> &mut State

Get a mutable reference to the contract state.

source§

fn self_balance(&self) -> Amount

Get the contract balance. This can be set with set_self_balance and defaults to 0.

source§

fn state_builder(&mut self) -> &mut StateBuilder<Self::StateApiType>

Get the state builder.

source§

fn state_and_builder( &mut self ) -> (&mut State, &mut StateBuilder<Self::StateApiType>)

Get the state and the state builder.

§

type ReturnValueType = Cursor<Vec<u8, Global>>

The type of return values this host provides. This is the raw return value. The intention is that it will be deserialized by the consumer, via the Read implementation. Read more
§

type StateApiType = TestStateApi

The type of low-level state that is associated with the host. This provides access to low-level state operations.
source§

fn account_balance(&self, address: AccountAddress) -> QueryAccountBalanceResult

Get the current public balance of an account. Here public means unencrypted or unshielded. See AccountBalance for more. This query will fail if the provided address does not exist on chain. Read more
source§

fn contract_balance( &self, address: ContractAddress ) -> QueryContractBalanceResult

Get the current balance of a contract instance. Read more
source§

fn exchange_rates(&self) -> ExchangeRates

Get the current exchange rates used by the chain. That is a Euro per Energy rate and micro CCD per Euro rate.
source§

fn upgrade(&mut self, module: ModuleReference) -> UpgradeResult

Upgrade the module for this instance to a given module. The new module must contain a smart contract with a matching name. Invocations of this instance after the point of a successful upgrade, will use the new smart contract module. The remaining code after a successful upgrade in the same invokation is executed as normal. Read more
source§

fn commit_state(&mut self)

Make sure the contract state is fully written out, so that any changes that were done in-memory up to the point in contract execution are reflected in the actual contract state maintained by the node.
source§

fn invoke_contract<P: Serial>( &mut self, to: &ContractAddress, parameter: &P, method: EntrypointName<'_>, amount: Amount ) -> CallContractResult<Self::ReturnValueType>

Like invoke_contract_raw, except that the parameter is automatically serialized. If the parameter already implements AsRef<[u8]> or can be equivalently cheaply converted to a byte array, then invoke_contract_raw should be used, since it avoids intermediate allocations.
source§

fn invoke_contract_read_only<P: Serial>( &self, to: &ContractAddress, parameter: &P, method: EntrypointName<'_>, amount: Amount ) -> ReadOnlyCallContractResult<Self::ReturnValueType>

Like invoke_contract_raw_read_only, except that the parameter is automatically serialized. If the parameter already implements AsRef<[u8]> or can be equivalently cheaply converted to a byte array, then invoke_contract_raw should be used, since it avoids intermediate allocations.

Auto Trait Implementations§

§

impl<State> !RefUnwindSafe for TestHost<State>

§

impl<State> !Send for TestHost<State>

§

impl<State> !Sync for TestHost<State>

§

impl<State> Unpin for TestHost<State>where State: Unpin,

§

impl<State> !UnwindSafe for TestHost<State>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.