core: Test drop / reject in txpool tests

This extends the existing txpool tests to evaluate the number of dropped and
rejected transactions throughout each test.
This commit is contained in:
Austin Roberts 2020-04-09 14:02:12 -05:00
parent 2791b22d83
commit f7dc0f5b73

View file

@ -152,6 +152,55 @@ func validateEvents(events chan NewTxsEvent, count int) error {
return nil
}
// validateDroppedEvents checks that the correct number of transaction rejection
// and drop events were fired.
func validateDroppedEvents(reject chan RejectedTxEvent, rcount int, dropped chan DropTxsEvent, dcount int) error {
count := 0
for count < rcount {
select {
case <-reject:
count++
case <-time.After(time.Second):
return fmt.Errorf("reject event #%d not fired", count)
}
}
rloop:
for {
select {
case <-reject:
count++
case <-time.After(50 * time.Millisecond):
break rloop
}
}
if count > rcount {
return fmt.Errorf("more than %v reject events fired: %v", rcount, count)
}
count = 0
for count < dcount {
select {
case <-dropped:
count++
case <-time.After(time.Second):
return fmt.Errorf("drop event #%d not fired", count)
}
}
dloop:
for {
select {
case <-dropped:
count++
case <-time.After(50 * time.Millisecond):
break dloop
}
}
if count > dcount {
return fmt.Errorf("more than %v drop events fired: %v", dcount, count)
}
return nil
}
func deriveSender(tx *types.Transaction) (common.Address, error) {
return types.Sender(types.HomesteadSigner{}, tx)
}
@ -689,6 +738,12 @@ func TestTransactionGapFilling(t *testing.T) {
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5)
sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe()
revents := make(chan RejectedTxEvent, testTxPoolConfig.AccountQueue+5)
rsub := pool.rejectTxFeed.Subscribe(revents)
defer rsub.Unsubscribe()
devents := make(chan DropTxsEvent, testTxPoolConfig.AccountQueue+5)
dsub := pool.dropTxFeed.Subscribe(devents)
defer dsub.Unsubscribe()
// Create a pending and a queued transaction with a nonce-gap in between
pool.AddRemotesSync([]*types.Transaction{
@ -722,6 +777,9 @@ func TestTransactionGapFilling(t *testing.T) {
if err := validateEvents(events, 2); err != nil {
t.Fatalf("gap-filling event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 6); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1201,6 +1259,12 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 7); err != nil {
t.Fatalf("original event firing failed: %v", err)
}
revents := make(chan RejectedTxEvent, testTxPoolConfig.AccountQueue+5)
rsub := pool.rejectTxFeed.Subscribe(revents)
defer rsub.Unsubscribe()
devents := make(chan DropTxsEvent, testTxPoolConfig.AccountQueue+5)
dsub := pool.dropTxFeed.Subscribe(devents)
defer dsub.Unsubscribe()
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1217,6 +1281,9 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 0); err != nil {
t.Fatalf("reprice event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 3); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1233,6 +1300,9 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 0); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 3, devents, 0); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1247,6 +1317,9 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil {
t.Fatalf("post-reprice local event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 2); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1263,6 +1336,9 @@ func TestTransactionPoolRepricing(t *testing.T) {
if err := validateEvents(events, 5); err != nil {
t.Fatalf("post-reprice event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 9); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1350,6 +1426,12 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
events := make(chan NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe()
revents := make(chan RejectedTxEvent, testTxPoolConfig.AccountQueue+5)
rsub := pool.rejectTxFeed.Subscribe(revents)
defer rsub.Unsubscribe()
devents := make(chan DropTxsEvent, testTxPoolConfig.AccountQueue+5)
dsub := pool.dropTxFeed.Subscribe(devents)
defer dsub.Unsubscribe()
// Create a number of test accounts and fund them
keys := make([]*ecdsa.PrivateKey, 4)
@ -1381,6 +1463,9 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 3); err != nil {
t.Fatalf("original event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 8); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1408,6 +1493,9 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil {
t.Fatalf("additional event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 1, devents, 13); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1430,6 +1518,9 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
if err := validateEvents(events, 2); err != nil {
t.Fatalf("local event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 7); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1456,6 +1547,12 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
events := make(chan NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe()
revents := make(chan RejectedTxEvent, testTxPoolConfig.AccountQueue+5)
rsub := pool.rejectTxFeed.Subscribe(revents)
defer rsub.Unsubscribe()
devents := make(chan DropTxsEvent, testTxPoolConfig.AccountQueue+5)
dsub := pool.dropTxFeed.Subscribe(devents)
defer dsub.Unsubscribe()
// Create a number of test accounts and fund them
keys := make([]*ecdsa.PrivateKey, 2)
@ -1480,6 +1577,9 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
if err := validateEvents(events, int(config.GlobalSlots)); err != nil {
t.Fatalf("original event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 3); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1497,6 +1597,9 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
if err := validateEvents(events, 1); err != nil {
t.Fatalf("additional event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 0, devents, 4); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}
@ -1583,6 +1686,12 @@ func TestTransactionReplacement(t *testing.T) {
events := make(chan NewTxsEvent, 32)
sub := pool.txFeed.Subscribe(events)
defer sub.Unsubscribe()
revents := make(chan RejectedTxEvent, testTxPoolConfig.AccountQueue+5)
rsub := pool.rejectTxFeed.Subscribe(revents)
defer rsub.Unsubscribe()
devents := make(chan DropTxsEvent, testTxPoolConfig.AccountQueue+5)
dsub := pool.dropTxFeed.Subscribe(devents)
defer dsub.Unsubscribe()
// Create a test account to add transactions with
key, _ := crypto.GenerateKey()
@ -1604,6 +1713,9 @@ func TestTransactionReplacement(t *testing.T) {
if err := validateEvents(events, 2); err != nil {
t.Fatalf("cheap replacement event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 1, devents, 4); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil {
t.Fatalf("failed to add original proper pending transaction: %v", err)
@ -1617,6 +1729,9 @@ func TestTransactionReplacement(t *testing.T) {
if err := validateEvents(events, 2); err != nil {
t.Fatalf("proper replacement event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 1, devents, 2); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
// Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too)
if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil {
@ -1642,6 +1757,9 @@ func TestTransactionReplacement(t *testing.T) {
if err := validateEvents(events, 0); err != nil {
t.Fatalf("queued replacement event firing failed: %v", err)
}
if err := validateDroppedEvents(revents, 2, devents, 6); err != nil {
t.Errorf("gap-filling drop / reject event firing failed: %v", err)
}
if err := validateTxPoolInternals(pool); err != nil {
t.Fatalf("pool internal state corrupted: %v", err)
}