Commit 98443ecd authored by David Chase's avatar David Chase

cmd/compile: clean up debug_test.go

Exercise of preparing a how-to document motivated me to
clean up some of the stupider wonkier bits.  Since this
does not run for test -short, expect no change for trybots,
did pass testing with OSX gdb and a refreshed copy of Delve.

Change-Id: I58edd10599b172c4787ff5f110db078f6c2c81c5
Reviewed-on: https://go-review.googlesource.com/83957
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
parent a4dfb2e5
...@@ -87,6 +87,10 @@ var debugger = "gdb" // For naming files, etc. ...@@ -87,6 +87,10 @@ var debugger = "gdb" // For naming files, etc.
// go test debug_test.go -args -u -d // go test debug_test.go -args -u -d
func TestNexting(t *testing.T) { func TestNexting(t *testing.T) {
gogcflags := os.Getenv("GO_GCFLAGS")
// optimizedLibs usually means "not running in a noopt test builder".
optimizedLibs := (!strings.Contains(gogcflags, "-N") && !strings.Contains(gogcflags, "-l"))
skipReasons := "" // Many possible skip reasons, list all that apply skipReasons := "" // Many possible skip reasons, list all that apply
if testing.Short() { if testing.Short() {
skipReasons = "not run in short mode; " skipReasons = "not run in short mode; "
...@@ -100,7 +104,7 @@ func TestNexting(t *testing.T) { ...@@ -100,7 +104,7 @@ func TestNexting(t *testing.T) {
// Various architectures tend to differ slightly sometimes, and keeping them // Various architectures tend to differ slightly sometimes, and keeping them
// all in sync is a pain for people who don't have them all at hand, // all in sync is a pain for people who don't have them all at hand,
// so limit testing to amd64 (for now) // so limit testing to amd64 (for now)
skipReasons += "not run unless linux-amd64 or -d or -f; " skipReasons += "not run unless linux-amd64 or -d (delve) or -f (force); "
} }
if *useDelve { if *useDelve {
...@@ -115,6 +119,7 @@ func TestNexting(t *testing.T) { ...@@ -115,6 +119,7 @@ func TestNexting(t *testing.T) {
if runtime.GOOS != "darwin" { if runtime.GOOS != "darwin" {
skipReasons += "not run because gdb not on path; " skipReasons += "not run because gdb not on path; "
} else { } else {
// On Darwin, MacPorts installs gdb as "ggdb".
_, err = exec.LookPath("ggdb") _, err = exec.LookPath("ggdb")
if err != nil { if err != nil {
skipReasons += "not run because gdb (and also ggdb) not on path; " skipReasons += "not run because gdb (and also ggdb) not on path; "
...@@ -129,6 +134,12 @@ func TestNexting(t *testing.T) { ...@@ -129,6 +134,12 @@ func TestNexting(t *testing.T) {
t.Skip(skipReasons[:len(skipReasons)-2]) t.Skip(skipReasons[:len(skipReasons)-2])
} }
optFlags := "-dwarflocationlists"
if !*useDelve && !*inlines {
// For gdb (default), disable inlining so that a compiler test does not depend on library code.
optFlags += " -l"
}
t.Run("dbg-"+debugger, func(t *testing.T) { t.Run("dbg-"+debugger, func(t *testing.T) {
testNexting(t, "hist", "dbg", "-N -l") testNexting(t, "hist", "dbg", "-N -l")
}) })
...@@ -138,18 +149,14 @@ func TestNexting(t *testing.T) { ...@@ -138,18 +149,14 @@ func TestNexting(t *testing.T) {
t.Run("dbg-22558-"+debugger, func(t *testing.T) { t.Run("dbg-22558-"+debugger, func(t *testing.T) {
testNexting(t, "i22558", "dbg-22558", "-N -l") testNexting(t, "i22558", "dbg-22558", "-N -l")
}) })
t.Run("opt-"+debugger, func(t *testing.T) { t.Run("opt-"+debugger, func(t *testing.T) {
// If this is test is run with a runtime compiled with -N -l, it is very likely to fail. // If optimized test is run with unoptimized libraries (compiled with -N -l), it is very likely to fail.
// This occurs in the noopt builders (for example). // This occurs in the noopt builders (for example).
if gogcflags := os.Getenv("GO_GCFLAGS"); *force || (!strings.Contains(gogcflags, "-N") && !strings.Contains(gogcflags, "-l")) { if *force || optimizedLibs {
if *useDelve || *inlines { testNexting(t, "hist", "opt", optFlags)
testNexting(t, "hist", "opt", "-dwarflocationlists")
} else {
// For gdb, disable inlining so that a compiler test does not depend on library code.
testNexting(t, "hist", "opt", "-l -dwarflocationlists")
}
} else { } else {
t.Skip("skipping for unoptimized runtime") t.Skip("skipping for unoptimized stdlib/runtime")
} }
}) })
} }
...@@ -183,16 +190,17 @@ func testNexting(t *testing.T, base, tag, gcflags string, moreArgs ...string) { ...@@ -183,16 +190,17 @@ func testNexting(t *testing.T, base, tag, gcflags string, moreArgs ...string) {
runGo(t, "", runGoArgs...) runGo(t, "", runGoArgs...)
var h1 *nextHist
nextlog := logbase + "-" + debugger + ".nexts" nextlog := logbase + "-" + debugger + ".nexts"
tmplog := tmpbase + "-" + debugger + ".nexts" tmplog := tmpbase + "-" + debugger + ".nexts"
var dbg dbgr
if *useDelve { if *useDelve {
h1 = dlvTest(tag, exe, 1000) dbg = newDelve(tag, exe)
} else { } else {
h1 = gdbTest(tag, exe, 1000) dbg = newGdb(tag, exe)
} }
h1 := runDbgr(dbg, 1000)
if *dryrun { if *dryrun {
fmt.Printf("# Tag for above is %s\n", tag) fmt.Printf("# Tag for above is %s\n", dbg.tag())
return return
} }
if *update { if *update {
...@@ -219,27 +227,10 @@ type dbgr interface { ...@@ -219,27 +227,10 @@ type dbgr interface {
stepnext(s string) bool // step or next, possible with parameter, gets line etc. returns true for success, false for unsure response stepnext(s string) bool // step or next, possible with parameter, gets line etc. returns true for success, false for unsure response
quit() quit()
hist() *nextHist hist() *nextHist
tag() string
} }
// gdbTest runs the debugger test with gdb and returns the history func runDbgr(dbg dbgr, maxNext int) *nextHist {
func gdbTest(tag, executable string, maxNext int, args ...string) *nextHist {
dbg := newGdb(tag, executable, args...)
dbg.start()
if *dryrun {
return nil
}
for i := 0; i < maxNext; i++ {
if !dbg.stepnext("n") {
break
}
}
h := dbg.hist()
return h
}
// dlvTest runs the debugger test with dlv and returns the history
func dlvTest(tag, executable string, maxNext int, args ...string) *nextHist {
dbg := newDelve(tag, executable, args...)
dbg.start() dbg.start()
if *dryrun { if *dryrun {
return nil return nil
...@@ -446,7 +437,7 @@ func canonFileName(f string) string { ...@@ -446,7 +437,7 @@ func canonFileName(f string) string {
type delveState struct { type delveState struct {
cmd *exec.Cmd cmd *exec.Cmd
tag string tagg string
*ioState *ioState
atLineRe *regexp.Regexp // "\n =>" atLineRe *regexp.Regexp // "\n =>"
funcFileLinePCre *regexp.Regexp // "^> ([^ ]+) ([^:]+):([0-9]+) .*[(]PC: (0x[a-z0-9]+)" funcFileLinePCre *regexp.Regexp // "^> ([^ ]+) ([^:]+):([0-9]+) .*[(]PC: (0x[a-z0-9]+)"
...@@ -462,7 +453,7 @@ func newDelve(tag, executable string, args ...string) dbgr { ...@@ -462,7 +453,7 @@ func newDelve(tag, executable string, args ...string) dbgr {
cmd.Args = append(cmd.Args, "--") cmd.Args = append(cmd.Args, "--")
cmd.Args = append(cmd.Args, args...) cmd.Args = append(cmd.Args, args...)
} }
s := &delveState{tag: tag, cmd: cmd} s := &delveState{tagg: tag, cmd: cmd}
// HAHA Delve has control characters embedded to change the color of the => and the line number // HAHA Delve has control characters embedded to change the color of the => and the line number
// that would be '(\\x1b\\[[0-9;]+m)?' OR TERM=dumb // that would be '(\\x1b\\[[0-9;]+m)?' OR TERM=dumb
s.atLineRe = regexp.MustCompile("\n=>[[:space:]]+[0-9]+:(.*)") s.atLineRe = regexp.MustCompile("\n=>[[:space:]]+[0-9]+:(.*)")
...@@ -471,6 +462,10 @@ func newDelve(tag, executable string, args ...string) dbgr { ...@@ -471,6 +462,10 @@ func newDelve(tag, executable string, args ...string) dbgr {
return s return s
} }
func (s *delveState) tag() string {
return "dlv-" + s.tagg
}
func (s *delveState) stepnext(ss string) bool { func (s *delveState) stepnext(ss string) bool {
x := s.ioState.writeReadExpect(ss+"\n", "[(]dlv[)] ") x := s.ioState.writeReadExpect(ss+"\n", "[(]dlv[)] ")
excerpts := s.atLineRe.FindStringSubmatch(x.o) excerpts := s.atLineRe.FindStringSubmatch(x.o)
...@@ -526,7 +521,7 @@ func (s *delveState) quit() { ...@@ -526,7 +521,7 @@ func (s *delveState) quit() {
type gdbState struct { type gdbState struct {
cmd *exec.Cmd cmd *exec.Cmd
tag string tagg string
args []string args []string
*ioState *ioState
atLineRe *regexp.Regexp atLineRe *regexp.Regexp
...@@ -540,7 +535,7 @@ func newGdb(tag, executable string, args ...string) dbgr { ...@@ -540,7 +535,7 @@ func newGdb(tag, executable string, args ...string) dbgr {
// Turn off shell, necessary for Darwin apparently // Turn off shell, necessary for Darwin apparently
cmd := exec.Command(gdb, "-ex", "set startup-with-shell off", executable) cmd := exec.Command(gdb, "-ex", "set startup-with-shell off", executable)
cmd.Env = replaceEnv(cmd.Env, "TERM", "dumb") cmd.Env = replaceEnv(cmd.Env, "TERM", "dumb")
s := &gdbState{tag: tag, cmd: cmd, args: args} s := &gdbState{tagg: tag, cmd: cmd, args: args}
s.atLineRe = regexp.MustCompile("(^|\n)([0-9]+)(.*)") s.atLineRe = regexp.MustCompile("(^|\n)([0-9]+)(.*)")
s.funcFileLinePCre = regexp.MustCompile( s.funcFileLinePCre = regexp.MustCompile(
"([^ ]+) [(][^)]*[)][ \\t\\n]+at ([^:]+):([0-9]+)") "([^ ]+) [(][^)]*[)][ \\t\\n]+at ([^:]+):([0-9]+)")
...@@ -551,6 +546,10 @@ func newGdb(tag, executable string, args ...string) dbgr { ...@@ -551,6 +546,10 @@ func newGdb(tag, executable string, args ...string) dbgr {
return s return s
} }
func (s *gdbState) tag() string {
return "gdb-" + s.tagg
}
func (s *gdbState) start() { func (s *gdbState) start() {
run := "run" run := "run"
for _, a := range s.args { for _, a := range s.args {
...@@ -614,7 +613,7 @@ func (s *gdbState) stepnext(ss string) bool { ...@@ -614,7 +613,7 @@ func (s *gdbState) stepnext(ss string) bool {
return true return true
} }
// Look for //gdb-<tag>=(v1,v2,v3) and print v1, v2, v3 // Look for //gdb-<tag>=(v1,v2,v3) and print v1, v2, v3
vars := varsToPrint(excerpt, "//gdb-"+s.tag+"=(") vars := varsToPrint(excerpt, "//"+s.tag()+"=(")
for _, v := range vars { for _, v := range vars {
slashIndex := strings.Index(v, "/") slashIndex := strings.Index(v, "/")
substitutions := "" substitutions := ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment