Wait on the watch having handled the entry, not 2 s twice, in the pull-key watch test (issue 1337)

The unit level ran at 4.4 s of its 5 s bound; this one test took 4.00 s of internal/link's 4.37 s by waiting a fixed 2 s for two things that must not happen. It now waits on the fake watch having handled the entry (two filler entries pass the one-slot channel only after the real one was handled) and on the watches having stopped after a move. Broken in turn (a verdict alone moving the check, a move told twice) it fails.

Unit level at this commit: 2454 tests (6 skipped), 2.84 s (bound 5 s); internal/link 0.36 s. Five slowest tests: TestNoPlanIsWrittenButThroughSavePlansMoving 0.64 s, TestAResolverThatAnswersNothingIsHeldAndSaidInMachineNames 0.48 s, TestNoCodeNamesATableOfTheChain 0.31 s, TestEveryUplinkListsBothResolversItsOwnFirst 0.29 s, TestEveryWordingIsPlain 0.28 s. No test moved to the integration level.
This commit is contained in:
2026-10-20 08:12:38 +00:00
parent 6c2a8d6210
commit b280b9de10
+39 -5
View File
@@ -6,6 +6,7 @@ import (
"errors"
"reflect"
"strings"
"sync"
"testing"
"time"
@@ -116,11 +117,30 @@ func contains(s, sub string) bool { return strings.Contains(s, sub) }
// fakeWatch is one bucket's watch of the key, fed by the test.
type fakeWatch struct {
updates chan jetstream.KeyValueEntry
stopped bool
done chan struct{} // closed when the watch is stopped
once sync.Once
}
func newFakeWatch() *fakeWatch {
return &fakeWatch{updates: make(chan jetstream.KeyValueEntry, 1), done: make(chan struct{})}
}
// handled returns once the watch has taken the entry fed before it and finished with it. The channel holds one entry,
// so the second filler (an entry the watch passes over) can only be sent after the first was taken, which the watch
// does only after it handled the entry before it. It needs a watch that is still listening: after a move it is not.
func (f *fakeWatch) handled(t *testing.T) {
t.Helper()
for range 2 {
select {
case f.updates <- fakeEntry{value: "not a key"}:
case <-time.After(2 * time.Second):
t.Fatal("the watch took no entry")
}
}
}
func (f *fakeWatch) Updates() <-chan jetstream.KeyValueEntry { return f.updates }
func (f *fakeWatch) Stop() error { f.stopped = true; return nil }
func (f *fakeWatch) Stop() error { f.once.Do(func() { close(f.done) }); return nil }
type fakeEntry struct {
jetstream.KeyValueEntry
@@ -138,7 +158,7 @@ func TestARunningChecksWatchFindsItsKeyInTheGatesBucketOrTodays(t *testing.T) {
run := func(exist ...string) (map[string]*fakeWatch, chan PullKey, func(), error) {
watches := map[string]*fakeWatch{}
for _, b := range exist {
watches[b] = &fakeWatch{updates: make(chan jetstream.KeyValueEntry, 1)}
watches[b] = newFakeWatch()
}
moved := make(chan PullKey, 2)
stop, err := watchPullIn(t.Context(), req.Check.Pulls, func(_ context.Context, bucket string) (pullWatcher, error) {
@@ -182,14 +202,28 @@ func TestARunningChecksWatchFindsItsKeyInTheGatesBucketOrTodays(t *testing.T) {
t.Fatal(err)
}
watches["mesh-delivery-gate_pulls"].updates <- fakeEntry{value: `{"head":"old","trunk":"t","verdict":"pass"}`}
if _, ok := wait(moved); ok {
watches["mesh-delivery-gate_pulls"].handled(t)
select {
case <-moved:
t.Error("a verdict alone moved the check")
default:
}
// Both buckets hear the move; the second watch is done (stopped) once it has handled its entry, and by then a
// second telling would be in the channel.
watches["mesh-delivery-gate_pulls"].updates <- fakeEntry{value: `{"head":"newer","trunk":"t"}`}
watches["mesh-delivery_pulls"].updates <- fakeEntry{value: `{"head":"newer","trunk":"t"}`}
wait(moved)
if _, ok := wait(moved); ok {
for b, w := range watches {
select {
case <-w.done:
case <-time.After(2 * time.Second):
t.Errorf("the watch of %s did not end after the move", b)
}
}
select {
case <-moved:
t.Error("a move was told twice")
default:
}
stop()
if _, _, _, err := run(); err == nil {