1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // TODO(austin): All of these tests are skipped if the debuglog build
6 // tag isn't provided. That means we basically never test debuglog.
7 // There are two potential ways around this:
9 // 1. Make these tests re-build the runtime test with the debuglog
10 // build tag and re-invoke themselves.
12 // 2. Always build the whole debuglog infrastructure and depend on
13 // linker dead-code elimination to drop it. This is easy for dlog()
14 // since there won't be any calls to it. For printDebugLog, we can
15 // make panic call a wrapper that is call printDebugLog if the
16 // debuglog build tag is set, or otherwise do nothing. Then tests
17 // could call printDebugLog directly. This is the right answer in
18 // principle, but currently our linker reads in all symbols
19 // regardless, so this would slow down and bloat all links. If the
20 // linker gets more efficient about this, we should revisit this
36 func skipDebugLog(t
*testing
.T
) {
37 if !runtime
.DlogEnabled
{
38 t
.Skip("debug log disabled (rebuild with -tags debuglog)")
42 func dlogCanonicalize(x
string) string {
43 begin
:= regexp
.MustCompile(`(?m)^>> begin log \d+ <<\n`)
44 x
= begin
.ReplaceAllString(x
, "")
45 prefix
:= regexp
.MustCompile(`(?m)^\[[^]]+\]`)
46 x
= prefix
.ReplaceAllString(x
, "[]")
50 func TestDebugLog(t
*testing
.T
) {
52 runtime
.ResetDebugLog()
53 runtime
.Dlog().S("testing").End()
54 got
:= dlogCanonicalize(runtime
.DumpDebugLog())
55 if want
:= "[] testing\n"; got
!= want
{
56 t
.Fatalf("want %q, got %q", want
, got
)
60 func TestDebugLogTypes(t
*testing
.T
) {
62 runtime
.ResetDebugLog()
63 var varString
= strings
.Repeat("a", 4)
64 runtime
.Dlog().B(true).B(false).I(-42).I16(0x7fff).U64(^uint64(0)).Hex(0xfff).P(nil).S(varString
).S("const string").End()
65 got
:= dlogCanonicalize(runtime
.DumpDebugLog())
66 if want
:= "[] true false -42 32767 18446744073709551615 0xfff 0x0 aaaa const string\n"; got
!= want
{
67 t
.Fatalf("want %q, got %q", want
, got
)
71 func TestDebugLogSym(t
*testing
.T
) {
73 runtime
.ResetDebugLog()
74 pc
, _
, _
, _
:= runtime
.Caller(0)
75 runtime
.Dlog().PC(pc
).End()
76 got
:= dlogCanonicalize(runtime
.DumpDebugLog())
77 want
:= regexp
.MustCompile(`\[\] 0x[0-9a-f]+ \[runtime_test\.TestDebugLogSym\+0x[0-9a-f]+ .*/debuglog_test\.go:[0-9]+\]\n`)
78 if !want
.MatchString(got
) {
79 t
.Fatalf("want matching %s, got %q", want
, got
)
83 func TestDebugLogInterleaving(t
*testing
.T
) {
85 runtime
.ResetDebugLog()
90 // Encourage main goroutine to move around to
91 // different Ms and Ps.
92 for atomic
.LoadInt32(&done
) == 0 {
98 for i
:= 0; i
< 1000; i
++ {
99 runtime
.Dlog().I(i
).End()
100 fmt
.Fprintf(&want
, "[] %d\n", i
)
103 atomic
.StoreInt32(&done
, 1)
106 gotFull
:= runtime
.DumpDebugLog()
107 got
:= dlogCanonicalize(gotFull
)
108 if got
!= want
.String() {
109 // Since the timestamps are useful in understand
110 // failures of this test, we print the uncanonicalized
112 t
.Fatalf("want %q, got (uncanonicalized) %q", want
.String(), gotFull
)
116 func TestDebugLogWraparound(t
*testing
.T
) {
119 // Make sure we don't switch logs so it's easier to fill one up.
120 runtime
.LockOSThread()
121 defer runtime
.UnlockOSThread()
123 runtime
.ResetDebugLog()
124 var longString
= strings
.Repeat("a", 128)
125 var want bytes
.Buffer
126 for i
, j
:= 0, 0; j
< 2*runtime
.DebugLogBytes
; i
, j
= i
+1, j
+len(longString
) {
127 runtime
.Dlog().I(i
).S(longString
).End()
128 fmt
.Fprintf(&want
, "[] %d %s\n", i
, longString
)
130 log
:= runtime
.DumpDebugLog()
132 // Check for "lost" message.
133 lost
:= regexp
.MustCompile(`^>> begin log \d+; lost first \d+KB <<\n`)
134 if !lost
.MatchString(log
) {
135 t
.Fatalf("want matching %s, got %q", lost
, log
)
137 idx
:= lost
.FindStringIndex(log
)
138 // Strip lost message.
139 log
= dlogCanonicalize(log
[idx
[1]:])
142 if !strings
.HasSuffix(want
.String(), log
) {
143 t
.Fatalf("wrong suffix:\n%s", log
)
147 func TestDebugLogLongString(t
*testing
.T
) {
150 runtime
.ResetDebugLog()
151 var longString
= strings
.Repeat("a", runtime
.DebugLogStringLimit
+1)
152 runtime
.Dlog().S(longString
).End()
153 got
:= dlogCanonicalize(runtime
.DumpDebugLog())
154 want
:= "[] " + strings
.Repeat("a", runtime
.DebugLogStringLimit
) + " ..(1 more bytes)..\n"
156 t
.Fatalf("want %q, got %q", want
, got
)