aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/testing
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/testing
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
downloadgcc-adb0401dac41c81571722312d4586b2693f95aa6.zip
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.bz2
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/testing')
-rw-r--r--libgo/go/testing/benchmark.go67
-rw-r--r--libgo/go/testing/iotest/reader.go22
-rw-r--r--libgo/go/testing/testing.go67
3 files changed, 121 insertions, 35 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index cf73e2b..fd0bd86 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -13,6 +13,7 @@ import (
)
var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
+var benchTime = flag.Float64("test.benchtime", 1, "approximate run time for each benchmark, in seconds")
// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
@@ -34,7 +35,11 @@ type B struct {
// StartTimer starts timing a test. This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
-func (b *B) StartTimer() { b.start = time.Nanoseconds() }
+func (b *B) StartTimer() {
+ if b.start == 0 {
+ b.start = time.Nanoseconds()
+ }
+}
// StopTimer stops timing a test. This can be used to pause the timer
// while performing complex initialization that you don't
@@ -46,9 +51,12 @@ func (b *B) StopTimer() {
b.start = 0
}
-// ResetTimer stops the timer and sets the elapsed benchmark time to zero.
+// ResetTimer sets the elapsed benchmark time to zero.
+// It does not affect whether the timer is running.
func (b *B) ResetTimer() {
- b.start = 0
+ if b.start > 0 {
+ b.start = time.Nanoseconds()
+ }
b.ns = 0
}
@@ -125,14 +133,15 @@ func (b *B) run() BenchmarkResult {
// Run the benchmark for a single iteration in case it's expensive.
n := 1
b.runN(n)
- // Run the benchmark for at least a second.
- for b.ns < 1e9 && n < 1e9 {
+ // Run the benchmark for at least the specified amount of time.
+ time := int64(*benchTime * 1e9)
+ for b.ns < time && n < 1e9 {
last := n
// Predict iterations/sec.
if b.nsPerOp() == 0 {
n = 1e9
} else {
- n = 1e9 / int(b.nsPerOp())
+ n = int(time / b.nsPerOp())
}
// Run more iterations than we think we'll need for a second (1.5x).
// Don't grow too fast in case we had timing errors previously.
@@ -143,14 +152,13 @@ func (b *B) run() BenchmarkResult {
b.runN(n)
}
return BenchmarkResult{b.N, b.ns, b.bytes}
-
}
// The results of a benchmark run.
type BenchmarkResult struct {
N int // The number of iterations.
Ns int64 // The total time taken.
- Bytes int64 // The total number of bytes processed.
+ Bytes int64 // Bytes processed in one iteration.
}
func (r BenchmarkResult) NsPerOp() int64 {
@@ -160,13 +168,31 @@ func (r BenchmarkResult) NsPerOp() int64 {
return r.Ns / int64(r.N)
}
+func (r BenchmarkResult) mbPerSec() float64 {
+ if r.Bytes <= 0 || r.Ns <= 0 || r.N <= 0 {
+ return 0
+ }
+ return float64(r.Bytes) * float64(r.N) / float64(r.Ns) * 1e3
+}
+
func (r BenchmarkResult) String() string {
- ns := r.NsPerOp()
+ mbs := r.mbPerSec()
mb := ""
- if ns > 0 && r.Bytes > 0 {
- mb = fmt.Sprintf("\t%7.2f MB/s", (float64(r.Bytes)/1e6)/(float64(ns)/1e9))
+ if mbs != 0 {
+ mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
}
- return fmt.Sprintf("%8d\t%10d ns/op%s", r.N, ns, mb)
+ nsop := r.NsPerOp()
+ ns := fmt.Sprintf("%10d ns/op", nsop)
+ if r.N > 0 && nsop < 100 {
+ // The format specifiers here make sure that
+ // the ones digits line up for all three possible formats.
+ if nsop < 10 {
+ ns = fmt.Sprintf("%13.2f ns/op", float64(r.Ns)/float64(r.N))
+ } else {
+ ns = fmt.Sprintf("%12.1f ns/op", float64(r.Ns)/float64(r.N))
+ }
+ }
+ return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
}
// An internal function but exported because it is cross-package; part of the implementation
@@ -185,9 +211,20 @@ func RunBenchmarks(matchString func(pat, str string) (bool, os.Error), benchmark
if !matched {
continue
}
- b := &B{benchmark: Benchmark}
- r := b.run()
- fmt.Printf("%s\t%v\n", Benchmark.Name, r)
+ for _, procs := range cpuList {
+ runtime.GOMAXPROCS(procs)
+ b := &B{benchmark: Benchmark}
+ benchName := Benchmark.Name
+ if procs != 1 {
+ benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
+ }
+ print(fmt.Sprintf("%s\t", benchName))
+ r := b.run()
+ print(fmt.Sprintf("%v\n", r))
+ if p := runtime.GOMAXPROCS(-1); p != procs {
+ print(fmt.Sprintf("%s left GOMAXPROCS set to %d\n", benchName, p))
+ }
+ }
}
}
diff --git a/libgo/go/testing/iotest/reader.go b/libgo/go/testing/iotest/reader.go
index e4003d7..dcf5565 100644
--- a/libgo/go/testing/iotest/reader.go
+++ b/libgo/go/testing/iotest/reader.go
@@ -37,7 +37,6 @@ func (r *halfReader) Read(p []byte) (int, os.Error) {
return r.r.Read(p[0 : (len(p)+1)/2])
}
-
// DataErrReader returns a Reader that returns the final
// error with the last data read, instead of by itself with
// zero bytes of data.
@@ -58,7 +57,7 @@ func (r *dataErrReader) Read(p []byte) (n int, err os.Error) {
r.unread = r.data[0:n1]
err = err1
}
- if n > 0 {
+ if n > 0 || err != nil {
break
}
n = copy(p, r.unread)
@@ -66,3 +65,22 @@ func (r *dataErrReader) Read(p []byte) (n int, err os.Error) {
}
return
}
+
+var ErrTimeout = os.NewError("timeout")
+
+// TimeoutReader returns ErrTimeout on the second read
+// with no data. Subsequent calls to read succeed.
+func TimeoutReader(r io.Reader) io.Reader { return &timeoutReader{r, 0} }
+
+type timeoutReader struct {
+ r io.Reader
+ count int
+}
+
+func (r *timeoutReader) Read(p []byte) (int, os.Error) {
+ r.count++
+ if r.count == 2 {
+ return 0, ErrTimeout
+ }
+ return r.r.Read(p)
+}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 8781b20..ec4a453 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -44,6 +44,8 @@ import (
"os"
"runtime"
"runtime/pprof"
+ "strings"
+ "strconv"
"time"
)
@@ -62,6 +64,9 @@ var (
memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
timeout = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
+ cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+
+ cpuList []int
)
// Short reports whether the -test.short flag is set.
@@ -69,7 +74,6 @@ func Short() bool {
return *short
}
-
// Insert final newline if needed and tabs after internal newlines.
func tabify(s string) string {
n := len(s)
@@ -157,6 +161,7 @@ func tRunner(t *T, test *InternalTest) {
// of gotest.
func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) {
flag.Parse()
+ parseCpuList()
before()
startAlarm()
@@ -180,23 +185,34 @@ func RunTests(matchString func(pat, str string) (bool, os.Error), tests []Intern
if !matched {
continue
}
- if *chatty {
- println("=== RUN ", tests[i].Name)
- }
- ns := -time.Nanoseconds()
- t := new(T)
- t.ch = make(chan *T)
- go tRunner(t, &tests[i])
- <-t.ch
- ns += time.Nanoseconds()
- tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
- if t.failed {
- println("--- FAIL:", tests[i].Name, tstr)
- print(t.errors)
- ok = false
- } else if *chatty {
- println("--- PASS:", tests[i].Name, tstr)
- print(t.errors)
+ for _, procs := range cpuList {
+ runtime.GOMAXPROCS(procs)
+ testName := tests[i].Name
+ if procs != 1 {
+ testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
+ }
+ if *chatty {
+ println("=== RUN ", testName)
+ }
+ ns := -time.Nanoseconds()
+ t := new(T)
+ t.ch = make(chan *T)
+ go tRunner(t, &tests[i])
+ <-t.ch
+ ns += time.Nanoseconds()
+ tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
+ if p := runtime.GOMAXPROCS(-1); t.failed == false && p != procs {
+ t.failed = true
+ t.errors = fmt.Sprintf("%s left GOMAXPROCS set to %d\n", testName, p)
+ }
+ if t.failed {
+ println("--- FAIL:", testName, tstr)
+ print(t.errors)
+ ok = false
+ } else if *chatty {
+ println("--- PASS:", testName, tstr)
+ print(t.errors)
+ }
}
}
if !ok {
@@ -265,3 +281,18 @@ func stopAlarm() {
func alarm() {
panic("test timed out")
}
+
+func parseCpuList() {
+ if len(*cpuListStr) == 0 {
+ cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
+ } else {
+ for _, val := range strings.Split(*cpuListStr, ",") {
+ cpu, err := strconv.Atoi(val)
+ if err != nil || cpu <= 0 {
+ println("invalid value for -test.cpu")
+ os.Exit(1)
+ }
+ cpuList = append(cpuList, cpu)
+ }
+ }
+}