m/test/util: implement MustTestEventual

This allows us to early abort tests in which some critical TestEventual
blocks fail.

Change-Id: I82d2dd692abdc04b33d30571ea5ff55dc52635c9
Reviewed-on: https://review.monogon.dev/c/monogon/+/2883
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/test/util/runners.go b/metropolis/test/util/runners.go
index e25fe10..99de4f1 100644
--- a/metropolis/test/util/runners.go
+++ b/metropolis/test/util/runners.go
@@ -12,15 +12,16 @@
 	"source.monogon.dev/metropolis/test/launch"
 )
 
-// TestEventual creates a new subtest looping the given function until it
-// either doesn't return an error anymore or the timeout is exceeded. The last
-// returned non-context-related error is being used as the test error.
-func TestEventual(t *testing.T, name string, ctx context.Context, timeout time.Duration, f func(context.Context) error) {
+// TestEventual creates a new subtest looping the given function until it either
+// doesn't return an error anymore, the timeout is exceeded or PermanentError is
+// returned. The last returned non-context-related error is being used as the
+// test error.
+func TestEventual(t *testing.T, name string, ctx context.Context, timeout time.Duration, f func(context.Context) error) bool {
 	start := time.Now()
 	ctx, cancel := context.WithTimeout(ctx, timeout)
 	t.Helper()
 	launch.Log("Test: %s: starting...", name)
-	t.Run(name, func(t *testing.T) {
+	return t.Run(name, func(t *testing.T) {
 		defer cancel()
 		var lastErr = errors.New("test didn't run to completion at least once")
 		for {
@@ -45,6 +46,14 @@
 	})
 }
 
+// MustTestEventual is like TestEventual, but aborts the `t` test with Fatal if a
+// timeout occurred or PermanentError was returned.
+func MustTestEventual(t *testing.T, name string, ctx context.Context, timeout time.Duration, f func(context.Context) error) {
+	if !TestEventual(t, name, ctx, timeout, f) {
+		t.Fatalf("Test: %s: fatal failure", name)
+	}
+}
+
 // PermanentError can be returned inside TestEventual to indicate that the test
 // is 'stuck', that it will not make progress anymore and that it should be
 // failed immediately.