diff --git a/assert/assertions.go b/assert/assertions.go index 1419e4776..ec32ac127 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -324,15 +324,20 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) - scanner := bufio.NewScanner(strings.NewReader(message)) - for firstLine := true; scanner.Scan(); firstLine = false { - if !firstLine { - fmt.Fprint(outBuf, "\n\t"+strings.Repeat(" ", longestLabelLen+1)+"\t") + // Splitting manually instead of using bufio.Scanner because the scanner + // errors out on lines longer than bufio.MaxScanTokenSize (64KiB), hiding + // the whole message. See issue #746. + lines := strings.Split(message, "\n") + // Like bufio.ScanLines, ignore the trailing empty line after a final "\n". + if len(lines) > 1 && lines[len(lines)-1] == "" { + lines = lines[:len(lines)-1] + } + for i, line := range lines { + if i != 0 { + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } - fmt.Fprint(outBuf, scanner.Text()) - } - if err := scanner.Err(); err != nil { - return fmt.Sprintf("cannot display message: %s", err) + // Like bufio.ScanLines, treat "\r\n" as a line ending as well. + outBuf.WriteString(strings.TrimSuffix(line, "\r")) } return outBuf.String() diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 11642e096..7cf7fe6f8 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -628,6 +628,29 @@ func TestEqual(t *testing.T) { } } +// Regression test for the issue #746: a diff line longer than +// bufio.MaxScanTokenSize replaced the whole failure message with +// "cannot display message: bufio.Scanner: token too long". +func TestEqualLongDiffLines(t *testing.T) { + t.Parallel() + + mockT := new(mockTestingT) + + longLine := strings.Repeat("a", bufio.MaxScanTokenSize) + Equal(mockT, longLine+"expected", longLine+"actual") + + errorString := mockT.errorString() + if strings.Contains(errorString, "cannot display message") { + t.Errorf("Equal failure message should be displayed, got: %.100q...", errorString) + } + if !strings.Contains(errorString, "--- Expected") { + t.Errorf("Equal failure message should contain the diff, got: %.100q...", errorString) + } + if !strings.Contains(errorString, longLine+"expected") { + t.Errorf("Equal failure message should contain the long expected line, got: %.100q...", errorString) + } +} + func ptr(i int) *int { return &i }