All checks were successful
Test / Create distribution (push) Successful in 1m10s
Test / Sandbox (push) Successful in 2m40s
Test / Hakurei (push) Successful in 3m58s
Test / Hpkg (push) Successful in 4m44s
Test / Sandbox (race detector) (push) Successful in 5m1s
Test / Hakurei (race detector) (push) Successful in 6m2s
Test / Flake checks (push) Successful in 1m47s
This frees all container instances of side effects. Signed-off-by: Ophestra <cat@gensokyo.uk>
178 lines
4.8 KiB
Go
178 lines
4.8 KiB
Go
package container_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"strings"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"hakurei.app/container"
|
|
"hakurei.app/container/stub"
|
|
)
|
|
|
|
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 := container.GetErrorMessage(tc.err)
|
|
if got != tc.want {
|
|
t.Errorf("GetErrorMessage: %q, want %q", got, tc.want)
|
|
}
|
|
if ok != tc.wantOk {
|
|
t.Errorf("GetErrorMessage: 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 := container.NewMsg(nil).GetLogger()
|
|
|
|
if out := got.Writer().(*container.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 := container.NewMsg(l)
|
|
|
|
if logger := got.GetLogger(); logger != l {
|
|
t.Errorf("GetLogger: %#v, want %#v", logger, l)
|
|
}
|
|
|
|
if ds := l.Writer().(*container.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 container.Msg)
|
|
}{
|
|
{"zero verbose", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.IsVerbose() {
|
|
t.Error("IsVerbose unexpected true")
|
|
}
|
|
}},
|
|
|
|
{"swap false", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.SwapVerbose(false) {
|
|
t.Error("SwapVerbose unexpected true")
|
|
}
|
|
}},
|
|
{"write discard", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Verbose("\x00")
|
|
msg.Verbosef("\x00")
|
|
}},
|
|
{"verbose false", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.IsVerbose() {
|
|
t.Error("IsVerbose unexpected true")
|
|
}
|
|
}},
|
|
|
|
{"swap true", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.SwapVerbose(true) {
|
|
t.Error("SwapVerbose unexpected true")
|
|
}
|
|
}},
|
|
{"write verbose", []byte("test: \x00\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Verbose("\x00")
|
|
}},
|
|
{"write verbosef", []byte(`test: "\x00"` + "\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Verbosef("%q", "\x00")
|
|
}},
|
|
{"verbose true", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if !msg.IsVerbose() {
|
|
t.Error("IsVerbose unexpected false")
|
|
}
|
|
}},
|
|
|
|
{"resume noop", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.Resume() {
|
|
t.Error("Resume unexpected success")
|
|
}
|
|
}},
|
|
{"beforeExit noop", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.BeforeExit()
|
|
}},
|
|
|
|
{"beforeExit suspend", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Suspend()
|
|
}},
|
|
{"beforeExit message", []byte("test: beforeExit reached on suspended output\n"), nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.BeforeExit()
|
|
}},
|
|
{"post beforeExit resume noop", nil, nil, nil, func(t *testing.T, msg container.Msg) {
|
|
if msg.Resume() {
|
|
t.Error("Resume unexpected success")
|
|
}
|
|
}},
|
|
|
|
{"suspend", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Suspend()
|
|
}},
|
|
{"suspend write", nil, nil, nil, func(_ *testing.T, msg container.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 container.Msg) {
|
|
if !msg.Resume() {
|
|
t.Error("Resume unexpected failure")
|
|
}
|
|
}},
|
|
|
|
{"suspend drop", nil, nil, nil, func(_ *testing.T, msg container.Msg) {
|
|
msg.Suspend()
|
|
}},
|
|
{"suspend write fill", nil, nil, nil, func(_ *testing.T, msg container.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 container.Msg) {
|
|
if !msg.Resume() {
|
|
t.Error("Resume unexpected failure")
|
|
}
|
|
}},
|
|
}
|
|
|
|
msg := container.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))
|
|
}
|
|
}
|
|
}
|