This is an automated email from the ASF dual-hosted git repository. sruehl pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 99a0299d6ab2674f25271a1cc92972f6c7d5db22 Author: Sebastian Rühl <[email protected]> AuthorDate: Mon Jul 20 13:28:43 2026 +0200 test(plc4go): fix three -race flakes in spi test hygiene - spi/default: Test_defaultCodec_Connect built the codec by hand without ctx/ctxCancel - the expire/receive workers panic on the nil-ctx select, and teardown joined wg instead of activeWorker, so the recover path logged through the finished test's logger (log-after-test panic, then SIGSEGV of the test binary). Give the codec a real ctx and join both worker groups in t.Cleanup. - spi/transactions: Test_requestTransaction_AwaitCompletion appended to runningRequests under workLogMutex.RLock - wrong mutex, and a read lock for a write. Use runningRequestMutex.Lock like production code. - spi/utils: TestStopWarn's logHook mutated its slices concurrently from the StopWarn ticker goroutine and the test goroutine's deferred stop (which logs before joining). Guard Run with a mutex. All three reproduced reliably with go test -race -count>=20 and are green for 50-500 iterations after the fix. --- plc4go/spi/default/DefaultCodec_test.go | 12 ++++++++++-- plc4go/spi/transactions/RequestTransaction_test.go | 4 ++-- plc4go/spi/utils/StopWarn_test.go | 5 +++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/plc4go/spi/default/DefaultCodec_test.go b/plc4go/spi/default/DefaultCodec_test.go index 82a71691bf..d5906085c4 100644 --- a/plc4go/spi/default/DefaultCodec_test.go +++ b/plc4go/spi/default/DefaultCodec_test.go @@ -423,9 +423,17 @@ func Test_defaultCodec_Connect(t *testing.T) { customMessageHandling: tt.fields.customMessageHandling, log: testutils.ProduceTestingLogger(t), } + // Connect starts the expire/receive workers, which select on m.ctx and + // log through m.log on panic — so ctx must be non-nil and the workers + // (tracked by activeWorker, not wg) must be joined before the test ends. + m.ctx, m.ctxCancel = context.WithCancel(t.Context()) + t.Cleanup(func() { + m.running.Store(false) + m.ctxCancel() + m.activeWorker.Wait() + m.wg.Wait() + }) tt.wantErr(t, m.Connect(tt.args.ctx), fmt.Sprintf("Connect(%v)", tt.args.ctx)) - m.running.Store(false) - m.wg.Wait() }) } } diff --git a/plc4go/spi/transactions/RequestTransaction_test.go b/plc4go/spi/transactions/RequestTransaction_test.go index 49208e5483..46280524d8 100644 --- a/plc4go/spi/transactions/RequestTransaction_test.go +++ b/plc4go/spi/transactions/RequestTransaction_test.go @@ -324,8 +324,8 @@ func Test_requestTransaction_AwaitCompletion(t1 *testing.T) { wg.Go(func() { time.Sleep(100 * time.Millisecond) r := transaction.parent - r.workLogMutex.RLock() - defer r.workLogMutex.RUnlock() + r.runningRequestMutex.Lock() + defer r.runningRequestMutex.Unlock() r.runningRequests = append(r.runningRequests, &requestTransaction{transactionId: 1}) }) }, diff --git a/plc4go/spi/utils/StopWarn_test.go b/plc4go/spi/utils/StopWarn_test.go index 2d737734de..4a331667a0 100644 --- a/plc4go/spi/utils/StopWarn_test.go +++ b/plc4go/spi/utils/StopWarn_test.go @@ -131,12 +131,17 @@ func TestStopWarn(t *testing.T) { } type logHook struct { + // Run is invoked concurrently: the StopWarn ticker goroutine logs its + // warnings while the stop func logs "done" from the test goroutine. + mu sync.Mutex logEvents []zerolog.Event level []zerolog.Level messages []string } func (logHook *logHook) Run(logEvent *zerolog.Event, level zerolog.Level, message string) { + logHook.mu.Lock() + defer logHook.mu.Unlock() logHook.logEvents = append(logHook.logEvents, *logEvent) logHook.level = append(logHook.level, level) logHook.messages = append(logHook.messages, message)
