[][src]Struct exonum_testkit::TestKit

pub struct TestKit { /* fields omitted */ }

Testkit for testing blockchain services. It offers simple network configuration emulation with no real network setup.

Transaction Checks

The testkit strives to emulate consensus rules and other behavior as close as possible. As a result, the testkit checks incoming transactions regardless of their source with Blockchain::check_tx and does not create blocks with incorrect transactions. Exonum nodes never include transactions failing check_tx in block proposals, and any proposal with such a transaction is incorrect per consensus rules.

Similarly, incorrect transactions are not included to the pool of the testkit since they are not included into the pools of real Exonum nodes and are not broadcast by the nodes. Note that it is still possible to obtain an incorrect transaction in the pool, e.g., by stopping the service targeted by an otherwise valid transaction. Again, the testkit does not differ in this regard from real nodes.

The testkit will panic if explicitly asked to create a block with an incorrect transaction (e.g., via create_block_with_transaction) or to add it to the pool via add_tx. If an incorrect transaction is being added to pool or block implicitly (e.g., via create_block or by generating a transaction in the service), the testkit will ignore the transaction and log this event with the warn level.

Examples

See the crate-level docs for examples of usage.

Methods

impl TestKit[src]

pub fn for_rust_service(
    service_factory: impl ServiceFactory,
    name: impl Into<String>,
    id: InstanceId,
    constructor: impl BinaryValue
) -> Self
[src]

Creates a new TestKit with a single validator with the given Rust service.

pub fn poll_control_messages(&mut self) -> Vec<ExternalMessage>[src]

Returns control messages received by the testkit since the last call to this method.

This method is only available if the crate is compiled with the exonum-node feature, which is off by default.

pub fn api(&mut self) -> TestKitApi[src]

Creates an instance of TestKitApi to test the API provided by services.

pub fn poll_events(&mut self)[src]

Polls the existing events from the event loop until exhaustion. Does not wait until new events arrive.

pub fn snapshot(&self) -> Box<dyn Snapshot>[src]

Returns a snapshot of the current blockchain state.

pub fn blockchain(&self) -> Blockchain[src]

Returns a blockchain used by the testkit.

pub fn checkpoint(&mut self)[src]

Sets a checkpoint for a future rollback.

pub fn rollback(&mut self)[src]

Rolls the blockchain back to the latest checkpoint.

Examples

Rollbacks are useful in testing alternative scenarios (e.g., transactions executed in different order and/or in different blocks) that require an expensive setup:

// Suppose we test this service interface:
#[exonum_interface]
pub trait ExampleInterface<Ctx> {
    type Output;
    #[interface_method(id = 0)]
    fn example_tx(&self, ctx: Ctx, arg: String) -> Self::Output;
}

// ...implemented by this service:
#[service_dispatcher(implements("ExampleInterface"))]
pub struct ExampleService;
impl Service for ExampleService {}
// ...with this ID:
const SERVICE_ID: u32 = 1;

let service = Spec::new(ExampleService).with_instance(SERVICE_ID, "example", ());
let mut testkit = TestKitBuilder::validator().with(service).build();
expensive_setup(&mut testkit);
let keys = KeyPair::random();
let tx_a = keys.example_tx(SERVICE_ID, "foo".into());
let tx_b = keys.example_tx(SERVICE_ID, "bar".into());

testkit.checkpoint();
testkit.create_block_with_transactions(vec![tx_a.clone(), tx_b.clone()]);
assert_something_about(&testkit);
testkit.rollback();

testkit.checkpoint();
testkit.create_block_with_transaction(tx_a);
testkit.create_block_with_transaction(tx_b);
assert_something_about(&testkit);
testkit.rollback();

pub fn create_block_with_transactions<I>(
    &mut self,
    txs: I
) -> BlockWithTransactions where
    I: IntoIterator<Item = Verified<AnyTx>>, 
[src]

Creates a block with the given transactions. Transactions that are in the pool will be ignored.

Return value

Returns information about the created block.

Panics

  • Panics if any of transactions has been already committed to the blockchain.
  • Panics if any of transactions in the created block is incorrect. See the type-level docs for more details.

pub fn create_block_with_transaction(
    &mut self,
    tx: Verified<AnyTx>
) -> BlockWithTransactions
[src]

Creates a block with the given transaction. Transactions that are in the pool will be ignored.

Return value

Returns information about the created block.

Panics

  • Panics if the given transaction has been already committed to the blockchain.
  • Panics if the transaction is incorrect. See the type-level docs for more details.

pub fn create_block_with_tx_hashes(
    &mut self,
    tx_hashes: &[Hash]
) -> BlockWithTransactions
[src]

Creates block with the specified transactions. The transactions must be previously sent to the node via API or directly put into the channel().

Return value

Returns information about the created block.

Panics

  • Panics in the case any of transaction hashes are not in the pool.
  • Panics if any of transactions in the created block is incorrect. See the type-level docs for more details.

pub fn create_block(&mut self) -> BlockWithTransactions[src]

Creates a block with all correct transactions in the pool.

Transaction correctness is defined per Blockchain::check_tx method. See the type-level docs for more details.

Return value

Returns information about the created block.

pub fn add_tx(&mut self, transaction: Verified<AnyTx>)[src]

Adds a transaction into the persistent pool.

Panics

  • Panics if the transaction is incorrect. See the type-level docs for more details.

pub fn is_tx_in_pool(&self, tx_hash: &Hash) -> bool[src]

Checks if a transaction with the specified hash is found in the transaction pool.

pub fn create_blocks_until(&mut self, height: Height)[src]

Creates a chain of blocks until a given height.

Example

let mut testkit = TestKitBuilder::validator().build();
testkit.create_blocks_until(Height(5));
assert_eq!(Height(5), testkit.height());

pub fn last_block_hash(&self) -> Hash[src]

Returns the hash of latest committed block.

pub fn height(&self) -> Height[src]

Returns the height of latest committed block.

pub fn consensus_config(&self) -> ConsensusConfig[src]

Returns an actual blockchain configuration.

pub fn validator(&self, id: ValidatorId) -> TestNode[src]

Returns reference to validator with the given identifier.

Panics

  • Panics if validator with the given ID is absent in the test network.

pub fn majority_count(&self) -> usize[src]

Returns sufficient number of validators for the Byzantine Fault Tolerance consensus.

pub fn leader(&self) -> TestNode[src]

Returns the leader on the current height. At the moment, this is always the first validator.

pub fn network(&self) -> &TestNetwork[src]

Returns the reference to the test network.

pub fn network_mut(&mut self) -> &mut TestNetwork[src]

Returns the mutable reference to test network for manual modifications.

pub fn us(&self) -> TestNode[src]

Returns the node in the emulated network, from whose perspective the testkit operates.

pub fn stop(self) -> StoppedTestKit[src]

Emulates stopping the node. The stopped node can then be restart()ed.

See StoppedTestKit documentation for more details how to use this method.

Trait Implementations

impl Debug for TestKit[src]

Auto Trait Implementations

impl !RefUnwindSafe for TestKit

impl Send for TestKit

impl !Sync for TestKit

impl Unpin for TestKit

impl !UnwindSafe for TestKit

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,