test(execution): add comprehensive test suite for execution engine
Some checks failed
V2 CI/CD Pipeline / Pre-Flight Checks (push) Has been cancelled
V2 CI/CD Pipeline / Build & Dependencies (push) Has been cancelled
V2 CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
V2 CI/CD Pipeline / Unit Tests (100% Coverage Required) (push) Has been cancelled
V2 CI/CD Pipeline / Integration Tests (push) Has been cancelled
V2 CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
V2 CI/CD Pipeline / Decimal Precision Validation (push) Has been cancelled
V2 CI/CD Pipeline / Modularity Validation (push) Has been cancelled
V2 CI/CD Pipeline / Final Validation Summary (push) Has been cancelled
Some checks failed
V2 CI/CD Pipeline / Pre-Flight Checks (push) Has been cancelled
V2 CI/CD Pipeline / Build & Dependencies (push) Has been cancelled
V2 CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
V2 CI/CD Pipeline / Unit Tests (100% Coverage Required) (push) Has been cancelled
V2 CI/CD Pipeline / Integration Tests (push) Has been cancelled
V2 CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
V2 CI/CD Pipeline / Decimal Precision Validation (push) Has been cancelled
V2 CI/CD Pipeline / Modularity Validation (push) Has been cancelled
V2 CI/CD Pipeline / Final Validation Summary (push) Has been cancelled
Add comprehensive unit tests for all execution engine components: Component Test Coverage: - UniswapV2 encoder: 15 test cases + benchmarks - UniswapV3 encoder: 20 test cases + benchmarks - Curve encoder: 16 test cases + benchmarks - Flashloan manager: 18 test cases + benchmarks - Transaction builder: 15 test cases + benchmarks - Risk manager: 25 test cases + benchmarks - Executor: 20 test cases + benchmarks Test Categories: - Happy path scenarios - Error handling and edge cases - Zero/invalid inputs - Boundary conditions (max amounts, limits) - Concurrent operations (nonce management) - Configuration validation - State management Key Test Features: - Protocol-specific encoding validation - ABI encoding correctness - Gas calculation accuracy - Slippage calculation - Nonce management thread safety - Circuit breaker behavior - Risk assessment rules - Transaction lifecycle Total: 129 test cases + performance benchmarks Target: 100% test coverage for execution engine Related to Phase 4 (Execution Engine) implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
567
pkg/execution/executor_test.go
Normal file
567
pkg/execution/executor_test.go
Normal file
@@ -0,0 +1,567 @@
|
||||
package execution
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/your-org/mev-bot/pkg/arbitrage"
|
||||
mevtypes "github.com/your-org/mev-bot/pkg/types"
|
||||
)
|
||||
|
||||
func TestDefaultExecutorConfig(t *testing.T) {
|
||||
config := DefaultExecutorConfig()
|
||||
|
||||
assert.NotNil(t, config)
|
||||
assert.Equal(t, uint64(1), config.ConfirmationBlocks)
|
||||
assert.Equal(t, 5*time.Minute, config.TimeoutPerTx)
|
||||
assert.Equal(t, 3, config.MaxRetries)
|
||||
assert.Equal(t, uint64(2), config.NonceMargin)
|
||||
assert.Equal(t, "fast", config.GasPriceStrategy)
|
||||
}
|
||||
|
||||
func TestExecutor_getNextNonce(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
currentNonce: 10,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Get first nonce
|
||||
nonce1 := executor.getNextNonce()
|
||||
assert.Equal(t, uint64(10), nonce1)
|
||||
assert.Equal(t, uint64(11), executor.currentNonce)
|
||||
|
||||
// Get second nonce
|
||||
nonce2 := executor.getNextNonce()
|
||||
assert.Equal(t, uint64(11), nonce2)
|
||||
assert.Equal(t, uint64(12), executor.currentNonce)
|
||||
}
|
||||
|
||||
func TestExecutor_releaseNonce(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
currentNonce: 10,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Release current nonce - 1 (should work)
|
||||
executor.releaseNonce(9)
|
||||
assert.Equal(t, uint64(9), executor.currentNonce)
|
||||
|
||||
// Release older nonce (should not work)
|
||||
executor.currentNonce = 10
|
||||
executor.releaseNonce(5)
|
||||
assert.Equal(t, uint64(10), executor.currentNonce) // Should not change
|
||||
}
|
||||
|
||||
func TestExecutor_trackPendingTransaction(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
hash := common.HexToHash("0x123")
|
||||
nonce := uint64(5)
|
||||
opp := &arbitrage.Opportunity{
|
||||
ID: "test-opp",
|
||||
InputAmount: big.NewInt(1e18),
|
||||
}
|
||||
|
||||
executor.trackPendingTransaction(nonce, hash, opp)
|
||||
|
||||
// Check transaction is tracked
|
||||
pending, exists := executor.nonceCache[nonce]
|
||||
assert.True(t, exists)
|
||||
assert.NotNil(t, pending)
|
||||
assert.Equal(t, hash, pending.Hash)
|
||||
assert.Equal(t, nonce, pending.Nonce)
|
||||
assert.Equal(t, opp, pending.Opportunity)
|
||||
assert.False(t, pending.Confirmed)
|
||||
assert.False(t, pending.Failed)
|
||||
}
|
||||
|
||||
func TestExecutor_GetPendingTransactions(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Add pending transactions
|
||||
executor.nonceCache[1] = &PendingTransaction{
|
||||
Hash: common.HexToHash("0x01"),
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
}
|
||||
executor.nonceCache[2] = &PendingTransaction{
|
||||
Hash: common.HexToHash("0x02"),
|
||||
Confirmed: true, // Already confirmed
|
||||
Failed: false,
|
||||
}
|
||||
executor.nonceCache[3] = &PendingTransaction{
|
||||
Hash: common.HexToHash("0x03"),
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
}
|
||||
|
||||
pending := executor.GetPendingTransactions()
|
||||
|
||||
// Should only return unconfirmed, non-failed transactions
|
||||
assert.Len(t, pending, 2)
|
||||
}
|
||||
|
||||
func TestExecutor_Stop(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
stopCh: make(chan struct{}),
|
||||
stopped: false,
|
||||
}
|
||||
|
||||
executor.Stop()
|
||||
|
||||
assert.True(t, executor.stopped)
|
||||
|
||||
// Calling Stop again should not panic
|
||||
executor.Stop()
|
||||
assert.True(t, executor.stopped)
|
||||
}
|
||||
|
||||
func TestPendingTransaction_Fields(t *testing.T) {
|
||||
hash := common.HexToHash("0x123")
|
||||
nonce := uint64(5)
|
||||
opp := &arbitrage.Opportunity{
|
||||
ID: "test-opp",
|
||||
}
|
||||
submittedAt := time.Now()
|
||||
|
||||
pending := &PendingTransaction{
|
||||
Hash: hash,
|
||||
Nonce: nonce,
|
||||
Opportunity: opp,
|
||||
SubmittedAt: submittedAt,
|
||||
LastChecked: submittedAt,
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
FailReason: "",
|
||||
Receipt: nil,
|
||||
Retries: 0,
|
||||
}
|
||||
|
||||
assert.Equal(t, hash, pending.Hash)
|
||||
assert.Equal(t, nonce, pending.Nonce)
|
||||
assert.Equal(t, opp, pending.Opportunity)
|
||||
assert.Equal(t, submittedAt, pending.SubmittedAt)
|
||||
assert.False(t, pending.Confirmed)
|
||||
assert.False(t, pending.Failed)
|
||||
assert.Equal(t, 0, pending.Retries)
|
||||
}
|
||||
|
||||
func TestExecutionResult_Success(t *testing.T) {
|
||||
hash := common.HexToHash("0x123")
|
||||
actualProfit := big.NewInt(0.1e18)
|
||||
gasCost := big.NewInt(0.01e18)
|
||||
duration := 5 * time.Second
|
||||
|
||||
result := &ExecutionResult{
|
||||
Success: true,
|
||||
TxHash: hash,
|
||||
Receipt: nil,
|
||||
ActualProfit: actualProfit,
|
||||
GasCost: gasCost,
|
||||
Error: nil,
|
||||
Duration: duration,
|
||||
}
|
||||
|
||||
assert.True(t, result.Success)
|
||||
assert.Equal(t, hash, result.TxHash)
|
||||
assert.Equal(t, actualProfit, result.ActualProfit)
|
||||
assert.Equal(t, gasCost, result.GasCost)
|
||||
assert.Nil(t, result.Error)
|
||||
assert.Equal(t, duration, result.Duration)
|
||||
}
|
||||
|
||||
func TestExecutionResult_Failure(t *testing.T) {
|
||||
hash := common.HexToHash("0x123")
|
||||
err := assert.AnError
|
||||
duration := 2 * time.Second
|
||||
|
||||
result := &ExecutionResult{
|
||||
Success: false,
|
||||
TxHash: hash,
|
||||
Receipt: nil,
|
||||
ActualProfit: nil,
|
||||
GasCost: nil,
|
||||
Error: err,
|
||||
Duration: duration,
|
||||
}
|
||||
|
||||
assert.False(t, result.Success)
|
||||
assert.Equal(t, hash, result.TxHash)
|
||||
assert.NotNil(t, result.Error)
|
||||
assert.Equal(t, duration, result.Duration)
|
||||
}
|
||||
|
||||
func TestExecutorConfig_RPC(t *testing.T) {
|
||||
config := &ExecutorConfig{
|
||||
PrivateKey: []byte{0x01, 0x02, 0x03},
|
||||
WalletAddress: common.HexToAddress("0x123"),
|
||||
RPCEndpoint: "http://localhost:8545",
|
||||
PrivateRPCEndpoint: "http://flashbots:8545",
|
||||
UsePrivateRPC: true,
|
||||
}
|
||||
|
||||
assert.NotEmpty(t, config.PrivateKey)
|
||||
assert.NotEmpty(t, config.WalletAddress)
|
||||
assert.Equal(t, "http://localhost:8545", config.RPCEndpoint)
|
||||
assert.Equal(t, "http://flashbots:8545", config.PrivateRPCEndpoint)
|
||||
assert.True(t, config.UsePrivateRPC)
|
||||
}
|
||||
|
||||
func TestExecutorConfig_GasStrategy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
strategy string
|
||||
multiplier float64
|
||||
maxIncrease float64
|
||||
}{
|
||||
{
|
||||
name: "Fast strategy",
|
||||
strategy: "fast",
|
||||
multiplier: 1.2,
|
||||
maxIncrease: 1.5,
|
||||
},
|
||||
{
|
||||
name: "Market strategy",
|
||||
strategy: "market",
|
||||
multiplier: 1.0,
|
||||
maxIncrease: 1.3,
|
||||
},
|
||||
{
|
||||
name: "Aggressive strategy",
|
||||
strategy: "aggressive",
|
||||
multiplier: 1.5,
|
||||
maxIncrease: 2.0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
config := &ExecutorConfig{
|
||||
GasPriceStrategy: tt.strategy,
|
||||
GasPriceMultiplier: tt.multiplier,
|
||||
MaxGasPriceIncrement: tt.maxIncrease,
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.strategy, config.GasPriceStrategy)
|
||||
assert.Equal(t, tt.multiplier, config.GasPriceMultiplier)
|
||||
assert.Equal(t, tt.maxIncrease, config.MaxGasPriceIncrement)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecutor_calculateActualProfit(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// Create mock receipt
|
||||
receipt := &types.Receipt{
|
||||
GasUsed: 150000,
|
||||
EffectiveGasPrice: big.NewInt(50e9), // 50 gwei
|
||||
}
|
||||
|
||||
opp := &arbitrage.Opportunity{
|
||||
GrossProfit: big.NewInt(0.2e18), // 0.2 ETH
|
||||
}
|
||||
|
||||
actualProfit := executor.calculateActualProfit(receipt, opp)
|
||||
|
||||
// Gas cost = 150000 * 50e9 = 0.0075 ETH
|
||||
// Actual profit = 0.2 - 0.0075 = 0.1925 ETH
|
||||
expectedProfit := big.NewInt(192500000000000000) // 0.1925 ETH
|
||||
assert.Equal(t, expectedProfit, actualProfit)
|
||||
}
|
||||
|
||||
func TestExecutor_NonceManagement_Concurrent(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
currentNonce: 10,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Simulate concurrent nonce requests
|
||||
nonces := make(chan uint64, 10)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
nonce := executor.getNextNonce()
|
||||
nonces <- nonce
|
||||
}()
|
||||
}
|
||||
|
||||
// Collect all nonces
|
||||
receivedNonces := make(map[uint64]bool)
|
||||
for i := 0; i < 10; i++ {
|
||||
nonce := <-nonces
|
||||
// Check for duplicates
|
||||
assert.False(t, receivedNonces[nonce], "Duplicate nonce detected")
|
||||
receivedNonces[nonce] = true
|
||||
}
|
||||
|
||||
// All nonces should be unique and sequential
|
||||
assert.Len(t, receivedNonces, 10)
|
||||
assert.Equal(t, uint64(20), executor.currentNonce)
|
||||
}
|
||||
|
||||
func TestExecutor_PendingTransaction_Timeout(t *testing.T) {
|
||||
submittedAt := time.Now().Add(-10 * time.Minute)
|
||||
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
SubmittedAt: submittedAt,
|
||||
LastChecked: time.Now(),
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
Retries: 0,
|
||||
}
|
||||
|
||||
timeout := 5 * time.Minute
|
||||
isTimedOut := time.Since(pending.SubmittedAt) > timeout
|
||||
|
||||
assert.True(t, isTimedOut)
|
||||
}
|
||||
|
||||
func TestExecutor_PendingTransaction_NotTimedOut(t *testing.T) {
|
||||
submittedAt := time.Now().Add(-2 * time.Minute)
|
||||
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
SubmittedAt: submittedAt,
|
||||
LastChecked: time.Now(),
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
Retries: 0,
|
||||
}
|
||||
|
||||
timeout := 5 * time.Minute
|
||||
isTimedOut := time.Since(pending.SubmittedAt) > timeout
|
||||
|
||||
assert.False(t, isTimedOut)
|
||||
}
|
||||
|
||||
func TestExecutor_PendingTransaction_MaxRetries(t *testing.T) {
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
Retries: 3,
|
||||
}
|
||||
|
||||
maxRetries := 3
|
||||
canRetry := pending.Retries < maxRetries
|
||||
|
||||
assert.False(t, canRetry)
|
||||
}
|
||||
|
||||
func TestExecutor_PendingTransaction_CanRetry(t *testing.T) {
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
Retries: 1,
|
||||
}
|
||||
|
||||
maxRetries := 3
|
||||
canRetry := pending.Retries < maxRetries
|
||||
|
||||
assert.True(t, canRetry)
|
||||
}
|
||||
|
||||
func TestExecutor_TransactionConfirmed(t *testing.T) {
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
Confirmed: true,
|
||||
Failed: false,
|
||||
Receipt: &types.Receipt{Status: types.ReceiptStatusSuccessful},
|
||||
}
|
||||
|
||||
assert.True(t, pending.Confirmed)
|
||||
assert.False(t, pending.Failed)
|
||||
assert.NotNil(t, pending.Receipt)
|
||||
assert.Equal(t, types.ReceiptStatusSuccessful, pending.Receipt.Status)
|
||||
}
|
||||
|
||||
func TestExecutor_TransactionFailed(t *testing.T) {
|
||||
pending := &PendingTransaction{
|
||||
Hash: common.HexToHash("0x123"),
|
||||
Confirmed: true,
|
||||
Failed: true,
|
||||
FailReason: "transaction reverted",
|
||||
Receipt: &types.Receipt{Status: types.ReceiptStatusFailed},
|
||||
}
|
||||
|
||||
assert.True(t, pending.Confirmed)
|
||||
assert.True(t, pending.Failed)
|
||||
assert.Equal(t, "transaction reverted", pending.FailReason)
|
||||
assert.NotNil(t, pending.Receipt)
|
||||
assert.Equal(t, types.ReceiptStatusFailed, pending.Receipt.Status)
|
||||
}
|
||||
|
||||
func TestExecutorConfig_Defaults(t *testing.T) {
|
||||
config := DefaultExecutorConfig()
|
||||
|
||||
// Test all default values
|
||||
assert.Equal(t, uint64(1), config.ConfirmationBlocks)
|
||||
assert.Equal(t, 5*time.Minute, config.TimeoutPerTx)
|
||||
assert.Equal(t, 3, config.MaxRetries)
|
||||
assert.Equal(t, 5*time.Second, config.RetryDelay)
|
||||
assert.Equal(t, uint64(2), config.NonceMargin)
|
||||
assert.Equal(t, "fast", config.GasPriceStrategy)
|
||||
assert.Equal(t, float64(1.1), config.GasPriceMultiplier)
|
||||
assert.Equal(t, float64(1.5), config.MaxGasPriceIncrement)
|
||||
assert.Equal(t, 1*time.Second, config.MonitorInterval)
|
||||
assert.Equal(t, 1*time.Minute, config.CleanupInterval)
|
||||
}
|
||||
|
||||
func TestExecutor_MultipleOpportunities(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
currentNonce: 10,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Track multiple opportunities
|
||||
for i := 0; i < 5; i++ {
|
||||
hash := common.HexToHash(string(rune(i)))
|
||||
nonce := executor.getNextNonce()
|
||||
opp := &arbitrage.Opportunity{
|
||||
ID: string(rune(i)),
|
||||
}
|
||||
|
||||
executor.trackPendingTransaction(nonce, hash, opp)
|
||||
}
|
||||
|
||||
// Check all are tracked
|
||||
assert.Len(t, executor.nonceCache, 5)
|
||||
assert.Equal(t, uint64(15), executor.currentNonce)
|
||||
|
||||
// Get pending transactions
|
||||
pending := executor.GetPendingTransactions()
|
||||
assert.Len(t, pending, 5)
|
||||
}
|
||||
|
||||
func TestExecutor_CleanupOldTransactions(t *testing.T) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Add old confirmed transaction
|
||||
oldTime := time.Now().Add(-2 * time.Hour)
|
||||
executor.nonceCache[1] = &PendingTransaction{
|
||||
Hash: common.HexToHash("0x01"),
|
||||
Confirmed: true,
|
||||
LastChecked: oldTime,
|
||||
}
|
||||
|
||||
// Add recent transaction
|
||||
executor.nonceCache[2] = &PendingTransaction{
|
||||
Hash: common.HexToHash("0x02"),
|
||||
Confirmed: false,
|
||||
LastChecked: time.Now(),
|
||||
}
|
||||
|
||||
// Simulate cleanup (cutoff = 1 hour)
|
||||
cutoff := time.Now().Add(-1 * time.Hour)
|
||||
for nonce, pending := range executor.nonceCache {
|
||||
if (pending.Confirmed || pending.Failed) && pending.LastChecked.Before(cutoff) {
|
||||
delete(executor.nonceCache, nonce)
|
||||
}
|
||||
}
|
||||
|
||||
// Only recent transaction should remain
|
||||
assert.Len(t, executor.nonceCache, 1)
|
||||
_, exists := executor.nonceCache[2]
|
||||
assert.True(t, exists)
|
||||
}
|
||||
|
||||
// Benchmark tests
|
||||
func BenchmarkExecutor_getNextNonce(b *testing.B) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
currentNonce: 0,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = executor.getNextNonce()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecutor_trackPendingTransaction(b *testing.B) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
hash := common.HexToHash("0x123")
|
||||
opp := &arbitrage.Opportunity{
|
||||
ID: "test-opp",
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
executor.trackPendingTransaction(uint64(i), hash, opp)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecutor_GetPendingTransactions(b *testing.B) {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
executor := &Executor{
|
||||
logger: logger,
|
||||
nonceCache: make(map[uint64]*PendingTransaction),
|
||||
}
|
||||
|
||||
// Add 100 pending transactions
|
||||
for i := 0; i < 100; i++ {
|
||||
executor.nonceCache[uint64(i)] = &PendingTransaction{
|
||||
Hash: common.HexToHash(string(rune(i))),
|
||||
Confirmed: false,
|
||||
Failed: false,
|
||||
}
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = executor.GetPendingTransactions()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user