Commit c500a311 authored by Ethen Pociask's avatar Ethen Pociask

[indexer.client] Random API port assignment for E2E tests

parent bbb3c4e5
...@@ -3,6 +3,7 @@ package api ...@@ -3,6 +3,7 @@ package api
import ( import (
"context" "context"
"fmt" "fmt"
"net"
"net/http" "net/http"
"runtime/debug" "runtime/debug"
"sync" "sync"
...@@ -10,7 +11,6 @@ import ( ...@@ -10,7 +11,6 @@ import (
"github.com/ethereum-optimism/optimism/indexer/api/routes" "github.com/ethereum-optimism/optimism/indexer/api/routes"
"github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-service/httputil"
"github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
...@@ -24,6 +24,7 @@ const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$` ...@@ -24,6 +24,7 @@ const ethereumAddressRegex = `^0x[a-fA-F0-9]{40}$`
// TODO : Structured error responses // TODO : Structured error responses
type API struct { type API struct {
log log.Logger log log.Logger
listener net.Listener
router *chi.Mux router *chi.Mux
serverConfig config.ServerConfig serverConfig config.ServerConfig
metricsConfig config.ServerConfig metricsConfig config.ServerConfig
...@@ -70,8 +71,8 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con ...@@ -70,8 +71,8 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con
return &API{log: logger, router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig} return &API{log: logger, router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig}
} }
// Start ... Starts the API server routines // Run ... Runs the API server routines
func (a *API) Start(ctx context.Context) error { func (a *API) Run(ctx context.Context) error {
var wg sync.WaitGroup var wg sync.WaitGroup
errCh := make(chan error, 2) errCh := make(chan error, 2)
...@@ -113,11 +114,32 @@ func (a *API) Start(ctx context.Context) error { ...@@ -113,11 +114,32 @@ func (a *API) Start(ctx context.Context) error {
return err return err
} }
// Port ... Returns the the port that server is listening on
func (a *API) Port() int {
return a.serverConfig.Port
}
// startServer ... Starts the API server // startServer ... Starts the API server
func (a *API) startServer(ctx context.Context) error { func (a *API) startServer(ctx context.Context) error {
a.log.Info("api server listening...", "port", a.serverConfig.Port) a.log.Info("api server listening...", "port", a.serverConfig.Port)
server := http.Server{Addr: fmt.Sprintf(":%d", a.serverConfig.Port), Handler: a.router} server := http.Server{Addr: fmt.Sprintf(":%d", a.serverConfig.Port), Handler: a.router}
err := httputil.ListenAndServeContext(ctx, &server)
addr := fmt.Sprintf(":%d", a.serverConfig.Port)
listener, err := net.Listen("tcp", addr)
if err != nil {
a.log.Error("Listen:", err)
return err
}
tcpAddr, ok := listener.Addr().(*net.TCPAddr)
if !ok {
return fmt.Errorf("failed to get TCP address from network listener")
}
// Update the port in the config in case the OS chose a different port
// than the one we requested (e.g. port 0)
a.serverConfig.Port = tcpAddr.Port
http.Serve(listener, server.Handler)
if err != nil { if err != nil {
a.log.Error("api server stopped", "err", err) a.log.Error("api server stopped", "err", err)
} else { } else {
......
...@@ -13,6 +13,7 @@ type WithdrawalItem struct { ...@@ -13,6 +13,7 @@ type WithdrawalItem struct {
From string `json:"from"` From string `json:"from"`
To string `json:"to"` To string `json:"to"`
TransactionHash string `json:"transactionHash"` TransactionHash string `json:"transactionHash"`
MessageHash string `json:"messageHash"`
Timestamp uint64 `json:"timestamp"` Timestamp uint64 `json:"timestamp"`
L2BlockHash string `json:"l2BlockHash"` L2BlockHash string `json:"l2BlockHash"`
Amount string `json:"amount"` Amount string `json:"amount"`
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"encoding/json" "encoding/json"
"github.com/ethereum-optimism/optimism/indexer/api" "github.com/ethereum-optimism/optimism/indexer/api"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/api/routes"
"github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -123,8 +123,8 @@ func (c *Client) HealthCheck() error { ...@@ -123,8 +123,8 @@ func (c *Client) HealthCheck() error {
} }
// GetDepositsByAddress ... Gets a deposit response object provided an L1 address and cursor // GetDepositsByAddress ... Gets a deposit response object provided an L1 address and cursor
func (c *Client) GetDepositsByAddress(l1Address common.Address, cursor string) (*database.L1BridgeDepositsResponse, error) { func (c *Client) GetDepositsByAddress(l1Address common.Address, cursor string) (*routes.DepositResponse, error) {
var dResponse *database.L1BridgeDepositsResponse var dResponse *routes.DepositResponse
url := c.cfg.BaseURL + api.DepositsPath + l1Address.String() + urlParams url := c.cfg.BaseURL + api.DepositsPath + l1Address.String() + urlParams
endpoint := fmt.Sprintf(url, cursor, c.cfg.PaginationLimit) endpoint := fmt.Sprintf(url, cursor, c.cfg.PaginationLimit)
...@@ -141,8 +141,8 @@ func (c *Client) GetDepositsByAddress(l1Address common.Address, cursor string) ( ...@@ -141,8 +141,8 @@ func (c *Client) GetDepositsByAddress(l1Address common.Address, cursor string) (
} }
// GetAllDepositsByAddress ... Gets all deposits provided a L1 address // GetAllDepositsByAddress ... Gets all deposits provided a L1 address
func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]database.L1BridgeDepositWithTransactionHashes, error) { func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]routes.DepositItem, error) {
var deposits []database.L1BridgeDepositWithTransactionHashes var deposits []routes.DepositItem
cursor := "" cursor := ""
for { for {
...@@ -151,7 +151,7 @@ func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]database.L ...@@ -151,7 +151,7 @@ func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]database.L
return nil, err return nil, err
} }
deposits = append(deposits, dResponse.Deposits...) deposits = append(deposits, dResponse.Items...)
if !dResponse.HasNextPage { if !dResponse.HasNextPage {
break break
...@@ -165,8 +165,8 @@ func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]database.L ...@@ -165,8 +165,8 @@ func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]database.L
} }
// GetAllWithdrawalsByAddress ... Gets all withdrawals provided a L2 address // GetAllWithdrawalsByAddress ... Gets all withdrawals provided a L2 address
func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]database.L2BridgeWithdrawalWithTransactionHashes, error) { func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]routes.WithdrawalItem, error) {
var withdrawals []database.L2BridgeWithdrawalWithTransactionHashes var withdrawals []routes.WithdrawalItem
cursor := "" cursor := ""
for { for {
...@@ -175,7 +175,7 @@ func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]databas ...@@ -175,7 +175,7 @@ func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]databas
return nil, err return nil, err
} }
withdrawals = append(withdrawals, wResponse.Withdrawals...) withdrawals = append(withdrawals, wResponse.Items...)
if !wResponse.HasNextPage { if !wResponse.HasNextPage {
break break
...@@ -188,8 +188,8 @@ func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]databas ...@@ -188,8 +188,8 @@ func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]databas
} }
// GetWithdrawalsByAddress ... Gets a withdrawal response object provided an L2 address and cursor // GetWithdrawalsByAddress ... Gets a withdrawal response object provided an L2 address and cursor
func (c *Client) GetWithdrawalsByAddress(l2Address common.Address, cursor string) (*database.L2BridgeWithdrawalsResponse, error) { func (c *Client) GetWithdrawalsByAddress(l2Address common.Address, cursor string) (*routes.WithdrawalResponse, error) {
var wResponse *database.L2BridgeWithdrawalsResponse var wResponse *routes.WithdrawalResponse
url := c.cfg.BaseURL + api.WithdrawalsPath + l2Address.String() + urlParams url := c.cfg.BaseURL + api.WithdrawalsPath + l2Address.String() + urlParams
endpoint := fmt.Sprintf(url, cursor, c.cfg.PaginationLimit) endpoint := fmt.Sprintf(url, cursor, c.cfg.PaginationLimit)
......
...@@ -67,7 +67,7 @@ func runApi(ctx *cli.Context) error { ...@@ -67,7 +67,7 @@ func runApi(ctx *cli.Context) error {
defer db.Close() defer db.Close()
api := api.NewApi(log, db.BridgeTransfers, cfg.HTTPServer, cfg.MetricsServer) api := api.NewApi(log, db.BridgeTransfers, cfg.HTTPServer, cfg.MetricsServer)
return api.Start(ctx.Context) return api.Run(ctx.Context)
} }
func runMigrations(ctx *cli.Context) error { func runMigrations(ctx *cli.Context) error {
......
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
) )
func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) { func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l1CrossDomainMessenger, err := bindings.NewL1CrossDomainMessenger(testSuite.OpCfg.L1Deployments.L1CrossDomainMessengerProxy, testSuite.L1Client) l1CrossDomainMessenger, err := bindings.NewL1CrossDomainMessenger(testSuite.OpCfg.L1Deployments.L1CrossDomainMessengerProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -93,7 +93,7 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) { ...@@ -93,7 +93,7 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) {
} }
func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
) )
func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) { func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -70,7 +70,7 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) { ...@@ -70,7 +70,7 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) {
} }
func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -166,7 +166,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { ...@@ -166,7 +166,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
} }
func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) { func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l2ToL1MessagePasser, err := bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client) l2ToL1MessagePasser, err := bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
) )
func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client) l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -92,7 +92,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { ...@@ -92,7 +92,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
} }
func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -151,7 +151,7 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { ...@@ -151,7 +151,7 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) {
} }
func TestE2EBridgeTransfersCursoredDeposits(t *testing.T) { func TestE2EBridgeTransfersCursoredDeposits(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client) l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -220,7 +220,7 @@ func TestE2EBridgeTransfersCursoredDeposits(t *testing.T) { ...@@ -220,7 +220,7 @@ func TestE2EBridgeTransfersCursoredDeposits(t *testing.T) {
} }
func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -305,8 +305,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -305,8 +305,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
} }
func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
l2ToL1MessagePasser, err := bindings.NewOptimismPortal(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client) l2ToL1MessagePasser, err := bindings.NewOptimismPortal(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
...@@ -379,7 +378,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { ...@@ -379,7 +378,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) {
} }
func TestE2EBridgeTransfersCursoredWithdrawals(t *testing.T) { func TestE2EBridgeTransfersCursoredWithdrawals(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, testSuite.L2Client) l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, testSuite.L2Client)
require.NoError(t, err) require.NoError(t, err)
...@@ -449,24 +448,21 @@ func TestE2EBridgeTransfersCursoredWithdrawals(t *testing.T) { ...@@ -449,24 +448,21 @@ func TestE2EBridgeTransfersCursoredWithdrawals(t *testing.T) {
} }
func Test_ClientGetWithdrawals(t *testing.T) { func Test_ClientGetWithdrawals(t *testing.T) {
testSuite := createAPITestSuite(t) testSuite := createE2ETestSuite(t)
// (1) Generate contract bindings for the L1 and L2 standard bridges
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
l2ToL1MessagePasser, err := bindings.NewOptimismPortal(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client) l2ToL1MessagePasser, err := bindings.NewOptimismPortal(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
require.NoError(t, err) require.NoError(t, err)
// Use alice and bob to generate two deposits / withdrawals // (2) Create test actors that will deposit and withdraw using the standard bridge
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
bobAddr := testSuite.OpCfg.Secrets.Addresses().Bob bobAddr := testSuite.OpCfg.Secrets.Addresses().Bob
// Actor represents a user that will deposit and withdraw
type actor struct { type actor struct {
addr common.Address addr common.Address
priv *ecdsa.PrivateKey priv *ecdsa.PrivateKey
depositHash common.Hash
withdrawalHash common.Hash
} }
actors := []actor{ actors := []actor{
...@@ -480,13 +476,13 @@ func Test_ClientGetWithdrawals(t *testing.T) { ...@@ -480,13 +476,13 @@ func Test_ClientGetWithdrawals(t *testing.T) {
}, },
} }
// (1) Iterate over each actor and deposit / withdraw // (3) Iterate over each actor and deposit / withdraw
for _, actor := range actors { for _, actor := range actors {
l2Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L2ChainIDBig()) l2Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether) l2Opts.Value = big.NewInt(params.Ether)
// (1.a) Deposit user funds into L2 via OptimismPortal contract // (3.a) Deposit user funds into L2 via OptimismPortal contract
l1Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L1ChainIDBig()) l1Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
l1Opts.Value = l2Opts.Value l1Opts.Value = l2Opts.Value
...@@ -495,41 +491,28 @@ func Test_ClientGetWithdrawals(t *testing.T) { ...@@ -495,41 +491,28 @@ func Test_ClientGetWithdrawals(t *testing.T) {
_, err = wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) _, err = wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err) require.NoError(t, err)
// (1.b) Initiate withdrawal transaction via L2ToL1MessagePasser contract // (3.b) Initiate withdrawal transaction via L2ToL1MessagePasser contract
l2ToL1MessagePasserWithdrawTx, err := l2ToL1MessagePasser.Receive(l2Opts) l2ToL1MessagePasserWithdrawTx, err := l2ToL1MessagePasser.Receive(l2Opts)
require.NoError(t, err) require.NoError(t, err)
l2ToL1WithdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, l2ToL1MessagePasserWithdrawTx.Hash()) l2ToL1WithdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, l2ToL1MessagePasserWithdrawTx.Hash())
require.NoError(t, err) require.NoError(t, err)
// (1.c) wait for indexer processor to catchup with the L2 block containing the withdrawal tx // (3.c) wait for indexer processor to catchup with the L2 block containing the withdrawal tx
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.BridgeProcessor.LatestL2Header l2Header := testSuite.Indexer.BridgeProcessor.LatestL2Header
return l2Header != nil && l2Header.Number.Uint64() >= l2ToL1WithdrawReceipt.BlockNumber.Uint64(), nil return l2Header != nil && l2Header.Number.Uint64() >= l2ToL1WithdrawReceipt.BlockNumber.Uint64(), nil
})) }))
actor.withdrawalHash = l2ToL1MessagePasserWithdrawTx.Hash() // (3.d) Ensure that withdrawal and deposit txs are retrievable via API
} deposits, err := testSuite.Client.GetAllDepositsByAddress(actor.addr)
require.NoError(t, err)
// (2) Test that Alice's withdrawal and deposit txs can be retrieved via API client require.Len(t, deposits, 1)
aliceWithdrawals, err := testSuite.Client.GetAllWithdrawalsByAddress(aliceAddr) require.Equal(t, depositTx.Hash().String(), deposits[0].L1TxHash)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1)
require.Equal(t, actors[0].withdrawalHash, aliceWithdrawals[0].L2TransactionHash[0])
aliceDeposits, err := testSuite.Client.GetAllDepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceDeposits, 1)
require.Equal(t, actors[0].depositHash, aliceDeposits[0].L1TransactionHash[0])
// (3) Test that Bob's withdrawal and deposit txs can be retrieved via API client
bobWithdrawals, err := testSuite.Client.GetAllWithdrawalsByAddress(bobAddr)
require.NoError(t, err)
require.Len(t, bobWithdrawals, 1)
require.Equal(t, actors[1].withdrawalHash, bobWithdrawals[0].L2TransactionHash[0])
bobDeposits, err := testSuite.Client.GetAllDepositsByAddress(bobAddr) withdrawals, err := testSuite.Client.GetAllWithdrawalsByAddress(actor.addr)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, actors[0].depositHash, aliceDeposits[0].L1TransactionHash[0]) require.Len(t, withdrawals, 1)
require.Equal(t, actors[1].depositHash, bobDeposits[0].L2TransactionHash[0]) require.Equal(t, l2ToL1MessagePasserWithdrawTx.Hash().String(), withdrawals[0].TransactionHash)
}
} }
...@@ -19,7 +19,7 @@ import ( ...@@ -19,7 +19,7 @@ import (
) )
func TestE2EETL(t *testing.T) { func TestE2EETL(t *testing.T) {
testSuite := createIndexerTestSuite(t) testSuite := createE2ETestSuite(t)
l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client) l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -23,6 +23,11 @@ import ( ...@@ -23,6 +23,11 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
/*
NOTE - Most of the current tests fetch chain data via direct database queries. These could all
be transitioned to use the API client instead to better simulate/validate real-world usage.
*/
type E2ETestSuite struct { type E2ETestSuite struct {
t *testing.T t *testing.T
...@@ -43,15 +48,8 @@ type E2ETestSuite struct { ...@@ -43,15 +48,8 @@ type E2ETestSuite struct {
L2Client *ethclient.Client L2Client *ethclient.Client
} }
func createIndexerTestSuite(t *testing.T) E2ETestSuite { // createE2ETestSuite ... Create a new E2E test suite
return buildE2ETestSuite(t, false) func createE2ETestSuite(t *testing.T) E2ETestSuite {
}
func createAPITestSuite(t *testing.T) E2ETestSuite {
return buildE2ETestSuite(t, true)
}
func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite {
dbUser := os.Getenv("DB_USER") dbUser := os.Getenv("DB_USER")
dbName := setupTestDatabase(t) dbName := setupTestDatabase(t)
...@@ -66,15 +64,9 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite { ...@@ -66,15 +64,9 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite {
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { opSys.Close() }) t.Cleanup(func() { opSys.Close() })
if !withAPI { // E2E tests can run on the order of magnitude of minutes. Once
// E2E tests can run on the order of magnitude of minutes. Once // the system is running, mark this test for Parallel execution
// the system is running, mark this test for Parallel execution t.Parallel()
// E2E API tests will not be marked for Parallel execution as they
// will try consuming the same port and fail. This can be fixed if a
// unique sport is dynamically allocated for each test.
t.Parallel()
}
// Indexer Configuration and Start // Indexer Configuration and Start
indexerCfg := config.Config{ indexerCfg := config.Config{
...@@ -114,9 +106,9 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite { ...@@ -114,9 +106,9 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite {
indexer, err := indexer.NewIndexer(indexerLog, db, indexerCfg.Chain, indexerCfg.RPCs, indexerCfg.HTTPServer, indexerCfg.MetricsServer) indexer, err := indexer.NewIndexer(indexerLog, db, indexerCfg.Chain, indexerCfg.RPCs, indexerCfg.HTTPServer, indexerCfg.MetricsServer)
require.NoError(t, err) require.NoError(t, err)
appCtx, appStop := context.WithCancel(context.Background()) indexerCtx, indexerStop := context.WithCancel(context.Background())
go func() { go func() {
err := indexer.Run(appCtx) err := indexer.Run(indexerCtx)
if err != nil { // panicking here ensures that the test will exit if err != nil { // panicking here ensures that the test will exit
// during service failure. Using t.Fail() wouldn't be caught // during service failure. Using t.Fail() wouldn't be caught
// until all awaiting routines finish which would never happen. // until all awaiting routines finish which would never happen.
...@@ -124,45 +116,45 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite { ...@@ -124,45 +116,45 @@ func buildE2ETestSuite(t *testing.T, withAPI bool) E2ETestSuite {
} }
}() }()
var indexerAPI *api.API apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api")
var indexerClient *client.Client
if withAPI { apiCfg := config.ServerConfig{
apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api") Host: "127.0.0.1",
Port: 0,
}
apiCfg := config.ServerConfig{ mCfg := config.ServerConfig{
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 4321, Port: 0,
} }
mCfg := config.ServerConfig{ api := api.NewApi(apiLog, db.BridgeTransfers, apiCfg, mCfg)
Host: "127.0.0.1", apiCtx, apiStop := context.WithCancel(context.Background())
Port: 0, go func() {
err := api.Run(apiCtx)
if err != nil {
panic(err)
} }
}()
indexerAPI = api.NewApi(apiLog, db.BridgeTransfers, apiCfg, mCfg)
go func() {
err := indexerAPI.Start(appCtx)
if err != nil {
panic(err)
}
}()
indexerClient, err = client.NewClient(&client.Config{
PaginationLimit: 100,
BaseURL: fmt.Sprintf("http://%s:%d", indexerCfg.HTTPServer.Host, indexerCfg.HTTPServer.Port),
})
require.NoError(t, err)
}
t.Cleanup(func() { t.Cleanup(func() {
appStop() apiStop()
indexerStop()
}) })
// Wait for the API to start listening
time.Sleep(1 * time.Second)
client, err := client.NewClient(&client.Config{
PaginationLimit: 100,
BaseURL: fmt.Sprintf("http://%s:%d", apiCfg.Host, api.Port()),
})
require.NoError(t, err)
return E2ETestSuite{ return E2ETestSuite{
t: t, t: t,
API: indexerAPI, Client: client,
Client: indexerClient,
DB: db, DB: db,
Indexer: indexer, Indexer: indexer,
OpCfg: &opCfg, OpCfg: &opCfg,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment