aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/msg_test.go
blob: 3c68a50e078f47e73f2276c2caf2d13d88d468c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package container_test

import (
	"log"
	"strings"
	"sync/atomic"
	"testing"

	"hakurei.app/container"
)

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("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) 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") }