# README

Tendermint Load Testing Framework

tm-load-test comes with the ability to define your own load testing clients. A client is the part of the load tester that generates transactions specific to a particular ABCI application. By default, tm-load-test comes with support for the kvstore ABCI app, but what if you want to extend it to test your own ABCI app?

Requirements

To follow this guide, you'll need:

  • Go v1.12+

Creating a Custom ABCI Load Testing App

Step 1: Create your project

You'll effectively have to create your own load testing tool by importing the tm-load-test package into a new project.

mkdir -p /your/project/
cd /your/project
go mod init github.com/you/my-load-tester

Step 2: Create your load testing client

Create a client that generates transactions for your ABCI app. For an example, you can look at the kvstore client code. Put this in ./pkg/myabciapp/client.go

package myabciapp

import "github.com/informalsystems/tm-load-test/pkg/loadtest"

// MyABCIAppClientFactory creates instances of MyABCIAppClient
type MyABCIAppClientFactory struct {}

// MyABCIAppClientFactory implements loadtest.ClientFactory
var _ loadtest.ClientFactory = (*MyABCIAppClientFactory)(nil)

// MyABCIAppClient is responsible for generating transactions. Only one client
// will be created per connection to the remote Tendermint RPC endpoint, and
// each client will be responsible for maintaining its own state in a
// thread-safe manner.
type MyABCIAppClient struct {}

// MyABCIAppClient implements loadtest.Client
var _ loadtest.Client = (*MyABCIAppClient)(nil)

func (f *MyABCIAppClientFactory) ValidateConfig(cfg loadtest.Config) error {
    // Do any checks here that you need to ensure that the load test 
    // configuration is compatible with your client.
    return nil
}

func (f *MyABCIAppClientFactory) NewClient(cfg loadtest.Config) (loadtest.Client, error) {
    return &MyABCIAppClient{}, nil
}

// GenerateTx must return the raw bytes that make up the transaction for your
// ABCI app. The conversion to base64 will automatically be handled by the 
// loadtest package, so don't worry about that. Only return an error here if you
// want to completely fail the entire load test operation.
func (c *MyABCIAppClient) GenerateTx() ([]byte, error) {
    return []byte("this is my transaction"), nil
}

Step 3: Create your CLI

Create your own CLI in ./cmd/my-load-tester/main.go:

package main

import (
    "github.com/informalsystems/tm-load-test/pkg/loadtest"
    "github.com/you/my-load-tester/pkg/myabciapp"
)

func main() {
    if err := loadtest.RegisterClientFactory("my-abci-app-name", &myabciapp.MyABCIAppClientFactory{}); err != nil {
        panic(err)
    }
    // The loadtest.Run method will handle CLI argument parsing, errors, 
    // configuration, instantiating the load test and/or coordinator/worker
    // operations, etc. All it needs is to know which client factory to use for
    // its load testing.
    loadtest.Run(&loadtest.CLIConfig{
        AppName:              "my-load-tester",
        AppShortDesc:         "Load testing application for My ABCI App (TM)",
        AppLongDesc:          "Some long description on how to use the tool",
        DefaultClientFactory: "my-abci-app-name",
    })
}

For an example of very simple integration testing, you could do something similar to what's covered in integration_test.go.

Step 4: Build your CLI

Then build the executable:

go build -o ./build/my-load-tester ./cmd/my-load-tester/main.go

Step 5: Run your load test!

Then just follow the same instructions as for running the tm-load-test tool to run your own tool. It will use the same command line parameters.

# Functions

ExecuteStandalone will run a standalone (non-coordinator/worker) load test.
No description provided by the author
No description provided by the author
NewTransactor initiates a WebSockets connection to the given host address.
No description provided by the author
No description provided by the author
RegisterClientFactory allows us to programmatically register different client factories to easily switch between different ones at runtime.
Run must be executed from your `main` function in your Go code.

# Constants

CLIVersion must be manually updated as new versions are released.
Allows for 6,471,002 random client IDs (62C5).
Select from any of supplied and/or discovered endpoints.
Select newly discovered endpoints only (excluding supplied endpoints).
Select only the supplied endpoint(s) for load testing (the default).

# Structs

No description provided by the author
No description provided by the author
CLIConfig allows developers to customize their own load testing tool.
Config represents the configuration for a single client (i.e.
No description provided by the author
Coordinator is a WebSockets server that allows workers to connect to it to obtain configuration information.
CoordinatorConfig is the configuration options specific to a coordinator node.
DefaultNodeInfo is the basic node information exchanged between two peers during the Tendermint P2P handshake.
DefaultNodeInfoOther is the misc.
FlowStatus represents the current Monitor status.
KVStoreClient generates arbitrary transactions (random key=value pairs) to be sent to the kvstore ABCI application.
KVStoreClientFactory creates load testing clients to interact with the built-in Tendermint kvstore ABCI application.
NetInfo corresponds to the JSON-RPC response format produced by the Tendermint Core v0.34.x net_info RPC API.
Peer represents a network peer.
ProtocolVersion contains the protocol versions for the software.
No description provided by the author
RPCRequest corresponds to the JSON-RPC request data format accepted by Tendermint Core v0.34.x.
No description provided by the author
Transactor represents a single wire-level connection to a Tendermint RPC endpoint, and this is responsible for sending transactions to that endpoint.
TransactorGroup allows us to encapsulate the management of a group of transactors.
Worker is a WebSockets client that interacts with the Coordinator node to (1) fetch its configuration, (2) execute a load test, and (3) report back to the coordinator node regularly on its progress.
WorkerConfig is the configuration options specific to a worker node.

# Interfaces

Client generates transactions to be sent to a specific endpoint.
ClientFactory produces load testing clients.

# Type aliases

HexBytes enables HEX-encoding for json/encoding.
JSONDuration is a time.Duration whose JSON representation is a string containing an integer value.
JSONStrInt is an integer whose JSON representation is a string.
JSONStrInt64 is a int64 whose JSON representation is a string.
JSONStrUint64 is a uint64 whose JSON representation is a string.
Percent represents a percentage in increments of 1/1000th of a percent.