mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
testing: fix memory blowup when formatting many lines.
Fixes #3830. R=golang-dev, r CC=golang-dev, remy https://golang.org/cl/6373047
This commit is contained in:
parent
f49b7b0acf
commit
dd78f745c4
1 changed files with 33 additions and 27 deletions
|
|
@ -79,6 +79,7 @@
|
||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -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 = "???"
|
||||||
|
line = 1
|
||||||
}
|
}
|
||||||
s = "\t" + s // Every line is indented at least one tab.
|
buf := new(bytes.Buffer)
|
||||||
n := len(s)
|
fmt.Fprintf(buf, "%s:%d: ", file, line)
|
||||||
if n > 0 && s[n-1] != '\n' {
|
|
||||||
s += "\n"
|
lines := strings.Split(s, "\n")
|
||||||
n++
|
for i, line := range lines {
|
||||||
}
|
if i > 0 {
|
||||||
for i := 0; i < n-1; i++ { // -1 to avoid final newline
|
buf.WriteByte('\n')
|
||||||
if s[i] == '\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)
|
||||||
}
|
}
|
||||||
return s
|
if l := len(s); l > 0 && s[len(s)-1] != '\n' {
|
||||||
|
// Add final new line if needed.
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
|
||||||
// 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(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue