chore: report aggregate race conditions in test

This commit is contained in:
Arran Schlosberg 2024-11-28 13:09:17 +00:00
parent 5b4ac11371
commit e15cb3e553
No known key found for this signature in database
GPG key ID: 5DD5567C12C5F312

View file

@ -19,6 +19,7 @@ package state
import ( import (
"math/big" "math/big"
"sync" "sync"
"sync/atomic"
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -71,8 +72,8 @@ func TestSchdeulerTerminationRaceCondition(t *testing.T) {
// The lock-based implementation of [subfetcher] had a race condition // The lock-based implementation of [subfetcher] had a race condition
// whereby schedule() could obtain the lock after the <-sf.stop branch of // whereby schedule() could obtain the lock after the <-sf.stop branch of
// loop() had already checked for an empty queue. Although probabilistic, // loop() had already checked for an empty queue. Although probabilistic,
// this test reliably triggered at a rate of ~4 in 10,000 on an Apple M3 Max // this test reliably triggered at a rates of (~4 in 10k) and (~100 in 50k)
// chip. // on an Apple M3 Max chip.
t.Parallel() t.Parallel()
db := filledStateDB() db := filledStateDB()
@ -80,9 +81,13 @@ func TestSchdeulerTerminationRaceCondition(t *testing.T) {
// Maximise concurrency by synchronising all scheduling and termination. // Maximise concurrency by synchronising all scheduling and termination.
start := make(chan struct{}) start := make(chan struct{})
var wg sync.WaitGroup var (
wg sync.WaitGroup
raceInduced atomic.Uint64
)
for i := 0; i < 50_000; i++ { const numTrials = 50_000
for i := 0; i < numTrials; i++ {
wg.Add(2) wg.Add(2)
fetcher := newSubfetcher(db.db, db.originalRoot, common.Hash{}, db.originalRoot, common.Address{}) fetcher := newSubfetcher(db.db, db.originalRoot, common.Hash{}, db.originalRoot, common.Address{})
@ -102,13 +107,16 @@ func TestSchdeulerTerminationRaceCondition(t *testing.T) {
<-doneScheduling <-doneScheduling
if gotScheduleErr == nil && len(fetcher.tasks) > 0 { if gotScheduleErr == nil && len(fetcher.tasks) > 0 {
t.Errorf("%T.schedule() returned nil error but %d task(s) remain in queue after %T.terminate([blocking]) returned", fetcher, len(fetcher.tasks), fetcher) raceInduced.Add(1)
} }
}() }()
} }
close(start) close(start)
wg.Wait() wg.Wait()
if got := raceInduced.Load(); got > 0 {
t.Errorf("In %d/%d concurrent trials %T.schedule() returned nil error but >0 tasks remain in queue after %[3]T.terminate([blocking]) returned", got, numTrials, &subfetcher{})
}
} }
func TestVerklePrefetcher(t *testing.T) { func TestVerklePrefetcher(t *testing.T) {