Archived
Switch the memory store's failure under its lock, so a test cannot race the keeper
The keeper keeps each transition from its own goroutine, which reads the memory store's Fail field under the store's lock; tests assigned the exported field bare, so TestAnUnreadableStoreClearsNothing failed under -race whenever the goroutine appended in that window. The field is now set only through SetFail (and Told's likewise), and a test makes the race certain rather than rare. Test-only: the controller runs the bus store, never InMemory.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package conditions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// **A test may take the store away while the keeper is still telling.** The keeper keeps every
|
||||
// transition from a goroutine of its own, so the memory store's failure is read there while a test
|
||||
// switches it: it is switched under the store's lock, or the race detector fails the suite at random
|
||||
// (it once failed TestAnUnreadableStoreClearsNothing). A hundred transitions still being kept while
|
||||
// the failure is switched a hundred times makes the race certain, not rare, when the lock is skipped.
|
||||
func TestTheStoreIsTakenAwayWhileTheKeeperIsTelling(t *testing.T) {
|
||||
k, store, told, _ := keeper(t)
|
||||
ctx := t.Context()
|
||||
const n = 100
|
||||
for i := range n {
|
||||
if _, err := k.Observe(ctx, silent(fmt.Sprintf("m%d", i))); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for range n {
|
||||
store.SetFail(errors.New("the bus is away"))
|
||||
store.SetFail(nil)
|
||||
}
|
||||
told.SetFail(errors.New("no responders"))
|
||||
told.SetFail(nil)
|
||||
settled(t, told, n)
|
||||
}
|
||||
Reference in New Issue
Block a user