@@ -25,6 +25,7 @@ import (
25
25
"runtime"
26
26
"strconv"
27
27
"strings"
28
+ "sync"
28
29
"sync/atomic"
29
30
"testing"
30
31
"time"
@@ -240,6 +241,70 @@ func TestServer(t *testing.T) {
240
241
t .Fatalf ("expected postgres URL to start with\" postgres://\" , got %q" ,got )
241
242
}
242
243
})
244
+ t .Run ("SpammyLogs" ,func (t * testing.T ) {
245
+ // The purpose of this test is to ensure we don't show excessive logs when the server starts.
246
+ t .Parallel ()
247
+ inv ,cfg := clitest .New (t ,
248
+ "server" ,
249
+ "--in-memory" ,
250
+ "--http-address" ,":0" ,
251
+ "--access-url" ,"http://localhost:3000/" ,
252
+ "--cache-dir" ,t .TempDir (),
253
+ )
254
+ stdoutRW := syncReaderWriter {}
255
+ stderrRW := syncReaderWriter {}
256
+ inv .Stdout = io .MultiWriter (os .Stdout ,& stdoutRW )
257
+ inv .Stderr = io .MultiWriter (os .Stderr ,& stderrRW )
258
+ clitest .Start (t ,inv )
259
+
260
+ // Wait for startup
261
+ _ = waitAccessURL (t ,cfg )
262
+
263
+ // Wait a bit for more logs to be printed.
264
+ time .Sleep (testutil .WaitShort )
265
+
266
+ // Lines containing these strings are printed because we're
267
+ // running the server with a test config. They wouldn't be
268
+ // normally shown to the user, so we'll ignore them.
269
+ ignoreLines := []string {
270
+ "isn't externally reachable" ,
271
+ "install.sh will be unavailable" ,
272
+ "telemetry disabled, unable to notify of security issues" ,
273
+ }
274
+
275
+ countLines := func (fullOutput string )int {
276
+ terminalWidth := 80
277
+ linesByNewline := strings .Split (fullOutput ,"\n " )
278
+ countByWidth := 0
279
+ lineLoop:
280
+ for _ ,line := range linesByNewline {
281
+ for _ ,ignoreLine := range ignoreLines {
282
+ if strings .Contains (line ,ignoreLine ) {
283
+ continue lineLoop
284
+ }
285
+ }
286
+ if line == "" {
287
+ // Empty lines take up one line.
288
+ countByWidth ++
289
+ }else {
290
+ countByWidth += (len (line )+ terminalWidth - 1 )/ terminalWidth
291
+ }
292
+ }
293
+ return countByWidth
294
+ }
295
+
296
+ stdout ,err := io .ReadAll (& stdoutRW )
297
+ if err != nil {
298
+ t .Fatalf ("failed to read stdout: %v" ,err )
299
+ }
300
+ stderr ,err := io .ReadAll (& stderrRW )
301
+ if err != nil {
302
+ t .Fatalf ("failed to read stderr: %v" ,err )
303
+ }
304
+
305
+ numLines := countLines (string (stdout ))+ countLines (string (stderr ))
306
+ require .Less (t ,numLines ,20 )
307
+ })
243
308
244
309
// Validate that a warning is printed that it may not be externally
245
310
// reachable.
@@ -2140,3 +2205,22 @@ func mockTelemetryServer(t *testing.T) (*url.URL, chan *telemetry.Deployment, ch
2140
2205
2141
2206
return serverURL ,deployment ,snapshot
2142
2207
}
2208
+
2209
+ // syncWriter provides a thread-safe io.ReadWriter implementation
2210
+ type syncReaderWriter struct {
2211
+ buf bytes.Buffer
2212
+ mu sync.Mutex
2213
+ }
2214
+
2215
+ func (w * syncReaderWriter )Write (p []byte ) (n int ,err error ) {
2216
+ w .mu .Lock ()
2217
+ defer w .mu .Unlock ()
2218
+ return w .buf .Write (p )
2219
+ }
2220
+
2221
+ func (w * syncReaderWriter )Read (p []byte ) (n int ,err error ) {
2222
+ w .mu .Lock ()
2223
+ defer w .mu .Unlock ()
2224
+
2225
+ return w .buf .Read (p )
2226
+ }