[−][src]Struct exonum_testkit::TestKit
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]
service_factory: impl ServiceFactory,
name: impl Into<String>,
id: InstanceId,
constructor: impl BinaryValue
) -> Self
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]
&mut self,
txs: I
) -> BlockWithTransactions where
I: IntoIterator<Item = Verified<AnyTx>>,
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]
&mut self,
tx: Verified<AnyTx>
) -> BlockWithTransactions
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]
&mut self,
tx_hashes: &[Hash]
) -> BlockWithTransactions
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
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]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,