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

Eth2 showcase with log poller #11214

Merged
merged 16 commits into from
Nov 13, 2023
Merged
66 changes: 0 additions & 66 deletions .github/log_poller_on_demand.yml

This file was deleted.

87 changes: 87 additions & 0 deletions .github/workflows/on-demand-log-poller.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: On Demand Log Poller Consistency Test
on:
workflow_dispatch:
inputs:
contracts:
description: Number of test contracts
default: "2"
required: true
eventsPerTx:
description: Number of events to emit per transaction
default: "10"
required: true
useFinalityTag:
description: Use finality tag
default: "false"
required: true
loadDuration:
description: Load duration (e.g. 10s, 10m, 1h)
default: "10m"
required: true
chainlinkImage:
description: Chainlink image to use
default: "public.ecr.aws/chainlink/chainlink"
required: true
chainlinkVersion:
description: Chainlink version to use
default: "2.7.0-beta0"
required: true
selectedNetworks:
type: choice
options:
- "SIMULATED"
- "SEPOLIA"
- "MUMBAI"
fundingPrivateKey:
description: Private funding key (Skip for Simulated)
required: true
type: string
wsURL:
description: WS URL for the network (Skip for Simulated)
required: true
type: string
httpURL:
description: HTTP URL for the network (Skip for Simulated)
required: true
type: string

jobs:
test:
env:
CONTRACTS: ${{ inputs.contracts }}
EVENTS_PER_TX: ${{ inputs.eventsPerTx }}
LOAD_DURATION: ${{ inputs.loadDuration }}
USE_FINALITY_TAG: ${{ inputs.useFinalityTag }}
CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }}
CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }}
SELECTED_NETWORKS: ${{ inputs.selectedNetworks }}
REF_NAME: ${{ github.head_ref || github.ref_name }}
runs-on: ubuntu20.04-8cores-32GB
steps:
- name: Get Inputs
run: |
EVM_URLS=$(jq -r '.inputs.wsURL' $GITHUB_EVENT_PATH)
EVM_HTTP_URLS=$(jq -r '.inputs.httpURL' $GITHUB_EVENT_PATH)
EVM_KEYS=$(jq -r '.inputs.fundingPrivateKey' $GITHUB_EVENT_PATH)

echo ::add-mask::$EVM_URLS
echo ::add-mask::$EVM_HTTP_URLS
echo ::add-mask::$EVM_KEYS

echo EVM_URLS=$EVM_URLS >> $GITHUB_ENV
echo EVM_HTTP_URLS=$EVM_HTTP_URLS >> $GITHUB_ENV
echo EVM_KEYS=$EVM_KEYS >> $GITHUB_ENV
- name: Checkout the repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ env.REF_NAME }}
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version-file: "integration-tests/go.mod"
cache: true
- name: Run tests
run: |
cd integration-tests
go mod download
go test -v -timeout 5h -v -count=1 -run ^TestLogPollerFromEnv$ ./reorg/log_poller_maybe_reorg_test.go
64 changes: 49 additions & 15 deletions integration-tests/docker/test_env/test_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ type CLClusterTestEnv struct {
LogWatch *logwatch.LogWatch

/* components */
ClCluster *ClCluster
Geth *test_env.Geth // for tests using --dev networks
PrivateChain []test_env.PrivateChain // for tests using non-dev networks
MockAdapter *test_env.Killgrave
EVMClient blockchain.EVMClient
ContractDeployer contracts.ContractDeployer
ContractLoader contracts.ContractLoader
l zerolog.Logger
t *testing.T
ClCluster *ClCluster
PrivateChain []test_env.PrivateChain // for tests using non-dev networks -- unify it with new approach
MockAdapter *test_env.Killgrave
EVMClient blockchain.EVMClient
ContractDeployer contracts.ContractDeployer
ContractLoader contracts.ContractLoader
RpcProvider test_env.RpcProvider
PrivateEthereumConfig *test_env.EthereumNetworkConfig // new approach to private chains, supporting eth1 and eth2
l zerolog.Logger
t *testing.T
}

func NewTestEnv() (*CLClusterTestEnv, error) {
Expand All @@ -59,27 +60,24 @@ func NewTestEnv() (*CLClusterTestEnv, error) {
}
n := []string{network.Name}
return &CLClusterTestEnv{
Geth: test_env.NewGeth(n),
MockAdapter: test_env.NewKillgrave(n, ""),
Network: network,
l: log.Logger,
}, nil
}

// WithTestEnvConfig sets the test environment cfg.
// Sets up the Geth and MockAdapter containers with the provided cfg.
// Sets up private ethereum chain and MockAdapter containers with the provided cfg.
func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTestEnv {
te.Cfg = cfg
n := []string{te.Network.Name}
te.Geth = test_env.NewGeth(n, test_env.WithContainerName(te.Cfg.Geth.ContainerName))
te.MockAdapter = test_env.NewKillgrave(n, te.Cfg.MockAdapter.ImpostersPath, test_env.WithContainerName(te.Cfg.MockAdapter.ContainerName))
return te
}

func (te *CLClusterTestEnv) WithTestLogger(t *testing.T) *CLClusterTestEnv {
te.t = t
te.l = logging.GetTestLogger(t)
te.Geth.WithTestLogger(t)
te.MockAdapter.WithTestLogger(t)
return te
}
Expand Down Expand Up @@ -128,8 +126,27 @@ func (te *CLClusterTestEnv) StartPrivateChain() error {
return nil
}

func (te *CLClusterTestEnv) StartGeth() (blockchain.EVMNetwork, test_env.InternalDockerUrls, error) {
return te.Geth.StartContainer()
func (te *CLClusterTestEnv) StartEthereumNetwork(b *test_env.EthereumNetworkBuilder) (blockchain.EVMNetwork, test_env.RpcProvider, test_env.EthereumNetworkConfig, error) {
// if environment is being restored from a previous state, use the existing config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this provision? is there any use case for it already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet, but I didn't want to break what we had there, because it allowed to re-use existing configuration (even if we never did it)

// this might fail terribly if temporary folders with chain data on the host machine were removed
if te.Cfg != nil && te.Cfg.PrivateEthereumConfig != nil {
b.WithExistingConfig(*te.Cfg.PrivateEthereumConfig)
}

// use Docker Network created or loaded so that all containers are on the same network
b.UsingDockerNetworks([]string{te.Network.Name})
err := b.Build()
if err != nil {
return blockchain.EVMNetwork{}, test_env.RpcProvider{}, test_env.EthereumNetworkConfig{}, err
}

n, rpc, config, err := b.Start()

if err != nil {
return blockchain.EVMNetwork{}, test_env.RpcProvider{}, test_env.EthereumNetworkConfig{}, err
}

return n, rpc, config, nil
}

func (te *CLClusterTestEnv) StartMockAdapter() error {
Expand Down Expand Up @@ -187,6 +204,8 @@ func (te *CLClusterTestEnv) Cleanup() error {
return errors.New("chainlink nodes are nil, unable cleanup chainlink nodes")
}

te.logWhetherAllContainersAreRunning()

// TODO: This is an imperfect and temporary solution, see TT-590 for a more sustainable solution
// Collect logs if the test fails, or if we just want them
if te.t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" {
Expand Down Expand Up @@ -216,6 +235,21 @@ func (te *CLClusterTestEnv) Cleanup() error {
return nil
}

func (te *CLClusterTestEnv) logWhetherAllContainersAreRunning() {
for _, node := range te.ClCluster.Nodes {
isCLRunning := node.Container.IsRunning()
isDBRunning := node.PostgresDb.Container.IsRunning()

if !isCLRunning {
te.l.Warn().Str("Node", node.ContainerName).Msg("Chainlink node was not running, when test ended")
}

if !isDBRunning {
te.l.Warn().Str("Node", node.ContainerName).Msg("Postgres DB is not running, when test ended")
}
}
}

// collectTestLogs collects the logs from all the Chainlink nodes in the test environment and writes them to local files
func (te *CLClusterTestEnv) collectTestLogs() error {
te.l.Info().Msg("Collecting test logs")
Expand Down
62 changes: 46 additions & 16 deletions integration-tests/docker/test_env/test_env_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const (
)

type CLTestEnvBuilder struct {
hasLogWatch bool
hasGeth bool
hasLogWatch bool
// hasGeth bool
hasKillgrave bool
hasForwarders bool
clNodeConfig *chainlink.Config
Expand All @@ -49,6 +49,7 @@ type CLTestEnvBuilder struct {
cleanUpCustomFn func()
chainOptionsFn []ChainOption
evmClientNetworkOption []EVMClientNetworkOption
ethereumNetworkBuilder *test_env.EthereumNetworkBuilder

/* funding */
ETHFunds *big.Float
Expand Down Expand Up @@ -118,8 +119,23 @@ func (b *CLTestEnvBuilder) WithFunding(eth *big.Float) *CLTestEnvBuilder {
return b
}

// deprecated
// left only for backward compatibility
func (b *CLTestEnvBuilder) WithGeth() *CLTestEnvBuilder {
b.hasGeth = true
ethBuilder := test_env.NewEthereumNetworkBuilder(b.t)
err := ethBuilder.
WithConsensusType(test_env.ConsensusType_PoW).
WithExecutionLayer(test_env.ExecutionLayer_Geth).
Build()

if err != nil {
panic(err)
}
return b
}

func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(enb test_env.EthereumNetworkBuilder) *CLTestEnvBuilder {
b.ethereumNetworkBuilder = &enb
return b
}

Expand Down Expand Up @@ -191,13 +207,6 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
return nil, err
}
}
b.l.Info().
Bool("hasGeth", b.hasGeth).
Bool("hasKillgrave", b.hasKillgrave).
Int("clNodesCount", b.clNodesCount).
Strs("customNodeCsaKeys", b.customNodeCsaKeys).
Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys).
Msg("Building CL cluster test environment..")

var err error
if b.t != nil {
Expand Down Expand Up @@ -260,12 +269,18 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
return b.te, nil
}
networkConfig := networks.MustGetSelectedNetworksFromEnv()[0]
var internalDockerUrls test_env.InternalDockerUrls
if b.hasGeth && networkConfig.Simulated {
networkConfig, internalDockerUrls, err = b.te.StartGeth()
var rpcProvider test_env.RpcProvider
if b.ethereumNetworkBuilder != nil && networkConfig.Simulated {
// TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point
// in general it seems we have no methods for saving config to file and we only load it from file
// but I don't know how that config file is to be created or whether anyone ever done that
var enCfg test_env.EthereumNetworkConfig
networkConfig, rpcProvider, enCfg, err = b.te.StartEthereumNetwork(b.ethereumNetworkBuilder)
if err != nil {
return nil, err
}
b.te.RpcProvider = rpcProvider
b.te.PrivateEthereumConfig = &enCfg
}

if !b.isNonEVM {
Expand Down Expand Up @@ -311,8 +326,8 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
var httpUrls []string
var wsUrls []string
if networkConfig.Simulated {
httpUrls = []string{internalDockerUrls.HttpUrl}
wsUrls = []string{internalDockerUrls.WsUrl}
httpUrls = rpcProvider.PrivateHttpUrls()
wsUrls = rpcProvider.PrivateWsUrsl()
Tofel marked this conversation as resolved.
Show resolved Hide resolved
} else {
httpUrls = networkConfig.HTTPURLs
wsUrls = networkConfig.URLs
Expand Down Expand Up @@ -341,13 +356,28 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) {
b.defaultNodeCsaKeys = nodeCsaKeys
}

if b.hasGeth && b.clNodesCount > 0 && b.ETHFunds != nil {
if b.ethereumNetworkBuilder != nil && b.clNodesCount > 0 && b.ETHFunds != nil {
b.te.ParallelTransactions(true)
defer b.te.ParallelTransactions(false)
if err := b.te.FundChainlinkNodes(b.ETHFunds); err != nil {
return nil, err
}
}

var enDesc string
if b.te.PrivateEthereumConfig != nil {
enDesc = b.te.PrivateEthereumConfig.Describe()
Tofel marked this conversation as resolved.
Show resolved Hide resolved
} else {
enDesc = "none"
}

b.l.Info().
Str("privateEthereumNetwork", enDesc).
Bool("hasKillgrave", b.hasKillgrave).
Int("clNodesCount", b.clNodesCount).
Strs("customNodeCsaKeys", b.customNodeCsaKeys).
Strs("defaultNodeCsaKeys", b.defaultNodeCsaKeys).
Msg("Building CL cluster test environment..")

return b.te, nil
}
Loading
Loading