From d5a870b4dcba730f31fff61643dc9e557a8d2305 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 17 Apr 2023 11:05:58 -0700 Subject: [PATCH] wgengine/monitor: add --monitor-duration flag to opt-in TestMonitorMode TestMonitorMode skips by default, without the --monitor flag, and then it previously ran forever. This adds an option --monitor-duration flag that defaults to zero (run forever) but if non-zero bounds how long the tests runs. This means you can then also use e.g. `go test --cpuprofile` and capture a CPU/mem profile for a minute or two. Updates #7621 Signed-off-by: Brad Fitzpatrick --- wgengine/monitor/monitor_test.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/wgengine/monitor/monitor_test.go b/wgengine/monitor/monitor_test.go index f93153a95..30c0ac52a 100644 --- a/wgengine/monitor/monitor_test.go +++ b/wgengine/monitor/monitor_test.go @@ -5,6 +5,7 @@ package monitor import ( "flag" + "sync/atomic" "testing" "time" @@ -55,7 +56,10 @@ func TestMonitorInjectEvent(t *testing.T) { } } -var monitor = flag.String("monitor", "", `go into monitor mode like 'route monitor'; test never terminates. Value can be either "raw" or "callback"`) +var ( + monitor = flag.String("monitor", "", `go into monitor mode like 'route monitor'; test never terminates. Value can be either "raw" or "callback"`) + monitorDuration = flag.Duration("monitor-duration", 0, "if non-zero, how long to run TestMonitorMode. Zero means forever.") +) func TestMonitorMode(t *testing.T) { switch *monitor { @@ -71,18 +75,38 @@ func TestMonitorMode(t *testing.T) { } switch *monitor { case "raw": + var closed atomic.Bool + if *monitorDuration != 0 { + t := time.AfterFunc(*monitorDuration, func() { + closed.Store(true) + mon.Close() + }) + defer t.Stop() + } for { msg, err := mon.om.Receive() + if closed.Load() { + return + } if err != nil { t.Fatal(err) } t.Logf("msg: %#v", msg) } case "callback": + var done <-chan time.Time + if *monitorDuration != 0 { + t := time.NewTimer(*monitorDuration) + defer t.Stop() + done = t.C + } + n := 0 mon.RegisterChangeCallback(func(changed bool, st *interfaces.State) { + n++ t.Logf("cb: changed=%v, ifSt=%v", changed, st) }) mon.Start() - select {} + <-done + t.Logf("%v callbacks", n) } }