aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/msg_test.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-17 02:59:37 +0900
committerOphestra <cat@gensokyo.uk>2025-08-17 02:59:37 +0900
commitf35733810e70163aa3e72399007b87451f8efe75 (patch)
tree8cfc7866fe2468f9d99fcfa621aaaaef9712389a /container/msg_test.go
parent9c1a5d43bad802aa0ad717ea603c51f7b0408cdd (diff)
container: check output helper functions
The container test suite has always been somewhat inadequate due to the inability of coverage tooling to reach into containers. This has become an excuse for not testing non-container code as well, which lead to the general lack of confidence when working with container code. This change aims to be one of many to address that to some extent. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container/msg_test.go')
-rw-r--r--container/msg_test.go139
1 files changed, 139 insertions, 0 deletions
diff --git a/container/msg_test.go b/container/msg_test.go
new file mode 100644
index 00000000..6945c892
--- /dev/null
+++ b/container/msg_test.go
@@ -0,0 +1,139 @@
+package container_test
+
+import (
+ "log"
+ "strings"
+ "sync/atomic"
+ "syscall"
+ "testing"
+
+ "hakurei.app/container"
+ "hakurei.app/internal/hlog"
+)
+
+func TestDefaultMsg(t *testing.T) {
+ {
+ w := log.Writer()
+ f := log.Flags()
+ t.Cleanup(func() { log.SetOutput(w); log.SetFlags(f) })
+ }
+ msg := new(container.DefaultMsg)
+
+ t.Run("is verbose", func(t *testing.T) {
+ if !msg.IsVerbose() {
+ t.Error("IsVerbose unexpected outcome")
+ }
+ })
+
+ t.Run("verbose", func(t *testing.T) {
+ log.SetOutput(panicWriter{})
+ msg.Suspend()
+ msg.Verbose()
+ msg.Verbosef("\x00")
+ msg.Resume()
+
+ buf := new(strings.Builder)
+ log.SetOutput(buf)
+ log.SetFlags(0)
+ msg.Verbose()
+ msg.Verbosef("\x00")
+
+ want := "\n\x00\n"
+ if buf.String() != want {
+ t.Errorf("Verbose: %q, want %q", buf.String(), want)
+ }
+ })
+
+ t.Run("wrapErr", func(t *testing.T) {
+ buf := new(strings.Builder)
+ log.SetOutput(buf)
+ log.SetFlags(0)
+ if err := msg.WrapErr(syscall.EBADE, "\x00", "\x00"); err != syscall.EBADE {
+ t.Errorf("WrapErr: %v", err)
+ }
+ msg.PrintBaseErr(syscall.ENOTRECOVERABLE, "cannot cuddle cat:")
+
+ want := "\x00 \x00\ncannot cuddle cat: state not recoverable\n"
+ if buf.String() != want {
+ t.Errorf("WrapErr: %q, want %q", buf.String(), want)
+ }
+ })
+
+ t.Run("inactive", func(t *testing.T) {
+ {
+ inactive := msg.Resume()
+ if inactive {
+ t.Cleanup(func() { msg.Suspend() })
+ }
+ }
+
+ if msg.Resume() {
+ t.Error("Resume unexpected outcome")
+ }
+
+ msg.Suspend()
+ if !msg.Resume() {
+ t.Error("Resume unexpected outcome")
+ }
+ })
+
+ // the function is a noop
+ t.Run("beforeExit", func(t *testing.T) { msg.BeforeExit() })
+}
+
+type panicWriter struct{}
+
+func (panicWriter) Write([]byte) (int, error) { panic("unreachable") }
+
+func saveRestoreOutput(t *testing.T) {
+ out := container.GetOutput()
+ t.Cleanup(func() { container.SetOutput(out) })
+}
+
+func replaceOutput(t *testing.T) {
+ saveRestoreOutput(t)
+ container.SetOutput(&testOutput{t: t})
+}
+
+type testOutput struct {
+ t *testing.T
+ suspended atomic.Bool
+}
+
+func (out *testOutput) IsVerbose() bool { return testing.Verbose() }
+
+func (out *testOutput) Verbose(v ...any) {
+ if !out.IsVerbose() {
+ return
+ }
+ out.t.Log(v...)
+}
+
+func (out *testOutput) Verbosef(format string, v ...any) {
+ if !out.IsVerbose() {
+ return
+ }
+ out.t.Logf(format, v...)
+}
+
+func (out *testOutput) WrapErr(err error, a ...any) error { return hlog.WrapErr(err, a...) }
+func (out *testOutput) PrintBaseErr(err error, fallback string) { hlog.PrintBaseError(err, fallback) }
+
+func (out *testOutput) Suspend() {
+ if out.suspended.CompareAndSwap(false, true) {
+ out.Verbose("suspend called")
+ return
+ }
+ out.Verbose("suspend called on suspended output")
+}
+
+func (out *testOutput) Resume() bool {
+ if out.suspended.CompareAndSwap(true, false) {
+ out.Verbose("resume called")
+ return true
+ }
+ out.Verbose("resume called on unsuspended output")
+ return false
+}
+
+func (out *testOutput) BeforeExit() { out.Verbose("beforeExit called") }