Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
Rebasing to Optimism Monorepo w/ Parallelized E2E Testing (#163)
Browse files Browse the repository at this point in the history
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
Ethen and dependabot[bot] authored Oct 10, 2023
1 parent 57c02f7 commit 5f6db5f
Show file tree
Hide file tree
Showing 37 changed files with 1,254 additions and 1,125 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/hygeine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21

- name: Install mockgen
run: go install github.com/golang/mock/[email protected]
Expand Down
21 changes: 16 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21

- name: Build App
run: make build-app
Expand All @@ -31,12 +31,16 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21

- name: Install project dependencies
run: |
go mod download
- name: Run Unit Tests
id: unit
run: |
go test -coverprofile=coverage.out ./internal/... >> out.txt
go test -v -coverprofile=coverage.out ./internal/...
# - name: Generate Coverage
# run: |
Expand Down Expand Up @@ -69,8 +73,15 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21

- name: Install foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Setup devnet resources
id: devnet
run: |
make devnet-allocs
- name: Run E2E Integration Tests
run: make e2e-test

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ config.env
/.vscode/
/.idea
genesis.json
alert-routing.yaml
alert-routing.yaml
.devnet
packages/contracts-bedrock/deploy-config/devnetL1.json
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test:

.PHONY: test-e2e
e2e-test:
@ go test ./e2e/... -timeout $(TEST_LIMIT)
@ go test ./e2e/... -timeout $(TEST_LIMIT) -deploy-config ../.devnet/devnetL1.json -parallel=4 -v

.PHONY: lint
lint:
Expand Down Expand Up @@ -65,3 +65,7 @@ metrics-docs: build-app
@echo "$(GREEN) Generating metric documentation...$(COLOR_END)"
@./bin/pessimism doc metrics


devnet-allocs:
@echo "$(GREEN) Generating devnet allocs...$(COLOR_END)"
@./scripts/devnet-allocs.sh
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ Unit tests can run using the following project level command(s):

Integration tests are written that leverage the existing [op-e2e](https://github.com/ethereum-optimism/optimism/tree/develop/op-e2e) testing framework for spinning up pieces of the bedrock system. Additionally, the [httptest](https://pkg.go.dev/net/http/httptest) library is used to mock downstream alerting services (e.g. Slack's webhook API). These tests live in the project's `/e2e` directory.

Running integration tests requires generating devnet allocation files for compatibility with the Optimism monorepo. The following `scripts/devnet_allocs.sh` can be run to do this generation. If successful, a new `.devnet` directory will be created in the project's root directory.

Integration tests can run using the following project level command(s):

* Using Make: `make e2e-test`
Expand Down
5 changes: 4 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,14 @@ func RunPessimism(_ *cli.Context) error {
return err
}

if err := pessimism.BootStrap(sessions); err != nil {
ids, err := pessimism.BootStrap(sessions)
if err != nil {
logger.Fatal("Error bootstrapping application state", zap.Error(err))
return err
}

logger.Info("Received bootstrapped session UUIDs", zap.Any(logging.SUUIDKey, ids))

logger.Debug("Application state successfully bootstrapped")
}

Expand Down
30 changes: 0 additions & 30 deletions e2e/alert-routing-cfg.yaml

This file was deleted.

152 changes: 152 additions & 0 deletions e2e/alerting_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package e2e_test

import (
"context"
"math/big"
"testing"
"time"

"github.com/base-org/pessimism/e2e"
"github.com/base-org/pessimism/internal/api/models"
"github.com/base-org/pessimism/internal/core"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/assert"
)

// TestMultiDirectiveRouting ... Tests the E2E flow of a contract event heuristic with high priority alerts all
// necessary destinations
func TestMultiDirectiveRouting(t *testing.T) {

ts := e2e.CreateSysTestSuite(t)

updateSig := "ConfigUpdate(uint256,uint8,bytes)"
alertMsg := "System config gas config updated"

_, err := ts.App.BootStrap([]*models.SessionRequestParams{{
Network: core.Layer1.String(),
PType: core.Live.String(),
HeuristicType: core.ContractEvent.String(),
StartHeight: nil,
EndHeight: nil,
AlertingParams: &core.AlertPolicy{
Msg: alertMsg,
Sev: core.HIGH.String(),
},
SessionParams: map[string]interface{}{
"address": ts.Cfg.L1Deployments.SystemConfigProxy.String(),
"args": []interface{}{updateSig},
},
}})

assert.NoError(t, err, "Error bootstrapping heuristic session")

sysCfg, err := bindings.NewSystemConfig(ts.Cfg.L1Deployments.SystemConfigProxy, ts.L1Client)
assert.NoError(t, err, "Error getting system config")

opts, err := bind.NewKeyedTransactorWithChainID(ts.Cfg.Secrets.SysCfgOwner, ts.Cfg.L1ChainIDBig())
assert.NoError(t, err, "Error getting system config owner pk")

overhead := big.NewInt(10000)
scalar := big.NewInt(1)

tx, err := sysCfg.SetGasConfig(opts, overhead, scalar)
assert.NoError(t, err, "Error setting gas config")

txTimeoutDuration := 10 * time.Duration(ts.Cfg.DeployConfig.L1BlockTime) * time.Second
receipt, err := e2e.WaitForTransaction(tx.Hash(), ts.L1Client, txTimeoutDuration)

assert.NoError(t, err, "Error waiting for transaction")
assert.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")

time.Sleep(3 * time.Second)
slackPosts := ts.TestSlackSvr.SlackAlerts()
pdPosts := ts.TestPagerDutyServer.PagerDutyAlerts()

// Expect 2 alerts to each destination as alert-routing-cfg.yaml has two slack and two pagerduty destinations
assert.Equal(t, 2, len(slackPosts), "Incorrect Number of slack posts sent")
assert.Equal(t, 2, len(pdPosts), "Incorrect Number of pagerduty posts sent")
assert.Contains(t, slackPosts[0].Text, "contract_event", "System contract event alert was not sent")
assert.Contains(t, slackPosts[1].Text, "contract_event", "System contract event alert was not sent")
assert.Contains(t, pdPosts[0].Payload.Summary, "contract_event", "System contract event alert was not sent")
assert.Contains(t, pdPosts[1].Payload.Summary, "contract_event", "System contract event alert was not sent")
}

// TestCoolDown ... Tests the E2E flow of a single
// balance enforcement heuristic session on L2 network with a cooldown.
func TestCoolDown(t *testing.T) {

ts := e2e.CreateL2TestSuite(t)
defer ts.Close()

alice := ts.L2Cfg.Secrets.Addresses().Alice
bob := ts.L2Cfg.Secrets.Addresses().Bob

alertMsg := "one baby to another says:"
// Deploy a balance enforcement heuristic session for Alice using a cooldown.
_, err := ts.App.BootStrap([]*models.SessionRequestParams{{
Network: core.Layer2.String(),
PType: core.Live.String(),
HeuristicType: core.BalanceEnforcement.String(),
StartHeight: nil,
EndHeight: nil,
AlertingParams: &core.AlertPolicy{
// Set a cooldown to one minute.
CoolDown: 60,
Sev: core.LOW.String(),
Msg: alertMsg,
},
SessionParams: map[string]interface{}{
"address": alice.String(),
"lower": 3, // i.e. alert if balance is less than 3 ETH
},
}})

assert.NoError(t, err, "Failed to bootstrap balance enforcement heuristic session")

// Get Alice's balance.
aliceAmt, err := ts.L2Geth.L2Client.BalanceAt(context.Background(), alice, nil)
assert.NoError(t, err, "Failed to get Alice's balance")

// Determine the gas cost of the transaction.
gasAmt := 1_000_001
bigAmt := big.NewInt(1_000_001)
gasPrice := big.NewInt(int64(ts.L2Cfg.DeployConfig.L2GenesisBlockGasLimit))

gasCost := gasPrice.Mul(gasPrice, bigAmt)

signer := types.LatestSigner(ts.L2Geth.L2ChainConfig)

// Create a transaction from Alice to Bob that will drain almost all of Alice's ETH.
drainAliceTx := types.MustSignNewTx(ts.L2Cfg.Secrets.Alice, signer, &types.DynamicFeeTx{
ChainID: big.NewInt(int64(ts.L2Cfg.DeployConfig.L2ChainID)),
Nonce: 0,
GasTipCap: big.NewInt(100),
GasFeeCap: big.NewInt(100000),
Gas: uint64(gasAmt),
To: &bob,
// Subtract the gas cost from the amount sent to Bob.
Value: aliceAmt.Sub(aliceAmt, gasCost),
Data: nil,
})

// Send the transaction to drain Alice's account of almost all ETH.
_, err = ts.L2Geth.AddL2Block(context.Background(), drainAliceTx)
assert.NoError(t, err, "Failed to create L2 block with transaction")

// Wait for Pessimism to process the balance change and send a notification to the mocked Slack server.
time.Sleep(2 * time.Second)

// Check that the balance enforcement was triggered using the mocked server cache.
posts := ts.TestSlackSvr.SlackAlerts()

assert.Equal(t, 1, len(posts), "No balance enforcement alert was sent")
assert.Contains(t, posts[0].Text, "balance_enforcement", "Balance enforcement alert was not sent")
assert.Contains(t, posts[0].Text, alertMsg)

// Ensure that no new alerts are sent for provided cooldown period.
time.Sleep(1 * time.Second)
posts = ts.TestSlackSvr.SlackAlerts()
assert.Equal(t, 1, len(posts), "No alerts should be sent after the transaction is sent")
}
Loading

0 comments on commit 5f6db5f

Please sign in to comment.