From 4f211ea5c5d40f14a861d3482a6edc75342b627d Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Thu, 18 Sep 2025 12:44:06 -0700 Subject: [PATCH] util/eventbus: add a LogAllEvents helper for testing (#17187) When developing (and debugging) tests, it is useful to be able to see all the traffic that transits the event bus during the execution of a test. Updates #15160 Change-Id: I929aee62ccf13bdd4bd07d786924ce9a74acd17a Signed-off-by: M. J. Fromberger --- util/eventbus/eventbustest/eventbustest.go | 22 +++++++++++++++++++ .../eventbustest/eventbustest_test.go | 7 ++++++ 2 files changed, 29 insertions(+) diff --git a/util/eventbus/eventbustest/eventbustest.go b/util/eventbus/eventbustest/eventbustest.go index c32e71140..0916ae522 100644 --- a/util/eventbus/eventbustest/eventbustest.go +++ b/util/eventbus/eventbustest/eventbustest.go @@ -263,3 +263,25 @@ func EqualTo[T any](want T) func(T) error { return nil } } + +// LogAllEvents logs summaries of all the events routed via the specified bus +// during the execution of the test governed by t. This is intended to support +// development and debugging of tests. +func LogAllEvents(t testing.TB, bus *eventbus.Bus) { + dw := bus.Debugger().WatchBus() + done := make(chan struct{}) + go func() { + defer close(done) + var i int + for { + select { + case <-dw.Done(): + return + case re := <-dw.Events(): + i++ + t.Logf("[eventbus] #%[1]d: %[2]T | %+[2]v", i, re.Event) + } + } + }() + t.Cleanup(func() { dw.Close(); <-done }) +} diff --git a/util/eventbus/eventbustest/eventbustest_test.go b/util/eventbus/eventbustest/eventbustest_test.go index f8b37eefe..f1b21ea8f 100644 --- a/util/eventbus/eventbustest/eventbustest_test.go +++ b/util/eventbus/eventbustest/eventbustest_test.go @@ -4,6 +4,7 @@ package eventbustest_test import ( + "flag" "fmt" "strings" "testing" @@ -13,6 +14,8 @@ import ( "tailscale.com/util/eventbus/eventbustest" ) +var doDebug = flag.Bool("debug", false, "Enable debug logging") + type EventFoo struct { Value int } @@ -109,7 +112,11 @@ func TestExpectFilter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + if *doDebug { + eventbustest.LogAllEvents(t, bus) + } tw := eventbustest.NewWatcher(t, bus) + // TODO(cmol): When synctest is out of experimental, use that instead: // https://go.dev/blog/synctest tw.TimeOut = 10 * time.Millisecond