libgo: Update to weekly.2011-12-22.
From-SVN: r183150
This commit is contained in:
parent
f83fa0bf8f
commit
df4aa89a5e
195 changed files with 3634 additions and 1287 deletions
|
@ -25,12 +25,12 @@ type InternalBenchmark struct {
|
|||
// B is a type passed to Benchmark functions to manage benchmark
|
||||
// timing and to specify the number of iterations to run.
|
||||
type B struct {
|
||||
common
|
||||
N int
|
||||
benchmark InternalBenchmark
|
||||
ns time.Duration
|
||||
bytes int64
|
||||
start time.Time
|
||||
timerOn bool
|
||||
result BenchmarkResult
|
||||
}
|
||||
|
||||
// StartTimer starts timing a test. This function is called automatically
|
||||
|
@ -48,7 +48,7 @@ func (b *B) StartTimer() {
|
|||
// want to measure.
|
||||
func (b *B) StopTimer() {
|
||||
if b.timerOn {
|
||||
b.ns += time.Now().Sub(b.start)
|
||||
b.duration += time.Now().Sub(b.start)
|
||||
b.timerOn = false
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func (b *B) ResetTimer() {
|
|||
if b.timerOn {
|
||||
b.start = time.Now()
|
||||
}
|
||||
b.ns = 0
|
||||
b.duration = 0
|
||||
}
|
||||
|
||||
// SetBytes records the number of bytes processed in a single operation.
|
||||
|
@ -70,7 +70,7 @@ func (b *B) nsPerOp() int64 {
|
|||
if b.N <= 0 {
|
||||
return 0
|
||||
}
|
||||
return b.ns.Nanoseconds() / int64(b.N)
|
||||
return b.duration.Nanoseconds() / int64(b.N)
|
||||
}
|
||||
|
||||
// runN runs a single benchmark for the specified number of iterations.
|
||||
|
@ -127,17 +127,25 @@ func roundUp(n int) int {
|
|||
return 10 * base
|
||||
}
|
||||
|
||||
// run times the benchmark function. It gradually increases the number
|
||||
// run times the benchmark function in a separate goroutine.
|
||||
func (b *B) run() BenchmarkResult {
|
||||
go b.launch()
|
||||
<-b.signal
|
||||
return b.result
|
||||
}
|
||||
|
||||
// launch launches the benchmark function. It gradually increases the number
|
||||
// of benchmark iterations until the benchmark runs for a second in order
|
||||
// to get a reasonable measurement. It prints timing information in this form
|
||||
// testing.BenchmarkHello 100000 19 ns/op
|
||||
func (b *B) run() BenchmarkResult {
|
||||
// launch is run by the fun function as a separate goroutine.
|
||||
func (b *B) launch() {
|
||||
// Run the benchmark for a single iteration in case it's expensive.
|
||||
n := 1
|
||||
b.runN(n)
|
||||
// Run the benchmark for at least the specified amount of time.
|
||||
d := time.Duration(*benchTime * float64(time.Second))
|
||||
for b.ns < d && n < 1e9 {
|
||||
for !b.failed && b.duration < d && n < 1e9 {
|
||||
last := n
|
||||
// Predict iterations/sec.
|
||||
if b.nsPerOp() == 0 {
|
||||
|
@ -153,7 +161,8 @@ func (b *B) run() BenchmarkResult {
|
|||
n = roundUp(n)
|
||||
b.runN(n)
|
||||
}
|
||||
return BenchmarkResult{b.N, b.ns, b.bytes}
|
||||
b.result = BenchmarkResult{b.N, b.duration, b.bytes}
|
||||
b.signal <- b
|
||||
}
|
||||
|
||||
// The results of a benchmark run.
|
||||
|
@ -215,14 +224,32 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
|
|||
}
|
||||
for _, procs := range cpuList {
|
||||
runtime.GOMAXPROCS(procs)
|
||||
b := &B{benchmark: Benchmark}
|
||||
b := &B{
|
||||
common: common{
|
||||
signal: make(chan interface{}),
|
||||
},
|
||||
benchmark: Benchmark,
|
||||
}
|
||||
benchName := Benchmark.Name
|
||||
if procs != 1 {
|
||||
benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
|
||||
}
|
||||
fmt.Printf("%s\t", benchName)
|
||||
r := b.run()
|
||||
if b.failed {
|
||||
// The output could be very long here, but probably isn't.
|
||||
// We print it all, regardless, because we don't want to trim the reason
|
||||
// the benchmark failed.
|
||||
fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%v\n", r)
|
||||
// Unlike with tests, we ignore the -chatty flag and always print output for
|
||||
// benchmarks since the output generation time will skew the results.
|
||||
if len(b.output) > 0 {
|
||||
b.trimOutput()
|
||||
fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
|
||||
}
|
||||
if p := runtime.GOMAXPROCS(-1); p != procs {
|
||||
fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
|
||||
}
|
||||
|
@ -230,9 +257,31 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
|
|||
}
|
||||
}
|
||||
|
||||
// trimOutput shortens the output from a benchmark, which can be very long.
|
||||
func (b *B) trimOutput() {
|
||||
// The output is likely to appear multiple times because the benchmark
|
||||
// is run multiple times, but at least it will be seen. This is not a big deal
|
||||
// because benchmarks rarely print, but just in case, we trim it if it's too long.
|
||||
const maxNewlines = 10
|
||||
for nlCount, j := 0, 0; j < len(b.output); j++ {
|
||||
if b.output[j] == '\n' {
|
||||
nlCount++
|
||||
if nlCount >= maxNewlines {
|
||||
b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark benchmarks a single function. Useful for creating
|
||||
// custom benchmarks that do not use gotest.
|
||||
func Benchmark(f func(b *B)) BenchmarkResult {
|
||||
b := &B{benchmark: InternalBenchmark{"", f}}
|
||||
b := &B{
|
||||
common: common{
|
||||
signal: make(chan interface{}),
|
||||
},
|
||||
benchmark: InternalBenchmark{"", f},
|
||||
}
|
||||
return b.run()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -67,11 +68,9 @@ func RunExamples(examples []InternalExample) (ok bool) {
|
|||
|
||||
// report any errors
|
||||
tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds())
|
||||
if out != eg.Output {
|
||||
fmt.Printf(
|
||||
"--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
|
||||
eg.Name, tstr, out, eg.Output,
|
||||
)
|
||||
if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e {
|
||||
fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n",
|
||||
eg.Name, tstr, g, e)
|
||||
ok = false
|
||||
} else if *chatty {
|
||||
fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr)
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
// }
|
||||
// The benchmark package will vary b.N until the benchmark function lasts
|
||||
// long enough to be timed reliably. The output
|
||||
// testing.BenchmarkHello 500000 4076 ns/op
|
||||
// means that the loop ran 500000 times at a speed of 4076 ns per loop.
|
||||
// testing.BenchmarkHello 10000000 282 ns/op
|
||||
// means that the loop ran 10000000 times at a speed of 282 ns per loop.
|
||||
//
|
||||
// If a benchmark needs some expensive setup before running, the timer
|
||||
// may be stopped:
|
||||
|
@ -70,6 +70,17 @@ var (
|
|||
cpuList []int
|
||||
)
|
||||
|
||||
// common holds the elements common between T and B and
|
||||
// captures common methods such as Errorf.
|
||||
type common struct {
|
||||
output []byte // Output generated by test or benchmark.
|
||||
failed bool // Test or benchmark has failed.
|
||||
start time.Time // Time test or benchmark started
|
||||
duration time.Duration
|
||||
self interface{} // To be sent on signal channel when done.
|
||||
signal chan interface{} // Output for serial tests.
|
||||
}
|
||||
|
||||
// Short reports whether the -test.short flag is set.
|
||||
func Short() bool {
|
||||
return *short
|
||||
|
@ -79,7 +90,7 @@ func Short() bool {
|
|||
// If addFileLine is true, it also prefixes the string with the file and line of the call site.
|
||||
func decorate(s string, addFileLine bool) string {
|
||||
if addFileLine {
|
||||
_, file, line, ok := runtime.Caller(3) // decorate + log + public function.
|
||||
_, file, line, ok := runtime.Caller(4) // decorate + log + public function.
|
||||
if ok {
|
||||
// Truncate file name at last file name separator.
|
||||
if index := strings.LastIndex(file, "/"); index >= 0 {
|
||||
|
@ -111,70 +122,68 @@ func decorate(s string, addFileLine bool) string {
|
|||
// T is a type passed to Test functions to manage test state and support formatted test logs.
|
||||
// Logs are accumulated during execution and dumped to standard error when done.
|
||||
type T struct {
|
||||
name string // Name of test.
|
||||
errors string // Error string from test.
|
||||
failed bool // Test has failed.
|
||||
ch chan *T // Output for serial tests.
|
||||
startParallel chan bool // Parallel tests will wait on this.
|
||||
start time.Time // Time test started
|
||||
dt time.Duration // Length of test
|
||||
common
|
||||
name string // Name of test.
|
||||
startParallel chan bool // Parallel tests will wait on this.
|
||||
}
|
||||
|
||||
// Fail marks the Test function as having failed but continues execution.
|
||||
func (t *T) Fail() { t.failed = true }
|
||||
// Fail marks the function as having failed but continues execution.
|
||||
func (c *common) Fail() { c.failed = true }
|
||||
|
||||
// Failed returns whether the Test function has failed.
|
||||
func (t *T) Failed() bool { return t.failed }
|
||||
// Failed returns whether the function has failed.
|
||||
func (c *common) Failed() bool { return c.failed }
|
||||
|
||||
// FailNow marks the Test function as having failed and stops its execution.
|
||||
// FailNow marks the function as having failed and stops its execution.
|
||||
// Execution will continue at the next Test.
|
||||
func (t *T) FailNow() {
|
||||
t.dt = time.Now().Sub(t.start)
|
||||
t.Fail()
|
||||
t.ch <- t
|
||||
func (c *common) FailNow() {
|
||||
c.duration = time.Now().Sub(c.start)
|
||||
c.Fail()
|
||||
c.signal <- c.self
|
||||
runtime.Goexit()
|
||||
}
|
||||
|
||||
// log generates the output. It's always at the same stack depth.
|
||||
func (t *T) log(s string) { t.errors += decorate(s, true) }
|
||||
func (c *common) log(s string) {
|
||||
c.output = append(c.output, decorate(s, true)...)
|
||||
}
|
||||
|
||||
// Log formats its arguments using default formatting, analogous to Print(),
|
||||
// Log formats its arguments using default formatting, analogous to Println(),
|
||||
// and records the text in the error log.
|
||||
func (t *T) Log(args ...interface{}) { t.log(fmt.Sprintln(args...)) }
|
||||
func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
|
||||
|
||||
// Logf formats its arguments according to the format, analogous to Printf(),
|
||||
// and records the text in the error log.
|
||||
func (t *T) Logf(format string, args ...interface{}) { t.log(fmt.Sprintf(format, args...)) }
|
||||
func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
|
||||
|
||||
// Error is equivalent to Log() followed by Fail().
|
||||
func (t *T) Error(args ...interface{}) {
|
||||
t.log(fmt.Sprintln(args...))
|
||||
t.Fail()
|
||||
func (c *common) Error(args ...interface{}) {
|
||||
c.log(fmt.Sprintln(args...))
|
||||
c.Fail()
|
||||
}
|
||||
|
||||
// Errorf is equivalent to Logf() followed by Fail().
|
||||
func (t *T) Errorf(format string, args ...interface{}) {
|
||||
t.log(fmt.Sprintf(format, args...))
|
||||
t.Fail()
|
||||
func (c *common) Errorf(format string, args ...interface{}) {
|
||||
c.log(fmt.Sprintf(format, args...))
|
||||
c.Fail()
|
||||
}
|
||||
|
||||
// Fatal is equivalent to Log() followed by FailNow().
|
||||
func (t *T) Fatal(args ...interface{}) {
|
||||
t.log(fmt.Sprintln(args...))
|
||||
t.FailNow()
|
||||
func (c *common) Fatal(args ...interface{}) {
|
||||
c.log(fmt.Sprintln(args...))
|
||||
c.FailNow()
|
||||
}
|
||||
|
||||
// Fatalf is equivalent to Logf() followed by FailNow().
|
||||
func (t *T) Fatalf(format string, args ...interface{}) {
|
||||
t.log(fmt.Sprintf(format, args...))
|
||||
t.FailNow()
|
||||
func (c *common) Fatalf(format string, args ...interface{}) {
|
||||
c.log(fmt.Sprintf(format, args...))
|
||||
c.FailNow()
|
||||
}
|
||||
|
||||
// Parallel signals that this test is to be run in parallel with (and only with)
|
||||
// other parallel tests in this CPU group.
|
||||
func (t *T) Parallel() {
|
||||
t.ch <- nil // Release main testing loop
|
||||
<-t.startParallel // Wait for serial tests to finish
|
||||
t.signal <- (*T)(nil) // Release main testing loop
|
||||
<-t.startParallel // Wait for serial tests to finish
|
||||
}
|
||||
|
||||
// An internal type but exported because it is cross-package; part of the implementation
|
||||
|
@ -187,8 +196,8 @@ type InternalTest struct {
|
|||
func tRunner(t *T, test *InternalTest) {
|
||||
t.start = time.Now()
|
||||
test.F(t)
|
||||
t.dt = time.Now().Sub(t.start)
|
||||
t.ch <- t
|
||||
t.duration = time.Now().Sub(t.start)
|
||||
t.signal <- t
|
||||
}
|
||||
|
||||
// An internal function but exported because it is cross-package; part of the implementation
|
||||
|
@ -211,13 +220,13 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest,
|
|||
after()
|
||||
}
|
||||
|
||||
func report(t *T) {
|
||||
tstr := fmt.Sprintf("(%.2f seconds)", t.dt.Seconds())
|
||||
func (t *T) report() {
|
||||
tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
|
||||
format := "--- %s: %s %s\n%s"
|
||||
if t.failed {
|
||||
fmt.Printf(format, "FAIL", t.name, tstr, t.errors)
|
||||
fmt.Printf(format, "FAIL", t.name, tstr, t.output)
|
||||
} else if *chatty {
|
||||
fmt.Printf(format, "PASS", t.name, tstr, t.errors)
|
||||
fmt.Printf(format, "PASS", t.name, tstr, t.output)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,9 +236,14 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
|
|||
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
||||
return
|
||||
}
|
||||
ch := make(chan *T)
|
||||
for _, procs := range cpuList {
|
||||
runtime.GOMAXPROCS(procs)
|
||||
// We build a new channel tree for each run of the loop.
|
||||
// collector merges in one channel all the upstream signals from parallel tests.
|
||||
// If all tests pump to the same channel, a bug can occur where a test
|
||||
// kicks off a goroutine that Fails, yet the test still delivers a completion signal,
|
||||
// which skews the counting.
|
||||
var collector = make(chan interface{})
|
||||
|
||||
numParallel := 0
|
||||
startParallel := make(chan bool)
|
||||
|
@ -247,17 +261,27 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
|
|||
if procs != 1 {
|
||||
testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
|
||||
}
|
||||
t := &T{ch: ch, name: testName, startParallel: startParallel}
|
||||
t := &T{
|
||||
common: common{
|
||||
signal: make(chan interface{}),
|
||||
},
|
||||
name: testName,
|
||||
startParallel: startParallel,
|
||||
}
|
||||
t.self = t
|
||||
if *chatty {
|
||||
fmt.Printf("=== RUN %s\n", t.name)
|
||||
}
|
||||
go tRunner(t, &tests[i])
|
||||
out := <-t.ch
|
||||
out := (<-t.signal).(*T)
|
||||
if out == nil { // Parallel run.
|
||||
go func() {
|
||||
collector <- <-t.signal
|
||||
}()
|
||||
numParallel++
|
||||
continue
|
||||
}
|
||||
report(t)
|
||||
t.report()
|
||||
ok = ok && !out.failed
|
||||
}
|
||||
|
||||
|
@ -269,8 +293,8 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
|
|||
numParallel--
|
||||
continue
|
||||
}
|
||||
t := <-ch
|
||||
report(t)
|
||||
t := (<-collector).(*T)
|
||||
t.report()
|
||||
ok = ok && !t.failed
|
||||
running--
|
||||
}
|
||||
|
|
105
libgo/go/testing/wrapper.go
Normal file
105
libgo/go/testing/wrapper.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains wrappers so t.Errorf etc. have documentation.
|
||||
// TODO: delete when godoc shows exported methods for unexported embedded fields.
|
||||
// TODO: need to change the argument to runtime.Caller in testing.go from 4 to 3 at that point.
|
||||
|
||||
package testing
|
||||
|
||||
// Fail marks the function as having failed but continues execution.
|
||||
func (b *B) Fail() {
|
||||
b.common.Fail()
|
||||
}
|
||||
|
||||
// Failed returns whether the function has failed.
|
||||
func (b *B) Failed() bool {
|
||||
return b.common.Failed()
|
||||
}
|
||||
|
||||
// FailNow marks the function as having failed and stops its execution.
|
||||
// Execution will continue at the next Test.
|
||||
func (b *B) FailNow() {
|
||||
b.common.FailNow()
|
||||
}
|
||||
|
||||
// Log formats its arguments using default formatting, analogous to Println(),
|
||||
// and records the text in the error log.
|
||||
func (b *B) Log(args ...interface{}) {
|
||||
b.common.Log(args...)
|
||||
}
|
||||
|
||||
// Logf formats its arguments according to the format, analogous to Printf(),
|
||||
// and records the text in the error log.
|
||||
func (b *B) Logf(format string, args ...interface{}) {
|
||||
b.common.Logf(format, args...)
|
||||
}
|
||||
|
||||
// Error is equivalent to Log() followed by Fail().
|
||||
func (b *B) Error(args ...interface{}) {
|
||||
b.common.Error(args...)
|
||||
}
|
||||
|
||||
// Errorf is equivalent to Logf() followed by Fail().
|
||||
func (b *B) Errorf(format string, args ...interface{}) {
|
||||
b.common.Errorf(format, args...)
|
||||
}
|
||||
|
||||
// Fatal is equivalent to Log() followed by FailNow().
|
||||
func (b *B) Fatal(args ...interface{}) {
|
||||
b.common.Fatal(args...)
|
||||
}
|
||||
|
||||
// Fatalf is equivalent to Logf() followed by FailNow().
|
||||
func (b *B) Fatalf(format string, args ...interface{}) {
|
||||
b.common.Fatalf(format, args...)
|
||||
}
|
||||
|
||||
// Fail marks the function as having failed but continues execution.
|
||||
func (t *T) Fail() {
|
||||
t.common.Fail()
|
||||
}
|
||||
|
||||
// Failed returns whether the function has failed.
|
||||
func (t *T) Failed() bool {
|
||||
return t.common.Failed()
|
||||
}
|
||||
|
||||
// FailNow marks the function as having failed and stops its execution.
|
||||
// Execution will continue at the next Test.
|
||||
func (t *T) FailNow() {
|
||||
t.common.FailNow()
|
||||
}
|
||||
|
||||
// Log formats its arguments using default formatting, analogous to Println(),
|
||||
// and records the text in the error log.
|
||||
func (t *T) Log(args ...interface{}) {
|
||||
t.common.Log(args...)
|
||||
}
|
||||
|
||||
// Logf formats its arguments according to the format, analogous to Printf(),
|
||||
// and records the text in the error log.
|
||||
func (t *T) Logf(format string, args ...interface{}) {
|
||||
t.common.Logf(format, args...)
|
||||
}
|
||||
|
||||
// Error is equivalent to Log() followed by Fail().
|
||||
func (t *T) Error(args ...interface{}) {
|
||||
t.common.Error(args...)
|
||||
}
|
||||
|
||||
// Errorf is equivalent to Logf() followed by Fail().
|
||||
func (t *T) Errorf(format string, args ...interface{}) {
|
||||
t.common.Errorf(format, args...)
|
||||
}
|
||||
|
||||
// Fatal is equivalent to Log() followed by FailNow().
|
||||
func (t *T) Fatal(args ...interface{}) {
|
||||
t.common.Fatal(args...)
|
||||
}
|
||||
|
||||
// Fatalf is equivalent to Logf() followed by FailNow().
|
||||
func (t *T) Fatalf(format string, args ...interface{}) {
|
||||
t.common.Fatalf(format, args...)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue