1 package cmdlog_test
2
3 import (
4 "bytes"
5 "context"
6 "fmt"
7 "io"
8 "testing"
9 "time"
10
11 "github.com/creack/pty"
12
13 "oss.terrastruct.com/util-go/assert"
14 "oss.terrastruct.com/util-go/cmdlog"
15 "oss.terrastruct.com/util-go/xos"
16 )
17
18 func TestLogger(t *testing.T) {
19 t.Parallel()
20
21 var tca = []struct {
22 name string
23 run func(t *testing.T, ctx context.Context, env *xos.Env)
24 }{
25 {
26 name: "COLOR=1",
27 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
28 b := &bytes.Buffer{}
29 env.Setenv("COLOR", "1")
30 l := cmdlog.New(env, b)
31
32 testLogger(l)
33
34 t.Log(b.String())
35 assert.TestdataJSON(t, b.String())
36 },
37 },
38 {
39 name: "COLOR=",
40 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
41 b := &bytes.Buffer{}
42 l := cmdlog.New(env, b)
43
44 testLogger(l)
45
46 t.Log(b.String())
47 assert.TestdataJSON(t, b.String())
48 },
49 },
50 {
51 name: "tty",
52 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
53 ptmx, tty, err := pty.Open()
54 if err != nil {
55 t.Fatalf("failed to open pty: %v", err)
56 }
57 defer assert.Close(t, ptmx)
58 defer assert.Close(t, tty)
59
60 l := cmdlog.New(env, tty)
61 testLogger(l)
62
63 timer := time.AfterFunc(time.Second*5, func() {
64
65
66 tty.Close()
67 t.Error("read took too long, update expLen")
68 })
69 defer timer.Stop()
70
71
72 const expLen = 415
73 out, err := io.ReadAll(io.LimitReader(ptmx, expLen))
74 if err != nil {
75 t.Fatalf("failed to read log output: %v", err)
76 }
77 t.Log(len(out), string(out))
78 assert.TestdataJSON(t, string(out))
79 },
80 },
81 {
82 name: "testing.TB",
83 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
84 ft := &fakeTB{
85 TB: t,
86 logf: func(f string, v ...interface{}) {
87 t.Helper()
88 assert.String(t, "info: what's up\n", fmt.Sprintf(f, v...))
89 },
90 }
91
92 env.Setenv("COLOR", "0")
93 l := cmdlog.NewTB(env, ft)
94 l.Info.Printf("what's up")
95 },
96 },
97 {
98 name: "WithPrefix",
99 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
100 b := &bytes.Buffer{}
101 env.Setenv("COLOR", "1")
102 l := cmdlog.New(env, b)
103
104 l2 := l.WithCCPrefix("lochness")
105 if l2 == l {
106 t.Fatalf("expected l and l2 to be different loggers")
107 }
108 l2 = l2.WithCCPrefix("imgbundler")
109 l2 = l2.WithCCPrefix("cache")
110
111 testLogger(l)
112 testLogger(l2)
113
114 t.Log(b.String())
115 assert.TestdataJSON(t, b.String())
116 },
117 },
118 {
119 name: "multiline",
120 run: func(t *testing.T, ctx context.Context, env *xos.Env) {
121 b := &bytes.Buffer{}
122 env.Setenv("COLOR", "1")
123 l := cmdlog.New(env, b)
124
125 l.NoLevel.Print("")
126 l.SetTS(true)
127 l.NoLevel.Print("")
128 l.SetTS(false)
129
130 l2 := l.WithCCPrefix("lochness")
131 l2 = l2.WithCCPrefix("imgbundler")
132 l2 = l2.WithCCPrefix("cache")
133
134 l2.Warn.Print(``)
135 l2.Warn.Print("\n\n\n")
136 l2.SetTS(true)
137 l2.Warn.Printf(`yes %d
138 yes %d`, 3, 4)
139
140 t.Log(b.String())
141 assert.TestdataJSON(t, b.String())
142 },
143 },
144 }
145
146 ctx := context.Background()
147 for _, tc := range tca {
148 tc := tc
149 t.Run(tc.name, func(t *testing.T) {
150 t.Parallel()
151
152 ctx, cancel := context.WithCancel(ctx)
153 defer cancel()
154
155 env := xos.NewEnv(nil)
156 tc.run(t, ctx, env)
157 })
158 }
159 }
160
161 func testLogger(l *cmdlog.Logger) {
162 l.NoLevel.Println("Somehow, the world always affects you more than you affect it.")
163
164 l.SetDebug(true)
165 l.Debug.Println("Man is a rational animal who always loses his temper when he is called upon.")
166
167 l.SetDebug(false)
168 l.Debug.Println("You can never trust a woman; she may be true to you.")
169
170 l.SetTS(true)
171 l.Success.Println("An alcoholic is someone you don't like who drinks as much as you do.")
172 l.Info.Println("There once was this swami who lived above a delicatessan.")
173
174 l.SetTSFormat(time.UnixDate)
175 l.Warn.Println("Telephone books are like dictionaries -- if you know the answer before.")
176
177 l.SetTS(false)
178 l.Error.Println("Nothing can be done in one trip.")
179 l.Error.Println(`Good day to let down old friends who need help.
180 I believe in getting into hot water; it keeps you clean.`)
181 }
182
183 type fakeTB struct {
184 testing.TB
185 logf func(string, ...interface{})
186 }
187
188 func (ftb *fakeTB) Logf(f string, v ...interface{}) {
189 ftb.TB.Helper()
190 ftb.logf(f, v...)
191 }
192
View as plain text