Skip to content

Commit

Permalink
Improve proxy api inspection tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aomerk committed Sep 26, 2023
1 parent ab336d0 commit bff32bd
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 137 deletions.
28 changes: 16 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SWAGGER = $(GOBIN)/swagger
PROTOC_GEN_GO = $(GOBIN)/protoc-gen-go
PROTOC_GEN_GO_GRPC = $(GOBIN)/protoc-gen-go-grpc
GOMERGETYPES = $(GOBIN)/gomergetypes
MOCKGEN = $(GOBIN)/mockgen

PROTOC = ./toolbin/protoc --plugin=protoc-gen-go=$(PROTOC_GEN_GO) --plugin=protoc-gen-go-grpc=$(PROTOC_GEN_GO_GRPC)

Expand All @@ -32,6 +33,8 @@ tools:
@go install github.com/golangci/golangci-lint/cmd/[email protected]
@go install golang.org/x/tools/cmd/[email protected]

@go install github.com/golang/mock/mockgen@5b455625bd2c8ffbcc0de6a0873f864ba3820904

@go install github.com/go-swagger/go-swagger/cmd/[email protected]

@go install google.golang.org/protobuf/cmd/[email protected]
Expand Down Expand Up @@ -67,18 +70,19 @@ protogen: require-tools

.PHONY: mocks
mocks:
mockgen -source ethereum/client.go -destination ethereum/mocks/mock_client.go
mockgen -source feeds/interfaces.go -destination feeds/mocks/mock_feeds.go
mockgen -source ethereum/contract_backend.go -destination ethereum/mocks/mock_ethclient.go
mockgen -source registry/client.go -destination registry/mocks/mock_client.go
mockgen -source registry/version.go -destination registry/mocks/mock_version.go
mockgen -source domain/registry/regmsg/regmsg.go -destination domain/registry/regmsg/mocks/mock_regmsg.go
mockgen -source ipfs/client.go -destination ipfs/mocks/mock_client.go
mockgen -source release/client.go -destination release/mocks/mock_client.go
mockgen -source domain/ethereum.go -destination domain/mocks/mock_ethereum.go
mockgen -source manifest/client.go -destination manifest/mocks/mock_client.go
mockgen -source clients/graphql/client.go -destination clients/mocks/mock_graphql_client.go
mockgen -source utils/ethutils/iterator.go -destination utils/ethutils/mocks/mock_iterator.go
$(MOCKGEN) -source ethereum/client.go -destination ethereum/mocks/mock_client.go
$(MOCKGEN) -source feeds/interfaces.go -destination feeds/mocks/mock_feeds.go
$(MOCKGEN) -source ethereum/contract_backend.go -destination ethereum/mocks/mock_ethclient.go
$(MOCKGEN) -source registry/client.go -destination registry/mocks/mock_client.go
$(MOCKGEN) -source registry/version.go -destination registry/mocks/mock_version.go
$(MOCKGEN) -source domain/registry/regmsg/regmsg.go -destination domain/registry/regmsg/mocks/mock_regmsg.go
$(MOCKGEN) -source ipfs/client.go -destination ipfs/mocks/mock_client.go
$(MOCKGEN) -source release/client.go -destination release/mocks/mock_client.go
$(MOCKGEN) -source domain/ethereum.go -destination domain/mocks/mock_ethereum.go
$(MOCKGEN) -source manifest/client.go -destination manifest/mocks/mock_client.go
$(MOCKGEN) -source clients/graphql/client.go -destination clients/mocks/mock_graphql_client.go
$(MOCKGEN) -source utils/ethutils/iterator.go -destination utils/ethutils/mocks/mock_iterator.go
$(MOCKGEN) -source inspect/proxy_api.go -destination inspect/mocks/mock_proxy_api.go

.PHONY: test
test:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
github.com/kelseyhightower/envconfig v1.4.0
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/showwin/speedtest-go v1.1.5
github.com/sirupsen/logrus v1.8.1
Expand Down Expand Up @@ -195,7 +196,6 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/openzipkin/zipkin-go v0.4.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
Expand Down
67 changes: 67 additions & 0 deletions inspect/mocks/mock_proxy_api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions inspect/offset.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"math/big"
"time"

"github.com/ethereum/go-ethereum/ethclient"
"github.com/montanaflynn/stats"
"golang.org/x/sync/errgroup"
)
Expand All @@ -19,8 +18,8 @@ type offsetStats struct {
}

func calculateOffsetStats(
ctx context.Context, primaryClient *ethclient.Client,
secondaryClient *ethclient.Client,
ctx context.Context, primaryClient,
secondaryClient ProxyAPIClient,
) (offsetStats, error) {
ds, err := collectOffsetData(ctx, primaryClient, secondaryClient)
if err != nil {
Expand All @@ -32,7 +31,7 @@ func calculateOffsetStats(

// collectOffsetData measures how long does it take to receive a recently created block and compares given eth clients.
// The idea is to mimic the behavior of Scanner feed and Bot proxy query.
func collectOffsetData(ctx context.Context, primaryClient *ethclient.Client, secondaryClient *ethclient.Client) (
func collectOffsetData(ctx context.Context, primaryClient, secondaryClient ProxyAPIClient) (
[]float64, error,
) {
maxDuration := time.Second * 20
Expand All @@ -56,6 +55,11 @@ func collectOffsetData(ctx context.Context, primaryClient *ethclient.Client, sec
case <-ctx.Done():
return dataPoints, nil
case <-t.C:
// circuit breaker for easier testing
if len(dataPoints) == 10 {
return dataPoints, nil
}

g, ctx := errgroup.WithContext(ctx)

var (
Expand Down Expand Up @@ -98,7 +102,7 @@ func collectOffsetData(ctx context.Context, primaryClient *ethclient.Client, sec
}
}
}
func measureBlockDelay(ctx context.Context, client *ethclient.Client, blockNum uint64) (int64, error) {
func measureBlockDelay(ctx context.Context, client ProxyAPIClient, blockNum uint64) (int64, error) {
t := time.Millisecond * 200

start := time.Now()
Expand Down
37 changes: 37 additions & 0 deletions inspect/offset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package inspect

import (
"context"
"fmt"
"testing"
"time"

mock_inspect "github.com/forta-network/forta-core-go/inspect/mocks"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

func TestCalculateOffsetStats(t *testing.T) {
// Create a test context with a timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

ctrl := gomock.NewController(t)
primaryClient := mock_inspect.NewMockProxyAPIClient(ctrl)
secondaryClient := mock_inspect.NewMockProxyAPIClient(ctrl)

// Test when everything is successful
primaryClient.EXPECT().BlockNumber(gomock.Any()).Return(uint64(5), nil)
primaryClient.EXPECT().BlockByNumber(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
secondaryClient.EXPECT().BlockByNumber(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
stats, err := calculateOffsetStats(ctx, primaryClient, secondaryClient)
assert.NoError(t, err)
assert.Equal(t, stats, offsetStats{0, 0, 0, 10})

// Test when collectOffsetData returns an error
primaryClient.EXPECT().BlockNumber(gomock.Any()).Return(uint64(0), fmt.Errorf("error"))

stats, err = calculateOffsetStats(ctx, primaryClient, secondaryClient)
assert.Error(t, err)
assert.Equal(t, stats, offsetStats{})
}
48 changes: 22 additions & 26 deletions inspect/proxy_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"context"
"fmt"
"math/big"
"time"

"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/hashicorp/go-multierror"
Expand Down Expand Up @@ -56,6 +56,11 @@ type ProxyAPIInspector struct{}
// compile time check: it should implement the interface
var _ Inspector = &ProxyAPIInspector{}

type ProxyAPIClient interface {
BlockNumber(ctx context.Context) (uint64, error)
BlockByNumber(ctx context.Context, int2 *big.Int) (*types.Block, error)
}

// Name returns the name of the inspector.
func (pai *ProxyAPIInspector) Name() string {
return "proxy-api"
Expand Down Expand Up @@ -125,7 +130,21 @@ func (pai *ProxyAPIInspector) Inspect(ctx context.Context, inspectionCfg Inspect
results.Indicators[IndicatorProxyAPIIsETH2] = ResultFailure
}

stats, err := pai.detectOffset(ctx, inspectionCfg)
scanRPCClient, err := rpc.DialContext(ctx, inspectionCfg.ScanAPIURL)
if err != nil {
resultErr = multierror.Append(resultErr, fmt.Errorf("can't dial json-rpc api %w", err))

results.Indicators[IndicatorProxyAPIAccessible] = ResultFailure
results.Indicators[IndicatorProxyAPIModuleWeb3] = ResultFailure
results.Indicators[IndicatorProxyAPIModuleEth] = ResultFailure
results.Indicators[IndicatorProxyAPIModuleNet] = ResultFailure
results.Indicators[IndicatorProxyAPIHistorySupport] = ResultFailure
results.Indicators[IndicatorProxyAPIChainID] = ResultFailure
}

scanClient := ethclient.NewClient(scanRPCClient)

stats, err := calculateOffsetStats(ctx, proxyClient, scanClient)
if err != nil {
resultErr = multierror.Append(resultErr, fmt.Errorf("can't calculate scan-proxy offset: %w", err))
results.Indicators[IndicatorProxyAPIOffsetScanMean] = ResultUnknown
Expand All @@ -142,29 +161,6 @@ func (pai *ProxyAPIInspector) Inspect(ctx context.Context, inspectionCfg Inspect
return
}

func (pai *ProxyAPIInspector) detectOffset(
ctx context.Context,
inspectionCfg InspectionConfig,
) (os offsetStats, resultErr error) {
proxyCtx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()

proxyRPCClient, err := rpc.DialContext(ctx, inspectionCfg.ProxyAPIURL)
if err != nil {
return offsetStats{}, err
}

proxyClient := ethclient.NewClient(proxyRPCClient)
scanRPCClient, err := rpc.DialContext(ctx, inspectionCfg.ScanAPIURL)
if err != nil {
return offsetStats{}, err
}

scanClient := ethclient.NewClient(scanRPCClient)

return calculateOffsetStats(proxyCtx, scanClient, proxyClient)
}

// checkSupportedModules double-checks the functionality of modules that were declared as supported by
// the node.
func checkSupportedModules(
Expand Down Expand Up @@ -213,7 +209,7 @@ func checkHistorySupport(ctx context.Context, latestBlock uint64, client *ethcli
}

// findOldestSupportedBlock returns the earliest block provided by client
func findOldestSupportedBlock(ctx context.Context, client *ethclient.Client, low, high uint64) uint64 {
func findOldestSupportedBlock(ctx context.Context, client ProxyAPIClient, low, high uint64) uint64 {
memo := make(map[uint64]bool)

// terminating condition, results merged
Expand Down
Loading

0 comments on commit bff32bd

Please sign in to comment.