Commit dd78f745 authored by Rémy Oudompheng's avatar Rémy Oudompheng

testing: fix memory blowup when formatting many lines.

Fixes #3830.

R=golang-dev, r
CC=golang-dev, remy
https://golang.org/cl/6373047
parent f49b7b0a
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
package testing package testing
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"os" "os"
...@@ -128,37 +129,42 @@ func Short() bool { ...@@ -128,37 +129,42 @@ func Short() bool {
return *short return *short
} }
// decorate inserts the final newline if needed and indentation tabs for formatting. // decorate prefixes the string with the file and line of the call site
// If addFileLine is true, it also prefixes the string with the file and line of the call site. // and inserts the final newline if needed and indentation tabs for formatting.
func decorate(s string, addFileLine bool) string { func decorate(s string) string {
if addFileLine { _, file, line, ok := runtime.Caller(3) // decorate + log + public function.
_, file, line, ok := runtime.Caller(3) // decorate + log + public function. if ok {
if ok { // Truncate file name at last file name separator.
// Truncate file name at last file name separator. if index := strings.LastIndex(file, "/"); index >= 0 {
if index := strings.LastIndex(file, "/"); index >= 0 { file = file[index+1:]
file = file[index+1:] } else if index = strings.LastIndex(file, "\\"); index >= 0 {
} else if index = strings.LastIndex(file, "\\"); index >= 0 { file = file[index+1:]
file = file[index+1:]
}
} else {
file = "???"
line = 1
} }
s = fmt.Sprintf("%s:%d: %s", file, line, s) } else {
} file = "???"
s = "\t" + s // Every line is indented at least one tab. line = 1
n := len(s)
if n > 0 && s[n-1] != '\n' {
s += "\n"
n++
} }
for i := 0; i < n-1; i++ { // -1 to avoid final newline buf := new(bytes.Buffer)
if s[i] == '\n' { fmt.Fprintf(buf, "%s:%d: ", file, line)
lines := strings.Split(s, "\n")
for i, line := range lines {
if i > 0 {
buf.WriteByte('\n')
}
// Every line is indented at least one tab.
buf.WriteByte('\t')
if i > 0 {
// Second and subsequent lines are indented an extra tab. // Second and subsequent lines are indented an extra tab.
return s[0:i+1] + "\t" + decorate(s[i+1:n], false) buf.WriteByte('\t')
} }
buf.WriteString(line)
}
if l := len(s); l > 0 && s[len(s)-1] != '\n' {
// Add final new line if needed.
buf.WriteByte('\n')
} }
return s return buf.String()
} }
// T is a type passed to Test functions to manage test state and support formatted test logs. // T is a type passed to Test functions to manage test state and support formatted test logs.
...@@ -204,7 +210,7 @@ func (c *common) FailNow() { ...@@ -204,7 +210,7 @@ func (c *common) FailNow() {
// log generates the output. It's always at the same stack depth. // log generates the output. It's always at the same stack depth.
func (c *common) log(s string) { func (c *common) log(s string) {
c.output = append(c.output, decorate(s, true)...) c.output = append(c.output, decorate(s)...)
} }
// Log formats its arguments using default formatting, analogous to Println(), // Log formats its arguments using default formatting, analogous to Println(),
......
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