aboutsummaryrefslogtreecommitdiff
path: root/test/run.go
diff options
context:
space:
mode:
authorGiovanni Bajo <rasky@develer.com>2018-03-03 19:44:47 +0100
committerGiovanni Bajo <rasky@develer.com>2018-03-04 01:05:02 +0000
commit80bfb75c429c4930b8ed603592b4c9df82a79240 (patch)
tree4650af9d3f244d95af8884f478bc38bed126e797 /test/run.go
parent8ce74b7d119a74c5882ae88556991f59267cb947 (diff)
downloadgo-80bfb75c429c4930b8ed603592b4c9df82a79240.tar.gz
go-80bfb75c429c4930b8ed603592b4c9df82a79240.zip
test: in asmcheck, dump only the functions which fail
Before this change, in case of any failure, asmcheck was dumping to stderr the whole output of compile -S, which can be very long if it contains multiple functions. Make it so it filters the output to only display the assembly output of functions for which at least one opcode check failed. This greatly simplifies debugging. Change-Id: I1bbf54473b8252a3384e2c1dade82d926afc119d Reviewed-on: https://go-review.googlesource.com/98444 Run-TryBot: Giovanni Bajo <rasky@develer.com> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'test/run.go')
-rw-r--r--test/run.go62
1 files changed, 46 insertions, 16 deletions
diff --git a/test/run.go b/test/run.go
index 36fbd798ab..c992c7e9d1 100644
--- a/test/run.go
+++ b/test/run.go
@@ -1294,10 +1294,11 @@ var (
)
type wantedAsmOpcode struct {
- line int
- opcode *regexp.Regexp
- negative bool
- found bool
+ fileline string // original source file/line (eg: "/path/foo.go:45")
+ line int // original source line
+ opcode *regexp.Regexp // opcode check to be performed on assembly output
+ negative bool // true if the check is supposed to fail rather than pass
+ found bool // true if the opcode check matched at least one in the output
}
func (t *test) wantedAsmOpcodes(fn string) (map[string]map[string][]wantedAsmOpcode, []string) {
@@ -1353,6 +1354,7 @@ func (t *test) wantedAsmOpcodes(fn string) (map[string]map[string][]wantedAsmOpc
archs[arch] = true
ops[arch][lnum] = append(ops[arch][lnum], wantedAsmOpcode{
negative: negative,
+ fileline: lnum,
line: i + 1,
opcode: oprx,
})
@@ -1371,28 +1373,46 @@ func (t *test) wantedAsmOpcodes(fn string) (map[string]map[string][]wantedAsmOpc
}
func (t *test) asmCheck(outStr string, fn string, arch string, fullops map[string][]wantedAsmOpcode) (err error) {
- defer func() {
- if *verbose && err != nil {
- log.Printf("%s gc output:\n%s", t, outStr)
- }
- }()
-
+ // The assembly output contains the concatenated dump of multiple functions.
+ // the first line of each function begins at column 0, while the rest is
+ // indented by a tabulation. These data structures help us index the
+ // output by function.
+ functionMarkers := make([]int, 1)
+ lineFuncMap := make(map[string]int)
+
+ lines := strings.Split(outStr, "\n")
rxLine := regexp.MustCompile(fmt.Sprintf(`\((%s:\d+)\)\s+(.*)`, regexp.QuoteMeta(fn)))
- for _, line := range strings.Split(outStr, "\n") {
+ for nl, line := range lines {
+ // Check if this line begins a function
+ if len(line) > 0 && line[0] != '\t' {
+ functionMarkers = append(functionMarkers, nl)
+ }
+
+ // Search if this line contains a assembly opcode (which is prefixed by the
+ // original source file/line in parenthesis)
matches := rxLine.FindStringSubmatch(line)
if len(matches) == 0 {
continue
}
+ srcFileLine, asm := matches[1], matches[2]
+
+ // Associate the original file/line information to the current
+ // function in the output; it will be useful to dump it in case
+ // of error.
+ lineFuncMap[srcFileLine] = len(functionMarkers) - 1
- ops := fullops[matches[1]]
- asm := matches[2]
- for i := range ops {
- if !ops[i].found && ops[i].opcode.FindString(asm) != "" {
- ops[i].found = true
+ // If there are opcode checks associated to this source file/line,
+ // run the checks.
+ if ops, found := fullops[srcFileLine]; found {
+ for i := range ops {
+ if !ops[i].found && ops[i].opcode.FindString(asm) != "" {
+ ops[i].found = true
+ }
}
}
}
+ functionMarkers = append(functionMarkers, len(lines))
var failed []wantedAsmOpcode
for _, ops := range fullops {
@@ -1413,9 +1433,19 @@ func (t *test) asmCheck(outStr string, fn string, arch string, fullops map[strin
return failed[i].line < failed[j].line
})
+ lastFunction := -1
var errbuf bytes.Buffer
fmt.Fprintln(&errbuf)
for _, o := range failed {
+ // Dump the function in which this opcode check was supposed to
+ // pass but failed.
+ funcIdx := lineFuncMap[o.fileline]
+ if funcIdx != 0 && funcIdx != lastFunction {
+ funcLines := lines[functionMarkers[funcIdx]:functionMarkers[funcIdx+1]]
+ log.Println(strings.Join(funcLines, "\n"))
+ lastFunction = funcIdx // avoid printing same function twice
+ }
+
if o.negative {
fmt.Fprintf(&errbuf, "%s:%d: %s: wrong opcode found: %q\n", t.goFileName(), o.line, arch, o.opcode.String())
} else {