Class TestKit

All Implemented Interfaces:
CloseableNativeProxy, java.lang.AutoCloseable

public final class TestKit
extends AbstractCloseableNativeProxy
TestKit for testing blockchain services. It offers simple network configuration emulation (with no real network setup). Although it is possible to add several validator nodes to this network, only one node will create the service instances, execute their operations (e.g., Service.afterCommit(BlockCommittedEvent) method logic), and provide access to its state.

Only the emulated node has a pool of unconfirmed transactions where a service can submit new transaction messages through Node.submitTransaction(RawTransaction); or the test code through createBlockWithTransactions(TransactionMessage...). All transactions from the pool are committed when a new block is created with createBlock().

When TestKit is created, Exonum blockchain instance is initialized — service instances are initialized and genesis block is committed. Then the public API handlers are created.

See Also:
Service Testing, Pool of Unconfirmed Transactions
  • Nested Class Summary

    Nested Classes 
    Modifier and Type Class Description
    static class  TestKit.Builder
    Builder for the TestKit.
  • Field Summary

    Fields 
    Modifier and Type Field Description
    static short MAX_VALIDATOR_COUNT_WITH_ENABLED_TIME_SERVICE
    The maximum number of validators supported by TestKit when a time oracle is enabled.

    Fields inherited from class com.exonum.binding.core.proxy.AbstractNativeProxy

    nativeHandle
  • Method Summary

    Modifier and Type Method Description
    <ResultT> ResultT applySnapshot​(java.util.function.Function<Snapshot,​ResultT> snapshotFunction)
    Performs the given function with a snapshot of the current database state (i.e., the one that corresponds to the latest committed block) and returns a result of its execution.
    static TestKit.Builder builder()
    Creates a new builder for the TestKit.
    Block createBlock()
    Creates a block with all in-pool transactions.
    Block createBlockWithTransactions​(TransactionMessage... transactions)
    Creates a block with the given transaction(s).
    Block createBlockWithTransactions​(java.lang.Iterable<TransactionMessage> transactions)
    Creates a block with the given transactions.
    protected void disposeInternal()
    Releases any resources owned by this proxy (e.g., the corresponding native object).
    java.util.List<TransactionMessage> findTransactionsInPool​(java.util.function.Predicate<TransactionMessage> predicate)
    Returns a list of in-pool transactions that match the given predicate.
    static TestKit forService​(ServiceArtifactId artifactId, java.lang.String artifactFilename, java.lang.String serviceName, int serviceId, java.nio.file.Path artifactsDirectory)
    Deploys and creates a single service with no configuration and with a single validator node in this TestKit network.
    BlockchainData getBlockchainData​(java.lang.String serviceName)
    Returns the snapshot of the current state of the blockchain data for a service with the given name.
    EmulatedNode getEmulatedNode()
    Returns the context of the node that the TestKit emulates (i.e., on which it instantiates and executes services).
    int getPort()
    Returns the TCP port on which the service REST API is mounted.
    Prefixed getServiceData​(java.lang.String serviceName)
    Returns the snapshot of the current state of the service data for a service with the given name.
    Snapshot getSnapshot()
    Returns a snapshot of the current database state (i.e., the one that corresponds to the latest committed block).
    java.util.List<TransactionMessage> getTransactionPool()
    Returns a list of in-pool transactions.
    void withSnapshot​(java.util.function.Consumer<Snapshot> snapshotFunction)
    Performs the given function with a snapshot of the current database state (i.e., the one that corresponds to the latest committed block).

    Methods inherited from class com.exonum.binding.core.proxy.AbstractCloseableNativeProxy

    close, getNativeHandle

    Methods inherited from class com.exonum.binding.core.proxy.AbstractNativeProxy

    isValidHandle

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • MAX_VALIDATOR_COUNT_WITH_ENABLED_TIME_SERVICE

      public static final short MAX_VALIDATOR_COUNT_WITH_ENABLED_TIME_SERVICE
      The maximum number of validators supported by TestKit when a time oracle is enabled. The time oracle does not work in a TestKit with a higher number of validators because the time oracle requires the majority of those validators to submit transactions with time updates, but only a single emulated node submits them.
      See Also:
      Constant Field Values
  • Method Details

    • forService

      public static TestKit forService​(ServiceArtifactId artifactId, java.lang.String artifactFilename, java.lang.String serviceName, int serviceId, java.nio.file.Path artifactsDirectory)
      Deploys and creates a single service with no configuration and with a single validator node in this TestKit network.
      Parameters:
      artifactId - the id of the artifact
      artifactFilename - a filename of the service artifact in the directory for artifacts
      serviceName - the name of the service
      serviceId - the id of the service, must be in range [0; 1023]
      artifactsDirectory - the directory from which the service runtime loads service artifacts
      Throws:
      java.lang.IllegalArgumentException - if serviceId is not in range [0; 1023]
    • createBlockWithTransactions

      public Block createBlockWithTransactions​(TransactionMessage... transactions)
      Creates a block with the given transaction(s). Transactions are applied in the lexicographical order of their hashes. In-pool transactions will be ignored.
      Returns:
      created block
      Throws:
      java.lang.RuntimeException - if any transaction does not belong to a started service (i.e., has an unknown service id)
    • createBlockWithTransactions

      public Block createBlockWithTransactions​(java.lang.Iterable<TransactionMessage> transactions)
      Creates a block with the given transactions. Transactions are applied in the lexicographical order of their hashes. In-pool transactions will be ignored.
      Returns:
      created block
      Throws:
      java.lang.RuntimeException - if any transaction does not belong to a started service (i.e., has an unknown service id)
    • createBlock

      public Block createBlock()
      Creates a block with all in-pool transactions. Transactions are applied in the lexicographical order of their hashes.
      Returns:
      created block
    • getTransactionPool

      public java.util.List<TransactionMessage> getTransactionPool()
      Returns a list of in-pool transactions. Please note that the order of transactions in pool does not necessarily match the order in which the clients submitted the messages.
    • findTransactionsInPool

      public java.util.List<TransactionMessage> findTransactionsInPool​(java.util.function.Predicate<TransactionMessage> predicate)
      Returns a list of in-pool transactions that match the given predicate.
    • getServiceData

      public Prefixed getServiceData​(java.lang.String serviceName)
      Returns the snapshot of the current state of the service data for a service with the given name.

      A shortcut for BlockchainData.getExecutingServiceData().

      Parameters:
      serviceName - the name of the service instance to which data the access is needed
      Throws:
      java.lang.IllegalArgumentException - if the service with the given name does not exist
    • getBlockchainData

      public BlockchainData getBlockchainData​(java.lang.String serviceName)
      Returns the snapshot of the current state of the blockchain data for a service with the given name.
      Parameters:
      serviceName - the name of the service instance to which data the access is needed
      Throws:
      java.lang.IllegalArgumentException - if the service with the given name does not exist
      See Also:
      getSnapshot(), getServiceData(String)
    • withSnapshot

      public void withSnapshot​(java.util.function.Consumer<Snapshot> snapshotFunction)
      Performs the given function with a snapshot of the current database state (i.e., the one that corresponds to the latest committed block). In-pool (not yet processed) transactions are also accessible with it in blockchain.

      This method destroys the snapshot once the passed closure completes, compared to getSnapshot(), which disposes created snapshots only when TestKit is closed.

      Parameters:
      snapshotFunction - a function to execute
      See Also:
      applySnapshot(Function)
    • applySnapshot

      public <ResultT> ResultT applySnapshot​(java.util.function.Function<Snapshot,​ResultT> snapshotFunction)
      Performs the given function with a snapshot of the current database state (i.e., the one that corresponds to the latest committed block) and returns a result of its execution. In-pool (not yet processed) transactions are also accessible with it in blockchain.

      This method destroys the snapshot once the passed closure completes, compared to getSnapshot(), which disposes created snapshots only when TestKit is closed.

      Consider using withSnapshot(Consumer) when returning the result of given function is not needed.

      Type Parameters:
      ResultT - a type the function returns
      Parameters:
      snapshotFunction - a function to execute
      Returns:
      the result of applying the given function to the database state
    • getSnapshot

      public Snapshot getSnapshot()
      Returns a snapshot of the current database state (i.e., the one that corresponds to the latest committed block). In-pool (not yet processed) transactions are also accessible with it in blockchain.

      All created snapshots are deleted when this TestKit is closed. It is forbidden to access the snapshots once the TestKit is closed.

      If you need to create a large number (e.g. more than a hundred) of snapshots, it is recommended to use withSnapshot(Consumer) or applySnapshot(Function), which destroy the snapshots once the passed closure completes.

    • getEmulatedNode

      public EmulatedNode getEmulatedNode()
      Returns the context of the node that the TestKit emulates (i.e., on which it instantiates and executes services).
    • getPort

      public int getPort()
      Returns the TCP port on which the service REST API is mounted.
    • disposeInternal

      protected void disposeInternal()
      Description copied from class: AbstractCloseableNativeProxy
      Releases any resources owned by this proxy (e.g., the corresponding native object).

      This method is only called once from AbstractCloseableNativeProxy.close() for a valid proxy and shall not be called directly.

      Specified by:
      disposeInternal in class AbstractCloseableNativeProxy
    • builder

      public static TestKit.Builder builder()
      Creates a new builder for the TestKit. Note that this builder creates a single validator network by default.