From 1e01868d92c38870bafcbb6282563e499afd624e Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 28 Oct 2026 12:25:32 +0100 Subject: [PATCH] An unplaced node owes no pass, so no timer is armed again; every wait a test sets is put back when it ends; pin mesh-sdk 8520a4c, whose masking splits only a file's secrets (issue 1126; review of seed-same-3, round 1) --- go.mod | 2 +- go.sum | 4 ++-- internal/selfcompose/selfcompose.go | 1 + internal/selfcompose/selfcompose_test.go | 26 +++++++++++++++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index d2c607f..8adbd11 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/novox/mesh-host go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028110239-70de9429e56d + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028112237-8520a4c09960 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 golang.org/x/crypto v0.57.0 diff --git a/go.sum b/go.sum index 001153c..f1787fa 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028110239-70de9429e56d h1:6XOd1cxwctmFHS3HU44LhaenXkIzcLABKoY6Er1a4qM= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028110239-70de9429e56d/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028112237-8520a4c09960 h1:+XJKxMzi1l0U9zAlv2wj8i3hTmHvc3XqBcIhCM2luV4= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261028112237-8520a4c09960/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/internal/selfcompose/selfcompose.go b/internal/selfcompose/selfcompose.go index ff3bb0d..713bf3b 100644 --- a/internal/selfcompose/selfcompose.go +++ b/internal/selfcompose/selfcompose.go @@ -482,6 +482,7 @@ func (c *Composer) compose(ctx context.Context) []agent.Update { // The catalogue no longer places it: the agent returns to the controller's compositions (endWhenUnplaced), and // this is no refusal of what it runs (issue 1126, the seed's revert). c.sayOnce("the catalogue no longer places this node: it composes nothing of its own, and keeps running what it runs") + c.owed.Store(false) // nothing of its own to compose, so no pass is owed and no timer armed again return nil } // Composed from the build its want names (frombus.Scope.KeptAt, issue 1126). diff --git a/internal/selfcompose/selfcompose_test.go b/internal/selfcompose/selfcompose_test.go index 86770f3..ddab63c 100644 --- a/internal/selfcompose/selfcompose_test.go +++ b/internal/selfcompose/selfcompose_test.go @@ -244,7 +244,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) { // Issue 1126, the switch made safe: a bus not answering for a moment (a reload of its accounts) is tried again and // refuses nothing; a pass whose run ended refuses nothing either. - composeAgain = []time.Duration{time.Millisecond, time.Millisecond, time.Millisecond} + setFor(t, &composeAgain, []time.Duration{time.Millisecond, time.Millisecond, time.Millisecond}) fresh := func(get func(context.Context, string, string) ([]byte, error)) (*Composer, *[]string) { var refusals []string e := b.env() @@ -491,6 +491,14 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) { if composed != "" || !again.owed.Load() { t.Errorf("%s: composed %v and owes a pass again %v; want nothing handed and a pass owed", row.name, composed != "", again.owed.Load()) } + // Then the catalogue no longer places the node: it composes nothing of its own, and owes no pass either, so + // no timer is armed again (rev-seed-same-3, round 1). + again.mu.Lock() + clear(again.placements) + again.mu.Unlock() + if again.compose(ctx); again.owed.Load() { + t.Errorf("%s: an unplaced node still owes a pass", row.name) + } continue } if composed == "" { @@ -837,7 +845,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) { t.Errorf("what runs moved, and %d answer(s) were composed again for %d group(s)", got-settled, len(answers)) } // A read the bus did not answer is no answer to keep: the group is answered again after a bound, though nothing moved. - laterAgain = []time.Duration{20 * time.Millisecond} + setFor(t, &laterAgain, []time.Duration{20 * time.Millisecond}) ownFails.Store(true) candidate("adds", 9, "lemurs", "keeper") waitFor("the answer met the vault not answering", func(a map[string]delivery.CandidateAnswer) bool { @@ -903,7 +911,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) { // Issue 1126, the shadow shows its work: one input not read after the wait is said, naming it, in the journal and in // a refused answer to each group known; once read, the group is answered for real. - notReadyAfter = 30 * time.Millisecond + setFor(t, ¬ReadyAfter, 30*time.Millisecond) nb := newPatternBus() nenv := readOnly.env() nenv.Watch = nb.watch @@ -948,8 +956,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) { t.Errorf("a shadow not ready said %q", nsaid) } nmu.Unlock() - slowAfter = time.Nanosecond // every answer is slow: said, and noted in words that do not move with the time - defer func() { slowAfter = time.Minute }() + setFor(t, &slowAfter, time.Nanosecond) // every answer is slow: said, and noted in words that do not move with the time nb.send(delivery.AssignerWantsBucket, agent.Update{Caught: true}) select { case a := <-nanswered: @@ -1310,3 +1317,12 @@ func TestAHaveSaysWhetherItsModuleRunsInsideTheNodesOwn(t *testing.T) { }) } } + +// setFor sets a package global (a wait the composer or the shadow reads) for one test, and puts back what it held when +// the test ends, so no later test runs on another test's waits. +func setFor[T any](t *testing.T, p *T, v T) { + t.Helper() + old := *p + *p = v + t.Cleanup(func() { *p = old }) +}