mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
test: add the loadtime tool (#9342)
This pull request adds the loadtime tool. This tool leverages the tm-load-test framework. Using the framework means that the only real logic that needs to be written is the logic for Tx generation. The framework does the rest. The tool writes a set of metadata into the transaction, including the current transaction rate, number of connections, specified size of the transaction, and the current time.
This commit is contained in:
committed by
William Banfield
parent
0b58342a46
commit
53e43e7f7d
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,6 +38,7 @@ terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
terraform.tfstate.d
|
||||
test/app/grpc_client
|
||||
test/loadtime/build
|
||||
test/e2e/build
|
||||
test/e2e/networks/*/
|
||||
test/logs
|
||||
|
||||
15
go.mod
15
go.mod
@@ -9,9 +9,6 @@ require (
|
||||
github.com/btcsuite/btcd v0.22.1
|
||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/go-kit/kit v0.12.0
|
||||
github.com/go-kit/log v0.2.1
|
||||
@@ -27,9 +24,9 @@ require (
|
||||
github.com/ory/dockertest v3.3.5+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.13.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa
|
||||
github.com/sasha-s/go-deadlock v0.3.1
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/viper v1.12.0
|
||||
@@ -50,8 +47,10 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/informalsystems/tm-load-test v1.0.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/vektra/mockery/v2 v2.14.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -139,7 +138,6 @@ require (
|
||||
github.com/gostaticanalysis/comment v1.4.2 // indirect
|
||||
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
|
||||
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -176,7 +174,7 @@ require (
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
|
||||
github.com/mgechev/revive v1.2.3 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/buildkit v0.10.3 // indirect
|
||||
@@ -213,6 +211,7 @@ require (
|
||||
github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect
|
||||
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
|
||||
github.com/sashamelentyev/usestdlibvars v1.13.0 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/securego/gosec/v2 v2.13.1 // indirect
|
||||
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
@@ -260,11 +259,9 @@ require (
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools v2.2.0+incompatible // indirect
|
||||
honnef.co/go/tools v0.3.3 // indirect
|
||||
mvdan.cc/gofumpt v0.3.1 // indirect
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
|
||||
|
||||
32
test/loadtime/Makefile
Normal file
32
test/loadtime/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
GOMOD="github.com/tendermint/tendermint/test/loadtime"
|
||||
OUTPUT?=build/loadtime
|
||||
|
||||
build:
|
||||
go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o $(OUTPUT) .
|
||||
.PHONY: build
|
||||
|
||||
check-proto-gen-deps:
|
||||
ifeq (,$(shell which protoc))
|
||||
$(error "protoc is required for Protobuf generation. See instructions for your platform on how to install it.")
|
||||
endif
|
||||
ifeq (,$(shell which protoc-gen-go))
|
||||
$(error "protoc-gen-go is required for Protobuf generation. See instructions for your platform on how to install it.")
|
||||
endif
|
||||
.PHONY: check-proto-gen-deps
|
||||
|
||||
check-proto-format-deps:
|
||||
ifeq (,$(shell which clang-format))
|
||||
$(error "clang-format is required for Protobuf formatting. See instructions for your platform on how to install it.")
|
||||
endif
|
||||
.PHONY: check-proto-format-deps
|
||||
|
||||
proto-format: check-proto-format-deps
|
||||
@echo "Formatting Protobuf files"
|
||||
@find . -name '*.proto' -exec clang-format -i {} \;
|
||||
.PHONY: proto-format
|
||||
|
||||
proto-gen: check-proto-gen-deps
|
||||
@echo "Generating Protobuf files"
|
||||
@find . -name '*.proto' -exec protoc \
|
||||
--go_out=paths=source_relative:. {} \;
|
||||
.PHONY: proto-gen
|
||||
32
test/loadtime/README.md
Normal file
32
test/loadtime/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# loadtime
|
||||
|
||||
This directory contains `loadtime`, a tool for generating transaction load against Tendermint.
|
||||
`loadtime` generates transactions that contain the timestamp corresponding to when they were generated
|
||||
as well as additional metadata to track the variables used when generating the load.
|
||||
|
||||
|
||||
## Building loadtime
|
||||
|
||||
The `Makefile` contains a target for building the `loadtime` tool.
|
||||
|
||||
The following command will build the tool and place the resulting binary in `./build/loadtime`.
|
||||
|
||||
```bash
|
||||
make build
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
`loadtime` leverages the [tm-load-test](https://github.com/informalsystems/tm-load-test)
|
||||
framework. As a result, all flags and options specified on the `tm-load-test` apply to
|
||||
`loadtime`.
|
||||
|
||||
Below is a basic invocation for generating load against a Tendermint websocket running
|
||||
on `localhost:25567`
|
||||
|
||||
```bash
|
||||
loadtime \
|
||||
-c 1 -T 10 -r 1000 -s 1024 \
|
||||
--broadcast-tx-method sync \
|
||||
--endpoints ws://localhost:26657/websocket
|
||||
```
|
||||
11
test/loadtime/basic.sh
Executable file
11
test/loadtime/basic.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# A basic invocation of the loadtime tool.
|
||||
|
||||
./build/loadtime \
|
||||
-c 1 -T 10 -r 1000 -s 1024 \
|
||||
--broadcast-tx-method sync \
|
||||
--endpoints ws://localhost:26657/websocket
|
||||
|
||||
89
test/loadtime/main.go
Normal file
89
test/loadtime/main.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
|
||||
"github.com/informalsystems/tm-load-test/pkg/loadtest"
|
||||
"github.com/tendermint/tendermint/test/loadtime/payload"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// Ensure all of the interfaces are correctly satisfied.
|
||||
var (
|
||||
_ loadtest.ClientFactory = (*ClientFactory)(nil)
|
||||
_ loadtest.Client = (*TxGenerator)(nil)
|
||||
)
|
||||
|
||||
// ClientFactory implements the loadtest.ClientFactory interface.
|
||||
type ClientFactory struct{}
|
||||
|
||||
// TxGenerator is responsible for generating transactions.
|
||||
// TxGenerator holds the set of information that will be used to generate
|
||||
// each transaction.
|
||||
type TxGenerator struct {
|
||||
conns uint64
|
||||
rate uint64
|
||||
size uint64
|
||||
payloadSizeBytes uint64
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := loadtest.RegisterClientFactory("loadtime-client", &ClientFactory{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
loadtest.Run(&loadtest.CLIConfig{
|
||||
AppName: "loadtime",
|
||||
AppShortDesc: "Generate timestamped transaction load.",
|
||||
AppLongDesc: "loadtime generates transaction load for the purpose of measuring the end-to-end latency of a transaction from submission to execution in a Tendermint network.",
|
||||
DefaultClientFactory: "loadtime-client",
|
||||
})
|
||||
}
|
||||
|
||||
func (f *ClientFactory) ValidateConfig(cfg loadtest.Config) error {
|
||||
psb, err := payload.CalculateUnpaddedSizeBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if psb > cfg.Size {
|
||||
return fmt.Errorf("payload size exceeds configured size")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *ClientFactory) NewClient(cfg loadtest.Config) (loadtest.Client, error) {
|
||||
psb, err := payload.CalculateUnpaddedSizeBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &TxGenerator{
|
||||
conns: uint64(cfg.Connections),
|
||||
rate: uint64(cfg.Rate),
|
||||
size: uint64(cfg.Size),
|
||||
payloadSizeBytes: uint64(psb),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *TxGenerator) GenerateTx() ([]byte, error) {
|
||||
p := &payload.Payload{
|
||||
Time: timestamppb.Now(),
|
||||
Connections: c.conns,
|
||||
Rate: c.rate,
|
||||
Size: c.size,
|
||||
Padding: make([]byte, c.size-c.payloadSizeBytes),
|
||||
}
|
||||
_, err := rand.Read(p.Padding)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := proto.Marshal(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// prepend a single key so that the kv store only ever stores a single
|
||||
// transaction instead of storing all tx and ballooning in size.
|
||||
return append([]byte("a="), b...), nil
|
||||
}
|
||||
190
test/loadtime/payload/payload.pb.go
Normal file
190
test/loadtime/payload/payload.pb.go
Normal file
@@ -0,0 +1,190 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.20.1
|
||||
// source: payload/payload.proto
|
||||
|
||||
package payload
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Payload struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Connections uint64 `protobuf:"varint,1,opt,name=connections,proto3" json:"connections,omitempty"`
|
||||
Rate uint64 `protobuf:"varint,2,opt,name=rate,proto3" json:"rate,omitempty"`
|
||||
Size uint64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
Time *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=time,proto3" json:"time,omitempty"`
|
||||
Padding []byte `protobuf:"bytes,5,opt,name=padding,proto3" json:"padding,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Payload) Reset() {
|
||||
*x = Payload{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_payload_payload_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Payload) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Payload) ProtoMessage() {}
|
||||
|
||||
func (x *Payload) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_payload_payload_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Payload.ProtoReflect.Descriptor instead.
|
||||
func (*Payload) Descriptor() ([]byte, []int) {
|
||||
return file_payload_payload_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Payload) GetConnections() uint64 {
|
||||
if x != nil {
|
||||
return x.Connections
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Payload) GetRate() uint64 {
|
||||
if x != nil {
|
||||
return x.Rate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Payload) GetSize() uint64 {
|
||||
if x != nil {
|
||||
return x.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Payload) GetTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Time
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Payload) GetPadding() []byte {
|
||||
if x != nil {
|
||||
return x.Padding
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_payload_payload_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_payload_payload_proto_rawDesc = []byte{
|
||||
0x0a, 0x15, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x6c, 0x6f, 0x61, 0x64, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9d, 0x01, 0x0a, 0x07, 0x50,
|
||||
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6e,
|
||||
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x74, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x72, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d,
|
||||
0x69, 0x6e, 0x74, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x74,
|
||||
0x65, 0x73, 0x74, 0x2f, 0x6c, 0x6f, 0x61, 0x64, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x70, 0x61, 0x79,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_payload_payload_proto_rawDescOnce sync.Once
|
||||
file_payload_payload_proto_rawDescData = file_payload_payload_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_payload_payload_proto_rawDescGZIP() []byte {
|
||||
file_payload_payload_proto_rawDescOnce.Do(func() {
|
||||
file_payload_payload_proto_rawDescData = protoimpl.X.CompressGZIP(file_payload_payload_proto_rawDescData)
|
||||
})
|
||||
return file_payload_payload_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_payload_payload_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_payload_payload_proto_goTypes = []interface{}{
|
||||
(*Payload)(nil), // 0: loadtime.payload.Payload
|
||||
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
|
||||
}
|
||||
var file_payload_payload_proto_depIdxs = []int32{
|
||||
1, // 0: loadtime.payload.Payload.time:type_name -> google.protobuf.Timestamp
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_payload_payload_proto_init() }
|
||||
func file_payload_payload_proto_init() {
|
||||
if File_payload_payload_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_payload_payload_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Payload); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_payload_payload_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_payload_payload_proto_goTypes,
|
||||
DependencyIndexes: file_payload_payload_proto_depIdxs,
|
||||
MessageInfos: file_payload_payload_proto_msgTypes,
|
||||
}.Build()
|
||||
File_payload_payload_proto = out.File
|
||||
file_payload_payload_proto_rawDesc = nil
|
||||
file_payload_payload_proto_goTypes = nil
|
||||
file_payload_payload_proto_depIdxs = nil
|
||||
}
|
||||
17
test/loadtime/payload/payload.proto
Normal file
17
test/loadtime/payload/payload.proto
Normal file
@@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
package loadtime.payload;
|
||||
|
||||
option go_package = "github.com/tendermint/tendermint/test/loadtime/payload";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// Payload is the structure of the loadtime transaction. Proto has a compact
|
||||
// encoded representation, making it ideal for the loadtime usecase which aims to
|
||||
// keep the generated transactions small.
|
||||
message Payload {
|
||||
uint64 connections = 1;
|
||||
uint64 rate = 2;
|
||||
uint64 size = 3;
|
||||
google.protobuf.Timestamp time = 4;
|
||||
bytes padding = 5;
|
||||
}
|
||||
23
test/loadtime/payload/size.go
Normal file
23
test/loadtime/payload/size.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package payload
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func CalculateUnpaddedSizeBytes() (int, error) {
|
||||
p := &Payload{
|
||||
Time: timestamppb.Now(),
|
||||
Connections: math.MaxUint64,
|
||||
Rate: math.MaxUint64,
|
||||
Size: math.MaxUint64,
|
||||
Padding: make([]byte, 1),
|
||||
}
|
||||
b, err := proto.Marshal(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
19
test/loadtime/payload/size_test.go
Normal file
19
test/loadtime/payload/size_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package payload_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tendermint/tendermint/test/loadtime/payload"
|
||||
)
|
||||
|
||||
const payloadSizeTarget = 1024 // 1kb
|
||||
|
||||
func TestCalculateSize(t *testing.T) {
|
||||
s, err := payload.CalculateUnpaddedSizeBytes()
|
||||
if err != nil {
|
||||
t.Fatalf("calculating unpadded size %s", err)
|
||||
}
|
||||
if s > payloadSizeTarget {
|
||||
t.Fatalf("unpadded payload size %d exceeds target %d", s, payloadSizeTarget)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user