Skip to content

Commit 5286b2a

Browse files
committed
cmd/compile: test delve instead of gdb in ssa/debug_test.go
This seems to deflake the test, and also allows testing on macOS. Fixes #31786. Change-Id: I10bfba46dd4b8e64cb09fdd4dd9d175c1ce1f022 Reviewed-on: https://go-review.googlesource.com/c/go/+/176058 Run-TryBot: David Chase <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 0793c81 commit 5286b2a

File tree

1 file changed

+90
-36
lines changed

1 file changed

+90
-36
lines changed

src/cmd/compile/internal/ssa/debug_test.go

Lines changed: 90 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,27 @@ import (
2222
"time"
2323
)
2424

25-
var update = flag.Bool("u", false, "update test reference files")
26-
var verbose = flag.Bool("v", false, "print debugger interactions (very verbose)")
27-
var dryrun = flag.Bool("n", false, "just print the command line and first debugging bits")
28-
var useDelve = flag.Bool("d", false, "use Delve (dlv) instead of gdb, use dlv reverence files")
29-
var force = flag.Bool("f", false, "force run under not linux-amd64; also do not use tempdir")
30-
31-
var repeats = flag.Bool("r", false, "detect repeats in debug steps and don't ignore them")
32-
var inlines = flag.Bool("i", false, "do inlining for gdb (makes testing flaky till inlining info is correct)")
33-
34-
var hexRe = regexp.MustCompile("0x[a-zA-Z0-9]+")
35-
var numRe = regexp.MustCompile("-?[0-9]+")
36-
var stringRe = regexp.MustCompile("\"([^\\\"]|(\\.))*\"")
37-
var leadingDollarNumberRe = regexp.MustCompile("^[$][0-9]+")
38-
var optOutGdbRe = regexp.MustCompile("[<]optimized out[>]")
39-
var numberColonRe = regexp.MustCompile("^ *[0-9]+:")
25+
var (
26+
update = flag.Bool("u", false, "update test reference files")
27+
verbose = flag.Bool("v", false, "print debugger interactions (very verbose)")
28+
dryrun = flag.Bool("n", false, "just print the command line and first debugging bits")
29+
useGdb = flag.Bool("g", false, "use Gdb instead of Delve (dlv), use gdb reference files")
30+
force = flag.Bool("f", false, "force run under not linux-amd64; also do not use tempdir")
31+
repeats = flag.Bool("r", false, "detect repeats in debug steps and don't ignore them")
32+
inlines = flag.Bool("i", false, "do inlining for gdb (makes testing flaky till inlining info is correct)")
33+
)
34+
35+
var (
36+
hexRe = regexp.MustCompile("0x[a-zA-Z0-9]+")
37+
numRe = regexp.MustCompile("-?[0-9]+")
38+
stringRe = regexp.MustCompile("\"([^\\\"]|(\\.))*\"")
39+
leadingDollarNumberRe = regexp.MustCompile("^[$][0-9]+")
40+
optOutGdbRe = regexp.MustCompile("[<]optimized out[>]")
41+
numberColonRe = regexp.MustCompile("^ *[0-9]+:")
42+
)
4043

4144
var gdb = "gdb" // Might be "ggdb" on Darwin, because gdb no longer part of XCode
42-
var debugger = "gdb" // For naming files, etc.
45+
var debugger = "dlv" // For naming files, etc.
4346

4447
var gogcflags = os.Getenv("GO_GCFLAGS")
4548

@@ -98,23 +101,18 @@ func TestNexting(t *testing.T) {
98101
}
99102
testenv.MustHaveGoBuild(t)
100103

101-
if !*useDelve && !*force && !(runtime.GOOS == "linux" && runtime.GOARCH == "amd64") {
104+
if *useGdb && !*force && !(runtime.GOOS == "linux" && runtime.GOARCH == "amd64") {
102105
// Running gdb on OSX/darwin is very flaky.
103106
// Sometimes it is called ggdb, depending on how it is installed.
104107
// It also sometimes requires an admin password typed into a dialog box.
105108
// Various architectures tend to differ slightly sometimes, and keeping them
106109
// all in sync is a pain for people who don't have them all at hand,
107110
// so limit testing to amd64 (for now)
108-
skipReasons += "not run unless linux-amd64 or -d (delve) or -f (force); "
111+
skipReasons += "not run when testing gdb (-g) unless forced (-f) or linux-amd64"
109112
}
110113

111-
if *useDelve {
112-
debugger = "dlv"
113-
_, err := exec.LookPath("dlv")
114-
if err != nil {
115-
skipReasons += "not run because dlv (requested by -d option) not on path; "
116-
}
117-
} else {
114+
if *useGdb {
115+
debugger = "gdb"
118116
_, err := exec.LookPath(gdb)
119117
if err != nil {
120118
if runtime.GOOS != "darwin" {
@@ -123,12 +121,18 @@ func TestNexting(t *testing.T) {
123121
// On Darwin, MacPorts installs gdb as "ggdb".
124122
_, err = exec.LookPath("ggdb")
125123
if err != nil {
126-
skipReasons += "not run because gdb (and also ggdb) not on path; "
124+
skipReasons += "not run because gdb (and also ggdb) request by -g option not on path; "
127125
} else {
128126
gdb = "ggdb"
129127
}
130128
}
131129
}
130+
} else { // Delve
131+
debugger = "dlv"
132+
_, err := exec.LookPath("dlv")
133+
if err != nil {
134+
skipReasons += "not run because dlv not on path; "
135+
}
132136
}
133137

134138
if skipReasons != "" {
@@ -137,14 +141,14 @@ func TestNexting(t *testing.T) {
137141

138142
optFlags := "" // Whatever flags are needed to test debugging of optimized code.
139143
dbgFlags := "-N -l"
140-
if !*useDelve && !*inlines {
144+
if *useGdb && !*inlines {
141145
// For gdb (default), disable inlining so that a compiler test does not depend on library code.
142-
// TODO: Technically not necessary in 1.10, but it causes a largish regression that needs investigation.
146+
// TODO: Technically not necessary in 1.10 and later, but it causes a largish regression that needs investigation.
143147
optFlags += " -l"
144148
}
145149

146150
moreargs := []string{}
147-
if !*useDelve && (runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
151+
if *useGdb && (runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
148152
// gdb and lldb on Darwin do not deal with compressed dwarf.
149153
// also, Windows.
150154
moreargs = append(moreargs, "-ldflags=-compressdwarf=false")
@@ -158,7 +162,12 @@ func TestNexting(t *testing.T) {
158162

159163
optSubTest(t, debugger+"-opt", "hist", optFlags, 1000, moreargs...)
160164
optSubTest(t, debugger+"-opt", "scopes", optFlags, 1000, moreargs...)
161-
optSubTest(t, debugger+"-opt", "infloop", optFlags, 10, moreargs...)
165+
166+
// Was optSubtest, this test is observed flaky on Linux in Docker on (busy) macOS, probably because of timing
167+
// glitches in this harness.
168+
// TODO get rid of timing glitches in this harness.
169+
skipSubTest(t, debugger+"-opt", "infloop", optFlags, 10, moreargs...)
170+
162171
}
163172

164173
// subTest creates a subtest that compiles basename.go with the specified gcflags and additional compiler arguments,
@@ -172,6 +181,17 @@ func subTest(t *testing.T, tag string, basename string, gcflags string, moreargs
172181
})
173182
}
174183

184+
// skipSubTest is the same as subTest except that it skips the test if execution is not forced (-f)
185+
func skipSubTest(t *testing.T, tag string, basename string, gcflags string, count int, moreargs ...string) {
186+
t.Run(tag+"-"+basename, func(t *testing.T) {
187+
if *force {
188+
testNexting(t, basename, tag, gcflags, count, moreargs...)
189+
} else {
190+
t.Skip("skipping flaky test becaused not forced (-f)")
191+
}
192+
})
193+
}
194+
175195
// optSubTest is the same as subTest except that it skips the test if the runtime and libraries
176196
// were not compiled with optimization turned on. (The skip may not be necessary with Go 1.10 and later)
177197
func optSubTest(t *testing.T, tag string, basename string, gcflags string, count int, moreargs ...string) {
@@ -218,10 +238,10 @@ func testNexting(t *testing.T, base, tag, gcflags string, count int, moreArgs ..
218238
nextlog := testbase + ".nexts"
219239
tmplog := tmpbase + ".nexts"
220240
var dbg dbgr
221-
if *useDelve {
222-
dbg = newDelve(tag, exe)
223-
} else {
241+
if *useGdb {
224242
dbg = newGdb(tag, exe)
243+
} else {
244+
dbg = newDelve(tag, exe)
225245
}
226246
h1 := runDbgr(dbg, count)
227247
if *dryrun {
@@ -539,7 +559,7 @@ func (s *delveState) start() {
539559
panic(fmt.Sprintf("There was an error [start] running '%s', %v\n", line, err))
540560
}
541561
s.ioState.readExpecting(-1, 5000, "Type 'help' for list of commands.")
542-
expect("Breakpoint [0-9]+ set at ", s.ioState.writeReadExpect("b main.test\n", "[(]dlv[)] "))
562+
s.ioState.writeReadExpect("b main.test\n", "[(]dlv[)] ")
543563
s.stepnext("c")
544564
}
545565

@@ -598,7 +618,7 @@ func (s *gdbState) start() {
598618
line := asCommandLine("", s.cmd)
599619
panic(fmt.Sprintf("There was an error [start] running '%s', %v\n", line, err))
600620
}
601-
s.ioState.readExpecting(-1, -1, "[(]gdb[)] ")
621+
s.ioState.readSimpleExpecting("[(]gdb[)] ")
602622
x := s.ioState.writeReadExpect("b main.test\n", "[(]gdb[)] ")
603623
expect("Breakpoint [0-9]+ at", x)
604624
s.stepnext(run)
@@ -840,7 +860,7 @@ func (s *ioState) writeReadExpect(ss, expectRE string) tstring {
840860
if err != nil {
841861
panic(fmt.Sprintf("There was an error writing '%s', %v\n", ss, err))
842862
}
843-
return s.readExpecting(-1, -1, expectRE)
863+
return s.readSimpleExpecting(expectRE)
844864
}
845865

846866
func (s *ioState) readExpecting(millis, interlineTimeout int, expectedRE string) tstring {
@@ -887,6 +907,40 @@ loop:
887907
return s.last
888908
}
889909

910+
func (s *ioState) readSimpleExpecting(expectedRE string) tstring {
911+
s.last = tstring{}
912+
var re *regexp.Regexp
913+
if expectedRE != "" {
914+
re = regexp.MustCompile(expectedRE)
915+
}
916+
for {
917+
select {
918+
case x, ok := <-s.outChan:
919+
if !ok {
920+
s.outChan = nil
921+
}
922+
s.last.o += x
923+
case x, ok := <-s.errChan:
924+
if !ok {
925+
s.errChan = nil
926+
}
927+
s.last.e += x
928+
}
929+
if re != nil {
930+
if re.MatchString(s.last.o) {
931+
break
932+
}
933+
if re.MatchString(s.last.e) {
934+
break
935+
}
936+
}
937+
}
938+
if *verbose {
939+
fmt.Printf("<= %s%s", s.last.o, s.last.e)
940+
}
941+
return s.last
942+
}
943+
890944
// replaceEnv returns a new environment derived from env
891945
// by removing any existing definition of ev and adding ev=evv.
892946
func replaceEnv(env []string, ev string, evv string) []string {

0 commit comments

Comments
 (0)