m/pkg/{logtree,supervisor}: add test helpers

This adds two functions:

  logtree.PipeAllToStderr
  supervisor.NewHarness

These are designed to simplify tests that exercise code which expects to
be run as a supervisor runnable and/or have access to a logtree
instance.

Change-Id: Ibce77aa4927515af7c273d07ced15215ff456ecc
Reviewed-on: https://review.monogon.dev/c/monogon/+/205
Reviewed-by: Leopold Schabel <leo@nexantic.com>
diff --git a/metropolis/pkg/logtree/testhelpers.go b/metropolis/pkg/logtree/testhelpers.go
new file mode 100644
index 0000000..a033bdb
--- /dev/null
+++ b/metropolis/pkg/logtree/testhelpers.go
@@ -0,0 +1,38 @@
+package logtree
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"testing"
+)
+
+// PipeAllToStderr starts a goroutine that will forward all logtree entries
+// into stderr, in the canonical logtree payload representation.
+//
+// It's designed to be used in tests, and will automatically stop when the
+// test/benchmark it's running in exits.
+func PipeAllToStderr(t *testing.T, lt *LogTree) {
+	t.Helper()
+
+	reader, err := lt.Read("", WithChildren(), WithStream())
+	if err != nil {
+		t.Fatalf("Failed to set up logtree reader: %v", err)
+	}
+
+	// Internal context used to cancel the goroutine. This could also be a
+	// implemented via a channel.
+	ctx, ctxC := context.WithCancel(context.Background())
+	t.Cleanup(ctxC)
+
+	go func() {
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			case p := <-reader.Stream:
+				fmt.Fprintf(os.Stderr, "%s\n", p.String())
+			}
+		}
+	}()
+}