mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Update tx_fetcher_test.go
This commit is contained in:
parent
2eafd6b6e7
commit
75009c2412
1 changed files with 80 additions and 13 deletions
|
|
@ -2150,9 +2150,17 @@ func containsHashInAnnounces(slice []announce, hash common.Hash) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Tests that a transaction is forgotten after the timeout.
|
||||
// TestTransactionForgotten verifies that underpriced transactions are properly
|
||||
// forgotten after the timeout period, testing both the exact timeout boundary
|
||||
// and the cleanup of the underpriced cache.
|
||||
func TestTransactionForgotten(t *testing.T) {
|
||||
fetcher := NewTxFetcher(
|
||||
// Test ensures that underpriced transactions are properly forgotten after a timeout period,
|
||||
// including checks for timeout boundary and cache cleanup.
|
||||
t.Parallel()
|
||||
|
||||
// Create a mock clock for deterministic time control
|
||||
mockClock := new(mclock.Simulated)
|
||||
fetcher := NewTxFetcherForTests(
|
||||
func(common.Hash) bool { return false },
|
||||
func(txs []*types.Transaction) []error {
|
||||
errs := make([]error, len(txs))
|
||||
|
|
@ -2163,24 +2171,83 @@ func TestTransactionForgotten(t *testing.T) {
|
|||
},
|
||||
func(string, []common.Hash) error { return nil },
|
||||
func(string) {},
|
||||
mockClock,
|
||||
rand.New(rand.NewSource(0)), // Use fixed seed for deterministic behavior
|
||||
)
|
||||
fetcher.Start()
|
||||
defer fetcher.Stop()
|
||||
// Create one TX which is 5 minutes old, and one which is recent
|
||||
tx1 := types.NewTx(&types.LegacyTx{Nonce: 0})
|
||||
tx1.SetTime(time.Now().Add(-maxTxUnderpricedTimeout - 1*time.Second))
|
||||
tx2 := types.NewTx(&types.LegacyTx{Nonce: 1})
|
||||
|
||||
// Enqueue both in the fetcher. They will be immediately tagged as underpriced
|
||||
if err := fetcher.Enqueue("asdf", []*types.Transaction{tx1, tx2}, false); err != nil {
|
||||
// Create two test transactions with the same timestamp
|
||||
tx1 := types.NewTransaction(0, common.Address{}, big.NewInt(100), 21000, big.NewInt(1), nil)
|
||||
tx2 := types.NewTransaction(1, common.Address{}, big.NewInt(100), 21000, big.NewInt(1), nil)
|
||||
|
||||
now := time.Unix(int64(mockClock.Now()/1000000000), 0)
|
||||
tx1.SetTime(now)
|
||||
tx2.SetTime(now)
|
||||
|
||||
// Initial state: both transactions should be marked as underpriced
|
||||
if err := fetcher.Enqueue("peer", []*types.Transaction{tx1, tx2}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// isKnownUnderpriced should trigger removal of the first tx (no longer be known underpriced)
|
||||
if fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Fatal("transaction should be forgotten by now")
|
||||
if !fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Error("tx1 should be underpriced")
|
||||
}
|
||||
// isKnownUnderpriced should not trigger removal of the second
|
||||
if !fetcher.isKnownUnderpriced(tx2.Hash()) {
|
||||
t.Fatal("transaction should be known underpriced")
|
||||
t.Error("tx2 should be underpriced")
|
||||
}
|
||||
|
||||
// Verify cache size
|
||||
if size := fetcher.underpriced.Len(); size != 2 {
|
||||
t.Errorf("wrong underpriced cache size: got %d, want %d", size, 2)
|
||||
}
|
||||
|
||||
// Just before timeout: transactions should still be underpriced
|
||||
mockClock.Run(maxTxUnderpricedTimeout - time.Second)
|
||||
if !fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Error("tx1 should still be underpriced before timeout")
|
||||
}
|
||||
if !fetcher.isKnownUnderpriced(tx2.Hash()) {
|
||||
t.Error("tx2 should still be underpriced before timeout")
|
||||
}
|
||||
|
||||
// Exactly at timeout boundary: transactions should still be present
|
||||
mockClock.Run(time.Second)
|
||||
if !fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Error("tx1 should be present exactly at timeout")
|
||||
}
|
||||
if !fetcher.isKnownUnderpriced(tx2.Hash()) {
|
||||
t.Error("tx2 should be present exactly at timeout")
|
||||
}
|
||||
|
||||
// After timeout: transactions should be forgotten
|
||||
mockClock.Run(time.Second)
|
||||
if fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Error("tx1 should be forgotten after timeout")
|
||||
}
|
||||
if fetcher.isKnownUnderpriced(tx2.Hash()) {
|
||||
t.Error("tx2 should be forgotten after timeout")
|
||||
}
|
||||
|
||||
// Verify cache is empty
|
||||
if size := fetcher.underpriced.Len(); size != 0 {
|
||||
t.Errorf("wrong underpriced cache size after timeout: got %d, want 0", size)
|
||||
}
|
||||
|
||||
// Re-enqueue tx1 with updated timestamp
|
||||
now = time.Unix(int64(mockClock.Now()/1000000000), 0)
|
||||
tx1.SetTime(now)
|
||||
if err := fetcher.Enqueue("peer", []*types.Transaction{tx1}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !fetcher.isKnownUnderpriced(tx1.Hash()) {
|
||||
t.Error("tx1 should be underpriced after re-enqueueing with new timestamp")
|
||||
}
|
||||
if fetcher.isKnownUnderpriced(tx2.Hash()) {
|
||||
t.Error("tx2 should remain forgotten")
|
||||
}
|
||||
|
||||
// Verify final cache state
|
||||
if size := fetcher.underpriced.Len(); size != 1 {
|
||||
t.Errorf("wrong final underpriced cache size: got %d, want 1", size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue