Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport e2e-test of the latest tendermint main branch #536

Merged
merged 6 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:
**/**.go
go.mod
go.sum
Makefile
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-${{ matrix.part }}"
Expand Down Expand Up @@ -97,6 +98,7 @@ jobs:
**/**.go
go.mod
go.sum
Makefile
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-00-coverage"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
- release/**

env:
TAG: ostracon/e2e-node
TAG: ostracon/e2e-node:local-version # See test/e2e/Makefile:docker
CACHE_DIR: /tmp/ostracon/e2etest

jobs:
Expand Down
42 changes: 42 additions & 0 deletions libs/log/lazy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package log

import (
"fmt"

tmbytes "github.com/line/ostracon/libs/bytes"
)

type LazySprintf struct {
format string
args []interface{}
}

// NewLazySprintf defers fmt.Sprintf until the Stringer interface is invoked.
// This is particularly useful for avoiding calling Sprintf when debugging is not
// active.
func NewLazySprintf(format string, args ...interface{}) *LazySprintf {
return &LazySprintf{format, args}
}

func (l *LazySprintf) String() string {
return fmt.Sprintf(l.format, l.args...)
}

type LazyBlockHash struct {
block hashable
}

type hashable interface {
Hash() tmbytes.HexBytes
}

// NewLazyBlockHash defers block Hash until the Stringer interface is invoked.
// This is particularly useful for avoiding calling Sprintf when debugging is not
// active.
func NewLazyBlockHash(block hashable) *LazyBlockHash {
return &LazyBlockHash{block}
}

func (l *LazyBlockHash) String() string {
return l.block.Hash().String()
}
29 changes: 29 additions & 0 deletions libs/log/lazy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package log

import (
tmbytes "github.com/line/ostracon/libs/bytes"
"github.com/stretchr/testify/require"
"testing"
)

func TestNewLazySprintf(t *testing.T) {
format := "echo:%s"
args := make([]interface{}, 0, 1)
args = append(args, "hello")
expected := LazySprintf{format: format, args: args}
actual := NewLazySprintf(format, args...)
require.Equal(t, expected.String(), actual.String())
}

func TestNewLazyBlockHash(t *testing.T) {
block := testHashable{}
expected := LazyBlockHash{block: block}
actual := NewLazyBlockHash(block)
require.Equal(t, expected.String(), actual.String())
}

type testHashable struct{}

func (testHashable) Hash() tmbytes.HexBytes {
return []byte{0}
}
6 changes: 3 additions & 3 deletions libs/log/oc_logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package log_test

import (
"bytes"
"io/ioutil"
"io"
"strings"
"testing"

Expand Down Expand Up @@ -90,11 +90,11 @@ func TestError(t *testing.T) {
}

func BenchmarkOCLoggerSimple(b *testing.B) {
benchmarkRunner(b, log.NewOCLogger(ioutil.Discard), baseInfoMessage)
benchmarkRunner(b, log.NewOCLogger(io.Discard), baseInfoMessage)
}

func BenchmarkOCLoggerContextual(b *testing.B) {
benchmarkRunner(b, log.NewOCLogger(ioutil.Discard), withInfoMessage)
benchmarkRunner(b, log.NewOCLogger(io.Discard), withInfoMessage)
}

func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) {
Expand Down
8 changes: 7 additions & 1 deletion libs/log/ocfmt_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (l ocfmtLogger) Log(keyvals ...interface{}) error {
switch keyvals[i] {
case kitlevel.Key():
excludeIndexes = append(excludeIndexes, i)
switch keyvals[i+1].(type) { // nolint:gocritic
switch keyvals[i+1].(type) { //nolint:gocritic
case string:
lvl = keyvals[i+1].(string)
case kitlevel.Value:
Expand All @@ -87,6 +87,12 @@ func (l ocfmtLogger) Log(keyvals ...interface{}) error {
if b, ok := keyvals[i+1].([]byte); ok {
keyvals[i+1] = strings.ToUpper(hex.EncodeToString(b))
}

// Realize stringers
if s, ok := keyvals[i+1].(fmt.Stringer); ok {
keyvals[i+1] = s.String()
}

}

// Form a custom Ostracon line
Expand Down
13 changes: 6 additions & 7 deletions libs/log/ocfmt_logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package log_test
import (
"bytes"
"errors"
"io/ioutil"
"io"
"math"
"regexp"
"testing"
Expand Down Expand Up @@ -62,16 +62,16 @@ func TestOCFmtLogger(t *testing.T) {
}

func BenchmarkOCFmtLoggerSimple(b *testing.B) {
benchmarkRunnerKitlog(b, log.NewOCFmtLogger(ioutil.Discard), baseMessage)
benchmarkRunnerKitlog(b, log.NewOCFmtLogger(io.Discard), baseMessage)
}

func BenchmarkOCFmtLoggerContextual(b *testing.B) {
benchmarkRunnerKitlog(b, log.NewOCFmtLogger(ioutil.Discard), withMessage)
benchmarkRunnerKitlog(b, log.NewOCFmtLogger(io.Discard), withMessage)
}

func TestOCFmtLoggerConcurrency(t *testing.T) {
t.Parallel()
testConcurrency(t, log.NewOCFmtLogger(ioutil.Discard), 10000)
testConcurrency(t, log.NewOCFmtLogger(io.Discard), 10000)
}

func benchmarkRunnerKitlog(b *testing.B, logger kitlog.Logger, f func(kitlog.Logger)) {
Expand All @@ -83,10 +83,9 @@ func benchmarkRunnerKitlog(b *testing.B, logger kitlog.Logger, f func(kitlog.Log
}
}

//nolint: errcheck // ignore errors
var (
baseMessage = func(logger kitlog.Logger) { logger.Log("foo_key", "foo_value") }
withMessage = func(logger kitlog.Logger) { kitlog.With(logger, "a", "b").Log("d", "f") }
baseMessage = func(logger kitlog.Logger) { logger.Log("foo_key", "foo_value") } //nolint:errcheck
withMessage = func(logger kitlog.Logger) { kitlog.With(logger, "a", "b").Log("d", "f") } //nolint:errcheck
)

// These test are designed to be run with the race detector.
Expand Down
12 changes: 6 additions & 6 deletions test/e2e/Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
all: docker generator runner

docker:
docker build --progress=plain --tag ostracon/e2e-node -f docker/Dockerfile ../..
# See the default version on test/e2e/pkg/testnet.go:LoadTestnet
# Relate the "docker-compose.yml" on test/e2e/pkg/infra/docker/docker.go:dockerComposeBytes
# Relate the "cleanup" on test/e2e/runner/cleanup.go:cleanupDir
docker build --progress=plain \
--tag ostracon/e2e-node:local-version \
-f docker/Dockerfile ../..

# We need to build support for database backends into the app in
# order to build a binary with an Ostracon node in it (for built-in
# ABCI testing).
node:
go build -o build/node -tags libsodium,badgerdb,boltdb,cleveldb,rocksdb ./node

# To be used primarily by the e2e docker instance. If you want to produce this binary
# elsewhere, then run go build in the maverick directory.
maverick:
go build -o build/maverick -tags libsodium,badgerdb,boltdb,cleveldb,rocksdb ../maverick

generator:
go build -o build/generator -tags libsodium ./generator

Expand Down
10 changes: 5 additions & 5 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ Random (but deterministic) combinations of testnets can be generated with `gener
```sh
./build/generator -d networks/generated/

# Split networks into 4 groups (by filename)
./build/generator -g 4 -d networks/generated/
# Split networks into 8 groups (by filename)
./build/generator -g 8 -d networks/generated/
```

Multiple testnets can be run with the `run-multiple.sh` script:

```sh
./run-multiple.sh networks/generated/gen-group0[0123]-*.toml
./run-multiple.sh networks/generated/gen-group3-*.toml
```

## Test Stages
Expand All @@ -54,7 +54,7 @@ Auxiliary commands:

* `logs`: outputs all node logs.

* `tail`: tails (follows) node logs until cancelled.
* `tail`: tails (follows) node logs until canceled.

## Tests

Expand All @@ -73,7 +73,7 @@ Optionally, `E2E_NODE` specifies the name of a single testnet node to test.

These environment variables can also be specified in `tests/e2e_test.go` to run tests from an editor or IDE:

```
```go
func init() {
// This can be used to manually specify a testnet manifest and/or node to
// run tests against. The testnet must have been started by the runner first.
Expand Down
18 changes: 15 additions & 3 deletions test/e2e/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"os"
"path/filepath"
"strconv"

cryptoenc "github.com/line/ostracon/crypto/encoding"
"github.com/line/ostracon/proto/ostracon/crypto"
"time"

"github.com/line/ostracon/abci/example/code"
abci "github.com/line/ostracon/abci/types"
cryptoenc "github.com/line/ostracon/crypto/encoding"
"github.com/line/ostracon/libs/log"
"github.com/line/ostracon/proto/ostracon/crypto"
"github.com/line/ostracon/version"
)

Expand Down Expand Up @@ -73,6 +73,13 @@ type Config struct {
//
// height <-> pubkey <-> voting power
ValidatorUpdates map[string]map[string]uint8 `toml:"validator_update"`

// Add artificial delays to each of the main ABCI calls to mimic computation time
// of the application
PrepareProposalDelay time.Duration `toml:"prepare_proposal_delay"`
ProcessProposalDelay time.Duration `toml:"process_proposal_delay"`
CheckTxDelay time.Duration `toml:"check_tx_delay"`
// TODO: add vote extension and finalize block delays once completed (@cmwaters)
}

func DefaultConfig(dir string) *Config {
Expand Down Expand Up @@ -139,6 +146,11 @@ func (app *Application) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx {
Log: err.Error(),
}
}

if app.cfg.CheckTxDelay != 0 {
time.Sleep(app.cfg.CheckTxDelay)
}

return abci.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}
}

Expand Down
12 changes: 5 additions & 7 deletions test/e2e/app/snapshots.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// nolint: gosec
package app

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
Expand All @@ -30,7 +28,7 @@ type SnapshotStore struct {
// NewSnapshotStore creates a new snapshot store.
func NewSnapshotStore(dir string) (*SnapshotStore, error) {
store := &SnapshotStore{dir: dir}
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
if err := store.loadMetadata(); err != nil {
Expand All @@ -45,7 +43,7 @@ func (s *SnapshotStore) loadMetadata() error {
file := filepath.Join(s.dir, "metadata.json")
metadata := []abci.Snapshot{}

bz, err := ioutil.ReadFile(file)
bz, err := os.ReadFile(file)
switch {
case errors.Is(err, os.ErrNotExist):
case err != nil:
Expand All @@ -72,7 +70,7 @@ func (s *SnapshotStore) saveMetadata() error {
// save the file to a new file and move it to make saving atomic.
newFile := filepath.Join(s.dir, "metadata.json.new")
file := filepath.Join(s.dir, "metadata.json")
err = ioutil.WriteFile(newFile, bz, 0644) // nolint: gosec
err = os.WriteFile(newFile, bz, 0o644) //nolint: gosec
if err != nil {
return err
}
Expand All @@ -93,7 +91,7 @@ func (s *SnapshotStore) Create(state *State) (abci.Snapshot, error) {
Hash: hashItems(state.Values),
Chunks: byteChunks(bz),
}
err = ioutil.WriteFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", state.Height)), bz, 0644)
err = os.WriteFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", state.Height)), bz, 0o644) //nolint:gosec
if err != nil {
return abci.Snapshot{}, err
}
Expand Down Expand Up @@ -122,7 +120,7 @@ func (s *SnapshotStore) LoadChunk(height uint64, format uint32, chunk uint32) ([
defer s.RUnlock()
for _, snapshot := range s.metadata {
if snapshot.Height == height && snapshot.Format == format {
bz, err := ioutil.ReadFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", height)))
bz, err := os.ReadFile(filepath.Join(s.dir, fmt.Sprintf("%v.json", height)))
if err != nil {
return nil, err
}
Expand Down
Loading