aboutsummaryrefslogtreecommitdiffhomepage
path: root/message/message_test.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-10-09 05:04:08 +0900
committerOphestra <cat@gensokyo.uk>2025-10-09 05:18:19 +0900
commit87b5c30ef6d5b7b8a10d6a5a8610054c403923e6 (patch)
tree805116c39a623bb30fc532af47ea3ed78b7304c0 /message/message_test.go
parentdf9b77b077d967d35082adb8ab3b00dd67d7bc97 (diff)
message: relocate from container
This package is quite useful. This change allows it to be imported without importing container. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'message/message_test.go')
-rw-r--r--message/message_test.go178
1 files changed, 178 insertions, 0 deletions
diff --git a/message/message_test.go b/message/message_test.go
new file mode 100644
index 00000000..93ceaacb
--- /dev/null
+++ b/message/message_test.go
@@ -0,0 +1,178 @@
+package message_test
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "log"
+ "strings"
+ "syscall"
+ "testing"
+
+ "hakurei.app/container"
+ "hakurei.app/container/stub"
+ "hakurei.app/message"
+)
+
+func TestMessageError(t *testing.T) {
+ testCases := []struct {
+ name string
+ err error
+ want string
+ wantOk bool
+ }{
+ {"nil", nil, "", false},
+ {"new", errors.New(":3"), "", false},
+ {"start", &container.StartError{
+ Step: "meow",
+ Err: syscall.ENOTRECOVERABLE,
+ }, "cannot meow: state not recoverable", true},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ got, ok := message.GetMessage(tc.err)
+ if got != tc.want {
+ t.Errorf("GetMessage: %q, want %q", got, tc.want)
+ }
+ if ok != tc.wantOk {
+ t.Errorf("GetMessage: ok = %v, want %v", ok, tc.wantOk)
+ }
+ })
+ }
+}
+
+func TestDefaultMsg(t *testing.T) {
+ // copied from output.go
+ const suspendBufMax = 1 << 24
+
+ t.Run("logger", func(t *testing.T) {
+ t.Run("nil", func(t *testing.T) {
+ got := message.NewMsg(nil).GetLogger()
+
+ if out := got.Writer().(*message.Suspendable).Downstream; out != log.Writer() {
+ t.Errorf("GetLogger: Downstream = %#v", out)
+ }
+
+ if prefix := got.Prefix(); prefix != "container: " {
+ t.Errorf("GetLogger: prefix = %q", prefix)
+ }
+ })
+
+ t.Run("takeover", func(t *testing.T) {
+ l := log.New(io.Discard, "\x00", 0xdeadbeef)
+ got := message.NewMsg(l)
+
+ if logger := got.GetLogger(); logger != l {
+ t.Errorf("GetLogger: %#v, want %#v", logger, l)
+ }
+
+ if ds := l.Writer().(*message.Suspendable).Downstream; ds != io.Discard {
+ t.Errorf("GetLogger: Downstream = %#v", ds)
+ }
+ })
+ })
+
+ dw := expectWriter{t: t}
+
+ steps := []struct {
+ name string
+ pt, next []byte
+ err error
+
+ f func(t *testing.T, msg message.Msg)
+ }{
+ {"zero verbose", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.IsVerbose() {
+ t.Error("IsVerbose unexpected true")
+ }
+ }},
+
+ {"swap false", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.SwapVerbose(false) {
+ t.Error("SwapVerbose unexpected true")
+ }
+ }},
+ {"write discard", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Verbose("\x00")
+ msg.Verbosef("\x00")
+ }},
+ {"verbose false", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.IsVerbose() {
+ t.Error("IsVerbose unexpected true")
+ }
+ }},
+
+ {"swap true", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.SwapVerbose(true) {
+ t.Error("SwapVerbose unexpected true")
+ }
+ }},
+ {"write verbose", []byte("test: \x00\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Verbose("\x00")
+ }},
+ {"write verbosef", []byte(`test: "\x00"` + "\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Verbosef("%q", "\x00")
+ }},
+ {"verbose true", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if !msg.IsVerbose() {
+ t.Error("IsVerbose unexpected false")
+ }
+ }},
+
+ {"resume noop", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.Resume() {
+ t.Error("Resume unexpected success")
+ }
+ }},
+ {"beforeExit noop", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.BeforeExit()
+ }},
+
+ {"beforeExit suspend", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Suspend()
+ }},
+ {"beforeExit message", []byte("test: beforeExit reached on suspended output\n"), nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.BeforeExit()
+ }},
+ {"post beforeExit resume noop", nil, nil, nil, func(t *testing.T, msg message.Msg) {
+ if msg.Resume() {
+ t.Error("Resume unexpected success")
+ }
+ }},
+
+ {"suspend", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Suspend()
+ }},
+ {"suspend write", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.GetLogger().Print("\x00")
+ }},
+ {"resume error", []byte("test: \x00\n"), []byte("test: cannot dump buffer on resume: unique error 0 injected by the test suite\n"), stub.UniqueError(0), func(t *testing.T, msg message.Msg) {
+ if !msg.Resume() {
+ t.Error("Resume unexpected failure")
+ }
+ }},
+
+ {"suspend drop", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.Suspend()
+ }},
+ {"suspend write fill", nil, nil, nil, func(_ *testing.T, msg message.Msg) {
+ msg.GetLogger().Print(strings.Repeat("\x00", suspendBufMax))
+ }},
+ {"resume dropped", append([]byte("test: "), bytes.Repeat([]byte{0}, suspendBufMax-6)...), []byte("test: dropped 7 bytes while output is suspended\n"), nil, func(t *testing.T, msg message.Msg) {
+ if !msg.Resume() {
+ t.Error("Resume unexpected failure")
+ }
+ }},
+ }
+
+ msg := message.NewMsg(log.New(&dw, "test: ", 0))
+ for _, step := range steps {
+ // these share the same writer, so cannot be subtests
+ t.Logf("running step %q", step.name)
+ dw.expect, dw.next, dw.err = step.pt, step.next, step.err
+ step.f(t, msg)
+ if dw.expect != nil {
+ t.Errorf("expect: %q", string(dw.expect))
+ }
+ }
+}