Files
mev-beta/test/integration/test_setup.go
2025-09-16 11:05:47 -05:00

135 lines
3.1 KiB
Go

package integration
import (
"context"
"fmt"
"log"
"os/exec"
"runtime"
"testing"
"time"
"github.com/ethereum/go-ethereum/ethclient"
)
// setupForkedArbitrum sets up a forked Arbitrum test environment using anvil
func setupForkedArbitrum(t testing.TB) (*ethclient.Client, func()) {
// Check if anvil is available
if _, err := exec.LookPath("anvil"); err != nil {
t.Skip("anvil not found in PATH - install Foundry to run fork tests")
}
// Start anvil with Arbitrum fork
arbitrumRPC := "https://arb1.arbitrum.io/rpc"
port := "8545"
cmd := exec.Command("anvil",
"--fork-url", arbitrumRPC,
"--port", port,
"--gas-limit", "30000000",
"--gas-price", "10000000000", // 10 gwei
"--block-time", "1", // 1 second blocks
"--accounts", "10", // 10 test accounts
"--balance", "1000", // 1000 ETH per account
)
// Start anvil in background
if err := cmd.Start(); err != nil {
t.Fatalf("Failed to start anvil: %v", err)
}
// Wait for anvil to be ready
time.Sleep(3 * time.Second)
// Connect to the forked network
client, err := ethclient.Dial(fmt.Sprintf("http://localhost:%s", port))
if err != nil {
cmd.Process.Kill()
t.Fatalf("Failed to connect to forked Arbitrum: %v", err)
}
// Verify connection by getting chain ID
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
chainID, err := client.ChainID(ctx)
if err != nil {
cmd.Process.Kill()
t.Fatalf("Failed to get chain ID: %v", err)
}
if chainID.Uint64() != 42161 {
t.Logf("Warning: Expected Arbitrum chain ID 42161, got %d", chainID.Uint64())
}
// Return cleanup function
cleanup := func() {
client.Close()
if cmd.Process != nil {
cmd.Process.Kill()
cmd.Wait()
}
}
return client, cleanup
}
// getMemStats returns current memory statistics
func getMemStats() runtime.MemStats {
var m runtime.MemStats
runtime.ReadMemStats(&m)
return m
}
// logMemoryUsage logs current memory usage for debugging
func logMemoryUsage(t testing.TB, label string) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
t.Logf("%s - Memory: Alloc=%d KB, TotalAlloc=%d KB, Sys=%d KB, NumGC=%d",
label,
m.Alloc/1024,
m.TotalAlloc/1024,
m.Sys/1024,
m.NumGC,
)
}
// waitForAnvil waits for anvil to be ready and responsive
func waitForAnvil(port string, timeout time.Duration) error {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
client, err := ethclient.Dial(fmt.Sprintf("http://localhost:%s", port))
if err == nil {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
_, err := client.ChainID(ctx)
cancel()
client.Close()
if err == nil {
return nil
}
}
time.Sleep(500 * time.Millisecond)
}
return fmt.Errorf("anvil not ready after %v", timeout)
}
// createTestLogger creates a test logger for debugging
func createTestLogger(t testing.TB) *log.Logger {
return log.New(&testWriter{t: t}, "[TEST] ", log.LstdFlags|log.Lshortfile)
}
// testWriter implements io.Writer for test logging
type testWriter struct {
t testing.TB
}
func (tw *testWriter) Write(p []byte) (n int, err error) {
tw.t.Log(string(p))
return len(p), nil
}