aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ast
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-05-03 14:07:19 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-05-05 14:01:52 +0200
commitc07ad91c6bf086ecf058af733995f8e6a185e967 (patch)
treecbb72e95e63a207199aa7262f963276e250d68ba /pkg/ast
parent577e2c45a7bcaf974ef661442dc4cd52339e8953 (diff)
pkg/ast: improve test output
Improve the test utility to group error messages by line.
Diffstat (limited to 'pkg/ast')
-rw-r--r--pkg/ast/scanner.go22
-rw-r--r--pkg/ast/test_util.go52
2 files changed, 62 insertions, 12 deletions
diff --git a/pkg/ast/scanner.go b/pkg/ast/scanner.go
index 3a6ba9d98..5607e3082 100644
--- a/pkg/ast/scanner.go
+++ b/pkg/ast/scanner.go
@@ -124,10 +124,32 @@ func LoggingHandler(pos Pos, msg string) {
fmt.Fprintf(os.Stderr, "%v: %v\n", pos, msg)
}
+const BuiltinFile = "BUILTINS"
+
+func (pos Pos) Builtin() bool {
+ return pos.File == BuiltinFile
+}
+
func (pos Pos) String() string {
+ if pos.Builtin() {
+ return "builtins"
+ }
+ if pos.Col == 0 {
+ return fmt.Sprintf("%v:%v", pos.File, pos.Line)
+ }
return fmt.Sprintf("%v:%v:%v", pos.File, pos.Line, pos.Col)
}
+func (pos Pos) less(other Pos) bool {
+ if pos.File != other.File {
+ return pos.File < other.File
+ }
+ if pos.Line != other.Line {
+ return pos.Line < other.Line
+ }
+ return pos.Col < other.Col
+}
+
func (s *scanner) Scan() (tok token, lit string, pos Pos) {
s.skipWhitespace()
pos = s.pos()
diff --git a/pkg/ast/test_util.go b/pkg/ast/test_util.go
index 741bed553..697b34505 100644
--- a/pkg/ast/test_util.go
+++ b/pkg/ast/test_util.go
@@ -6,9 +6,11 @@ package ast
import (
"bufio"
"bytes"
+ "fmt"
"io/ioutil"
"path/filepath"
"regexp"
+ "sort"
"strings"
"testing"
)
@@ -21,9 +23,7 @@ type ErrorMatcher struct {
}
type errorDesc struct {
- file string
- line int
- col int
+ pos Pos
text string
matched bool
}
@@ -44,8 +44,7 @@ func NewErrorMatcher(t *testing.T, file string) *ErrorMatcher {
break
}
errors = append(errors, &errorDesc{
- file: filepath.Base(file),
- line: i,
+ pos: Pos{File: filepath.Base(file), Line: i},
text: strings.TrimSpace(string(ln[pos+3:])),
})
ln = ln[:pos]
@@ -70,9 +69,7 @@ func (em *ErrorMatcher) ErrorHandler(pos Pos, msg string) {
msg = msg[0:match[0]] + "at LOCATION" + msg[match[1]:]
}
em.got = append(em.got, &errorDesc{
- file: pos.File,
- line: pos.Line,
- col: pos.Col,
+ pos: pos,
text: msg,
})
}
@@ -82,27 +79,58 @@ func (em *ErrorMatcher) Count() int {
}
func (em *ErrorMatcher) Check() {
+ em.t.Helper()
+ errors := make(map[Pos][]string)
nextErr:
for _, e := range em.got {
for _, want := range em.expect {
- if want.matched || want.line != e.line || want.text != e.text {
+ if want.matched || want.pos.Line != e.pos.Line || want.text != e.text {
continue
}
want.matched = true
continue nextErr
}
- em.t.Errorf("unexpected error:\n%v:%v:%v: %v", e.file, e.line, e.col, e.text)
+ pos := e.pos
+ pos.Col = 0
+ pos.Off = 0
+ errors[pos] = append(errors[pos], fmt.Sprintf("unexpected: %v", e.text))
}
for _, want := range em.expect {
if want.matched {
continue
}
- em.t.Errorf("unmatched error:\n%v:%v: %v", want.file, want.line, want.text)
+ errors[want.pos] = append(errors[want.pos], fmt.Sprintf("unmatched : %v", want.text))
}
+
+ if len(errors) == 0 {
+ return
+ }
+ type Sorted struct {
+ pos Pos
+ msgs []string
+ }
+ sorted := []Sorted{}
+ for pos, msgs := range errors {
+ sorted = append(sorted, Sorted{pos, msgs})
+ }
+ sort.Slice(sorted, func(i, j int) bool {
+ return sorted[i].pos.less(sorted[j].pos)
+ })
+ buf := new(bytes.Buffer)
+ for _, err := range sorted {
+ if len(err.msgs) == 1 {
+ fmt.Fprintf(buf, "%v: %v\n", err.pos, err.msgs[0])
+ continue
+ }
+ sort.Strings(err.msgs)
+ fmt.Fprintf(buf, "%v:\n\t%v\n", err.pos, strings.Join(err.msgs, "\n\t"))
+ }
+ em.t.Errorf("\n%s", buf.Bytes())
}
func (em *ErrorMatcher) DumpErrors() {
+ em.t.Helper()
for _, e := range em.got {
- em.t.Logf("%v:%v:%v: %v", e.file, e.line, e.col, e.text)
+ em.t.Logf("%v: %v", e.pos, e.text)
}
}