From 984d85865d70305cb500ee49f41d7be2f1a5bca0 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 11 Oct 2026 03:41:14 +0200 Subject: [PATCH] Give the words' zone through a seam, so no test writes time.Local under the race detector (novox/hq issue 443) --- cmd/mesh-controller/delivery_conditions.go | 4 ++++ cmd/mesh-controller/plain_words.go | 2 +- cmd/mesh-controller/plain_words_test.go | 8 +++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cmd/mesh-controller/delivery_conditions.go b/cmd/mesh-controller/delivery_conditions.go index adaa1e29..def12653 100644 --- a/cmd/mesh-controller/delivery_conditions.go +++ b/cmd/mesh-controller/delivery_conditions.go @@ -61,6 +61,10 @@ type waitingCheck struct { // wordsNow is the time the words are said at, which says whether a time needs its day; a seam a test replaces. var wordsNow = time.Now +// wordsZone is the zone a stalled line's times are said in: the controller's local zone, as every other time in its +// messages. A seam a test replaces, so that no test writes time.Local, which every goroutine of the package reads. +var wordsZone = func() *time.Location { return time.Local } + // operatorsOnly is whether the table leaves H2 nothing to do for the line: the state is the operator's. func (l stalledLine) operatorsOnly() bool { return l.H2 == "" || strings.HasPrefix(l.H2, "none") } diff --git a/cmd/mesh-controller/plain_words.go b/cmd/mesh-controller/plain_words.go index 154e156d..29e5da85 100644 --- a/cmd/mesh-controller/plain_words.go +++ b/cmd/mesh-controller/plain_words.go @@ -921,7 +921,7 @@ func sinceWords(since string) string { if err != nil { return ", since a time the forge did not say" } - local, today := at.Local(), wordsNow().Local() + local, today := at.In(wordsZone()), wordsNow().In(wordsZone()) if local.YearDay() == today.YearDay() && local.Year() == today.Year() { return " since " + local.Format("15:04") } diff --git a/cmd/mesh-controller/plain_words_test.go b/cmd/mesh-controller/plain_words_test.go index a31db03a..cd025c19 100644 --- a/cmd/mesh-controller/plain_words_test.go +++ b/cmd/mesh-controller/plain_words_test.go @@ -408,10 +408,12 @@ func TestAnUnansweredMergeCheckSaysWhichCheckAndWhatToDo(t *testing.T) { // the finished words it gave before, and the controller words it in its local zone, as every other time in a message. // The line is the one mesh-delivery says, as in the report of issue 443, with the checks it now carries. func TestAnUnansweredMergeChecksTimeIsSaidInLocalTime(t *testing.T) { - was, wasNow := time.Local, wordsNow - time.Local = time.FixedZone("CEST", 2*60*60) + // The operator's zone given through the seam, never by writing time.Local: other tests' goroutines read it, and + // the build seat runs the suite under the race detector. + wasZone, wasNow := wordsZone, wordsNow + wordsZone = func() *time.Location { return time.FixedZone("CEST", 2*60*60) } wordsNow = func() time.Time { return time.Date(2026, 10, 11, 1, 12, 39, 0, time.UTC) } - t.Cleanup(func() { time.Local, wordsNow = was, wasNow }) + t.Cleanup(func() { wordsZone, wordsNow = wasZone, wasNow }) var l stalledLine if err := json.Unmarshal([]byte(`{"id":"novox/mesh-controller@c11222026a3b","number":212,"state":"unanswered",`+