aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/testing
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-02-03 21:58:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-02-03 21:58:02 +0000
commitf98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch)
tree2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/testing
parentb081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff)
downloadgcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.zip
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.gz
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.bz2
libgo: Update to go1.6rc1.
Reviewed-on: https://go-review.googlesource.com/19200 From-SVN: r233110
Diffstat (limited to 'libgo/go/testing')
-rw-r--r--libgo/go/testing/benchmark.go11
-rw-r--r--libgo/go/testing/quick/quick.go38
-rw-r--r--libgo/go/testing/quick/quick_test.go53
-rw-r--r--libgo/go/testing/testing.go32
4 files changed, 109 insertions, 25 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 62e696d..85178c2 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -33,6 +33,17 @@ type InternalBenchmark struct {
// B is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
+//
+// A benchmark ends when its Benchmark function returns or calls any of the methods
+// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called
+// only from the goroutine running the Benchmark function.
+// The other reporting methods, such as the variations of Log and Error,
+// may be called simultaneously from multiple goroutines.
+//
+// Like in tests, benchmark logs are accumulated during execution
+// and dumped to standard error when done. Unlike in tests, benchmark logs
+// are always printed, so as not to hide output whose existence may be
+// affecting benchmark results.
type B struct {
common
N int
diff --git a/libgo/go/testing/quick/quick.go b/libgo/go/testing/quick/quick.go
index 13c56cd..187195c 100644
--- a/libgo/go/testing/quick/quick.go
+++ b/libgo/go/testing/quick/quick.go
@@ -52,8 +52,15 @@ const complexSize = 50
// If the type implements the Generator interface, that will be used.
// Note: To create arbitrary values for structs, all the fields must be exported.
func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
+ return sizedValue(t, rand, complexSize)
+}
+
+// sizedValue returns an arbitrary value of the given type. The size
+// hint is used for shrinking as a function of indirection level so
+// that recursive data structures will terminate.
+func sizedValue(t reflect.Type, rand *rand.Rand, size int) (value reflect.Value, ok bool) {
if m, ok := reflect.Zero(t).Interface().(Generator); ok {
- return m.Generate(rand, complexSize), true
+ return m.Generate(rand, size), true
}
v := reflect.New(t).Elem()
@@ -91,21 +98,21 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
case reflect.Uintptr:
v.SetUint(uint64(randInt64(rand)))
case reflect.Map:
- numElems := rand.Intn(complexSize)
+ numElems := rand.Intn(size)
v.Set(reflect.MakeMap(concrete))
for i := 0; i < numElems; i++ {
- key, ok1 := Value(concrete.Key(), rand)
- value, ok2 := Value(concrete.Elem(), rand)
+ key, ok1 := sizedValue(concrete.Key(), rand, size)
+ value, ok2 := sizedValue(concrete.Elem(), rand, size)
if !ok1 || !ok2 {
return reflect.Value{}, false
}
v.SetMapIndex(key, value)
}
case reflect.Ptr:
- if rand.Intn(complexSize) == 0 {
+ if rand.Intn(size) == 0 {
v.Set(reflect.Zero(concrete)) // Generate nil pointer.
} else {
- elem, ok := Value(concrete.Elem(), rand)
+ elem, ok := sizedValue(concrete.Elem(), rand, size)
if !ok {
return reflect.Value{}, false
}
@@ -113,10 +120,11 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
v.Elem().Set(elem)
}
case reflect.Slice:
- numElems := rand.Intn(complexSize)
+ numElems := rand.Intn(size)
+ sizeLeft := size - numElems
v.Set(reflect.MakeSlice(concrete, numElems, numElems))
for i := 0; i < numElems; i++ {
- elem, ok := Value(concrete.Elem(), rand)
+ elem, ok := sizedValue(concrete.Elem(), rand, sizeLeft)
if !ok {
return reflect.Value{}, false
}
@@ -124,7 +132,7 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
}
case reflect.Array:
for i := 0; i < v.Len(); i++ {
- elem, ok := Value(concrete.Elem(), rand)
+ elem, ok := sizedValue(concrete.Elem(), rand, size)
if !ok {
return reflect.Value{}, false
}
@@ -138,8 +146,16 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
}
v.SetString(string(codePoints))
case reflect.Struct:
- for i := 0; i < v.NumField(); i++ {
- elem, ok := Value(concrete.Field(i).Type, rand)
+ n := v.NumField()
+ // Divide sizeLeft evenly among the struct fields.
+ sizeLeft := size
+ if n > sizeLeft {
+ sizeLeft = 1
+ } else if n > 0 {
+ sizeLeft /= n
+ }
+ for i := 0; i < n; i++ {
+ elem, ok := sizedValue(concrete.Field(i).Type, rand, sizeLeft)
if !ok {
return reflect.Value{}, false
}
diff --git a/libgo/go/testing/quick/quick_test.go b/libgo/go/testing/quick/quick_test.go
index c79f30e..fe44359 100644
--- a/libgo/go/testing/quick/quick_test.go
+++ b/libgo/go/testing/quick/quick_test.go
@@ -259,16 +259,51 @@ func TestFailure(t *testing.T) {
}
}
-// The following test didn't terminate because nil pointers were not
-// generated.
-// Issue 8818.
-func TestNilPointers(t *testing.T) {
- type Recursive struct {
- Next *Recursive
+// Recursive data structures didn't terminate.
+// Issues 8818 and 11148.
+func TestRecursive(t *testing.T) {
+ type R struct {
+ Ptr *R
+ SliceP []*R
+ Slice []R
+ Map map[int]R
+ MapP map[int]*R
+ MapR map[*R]*R
+ SliceMap []map[int]R
}
- f := func(rec Recursive) bool {
- return true
- }
+ f := func(r R) bool { return true }
+ Check(f, nil)
+}
+
+func TestEmptyStruct(t *testing.T) {
+ f := func(struct{}) bool { return true }
+ Check(f, nil)
+}
+
+type (
+ A struct{ B *B }
+ B struct{ A *A }
+)
+
+func TestMutuallyRecursive(t *testing.T) {
+ f := func(a A) bool { return true }
Check(f, nil)
}
+
+// Some serialization formats (e.g. encoding/pem) cannot distinguish
+// between a nil and an empty map or slice, so avoid generating the
+// zero value for these.
+func TestNonZeroSliceAndMap(t *testing.T) {
+ type Q struct {
+ M map[int]int
+ S []int
+ }
+ f := func(q Q) bool {
+ return q.M != nil && q.S != nil
+ }
+ err := Check(f, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 9ec3869..bcbe8f1 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -149,6 +149,7 @@ import (
"fmt"
"os"
"runtime"
+ "runtime/debug"
"runtime/pprof"
"strconv"
"strings"
@@ -281,9 +282,18 @@ var _ TB = (*B)(nil)
// 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.
+//
+// A test ends when its Test function returns or calls any of the methods
+// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as
+// the Parallel method, must be called only from the goroutine running the
+// Test function.
+//
+// The other reporting methods, such as the variations of Log and Error,
+// may be called simultaneously from multiple goroutines.
type T struct {
common
- name string // Name of test.
+ name string // Name of test.
+ isParallel bool
startParallel chan bool // Parallel tests will wait on this.
}
@@ -417,10 +427,17 @@ func (c *common) Skipped() bool {
// Parallel signals that this test is to be run in parallel with (and only with)
// other parallel tests.
func (t *T) Parallel() {
+ if t.isParallel {
+ panic("testing: t.Parallel called multiple times")
+ }
+ t.isParallel = true
+
+ // We don't want to include the time we spend waiting for serial tests
+ // in the test duration. Record the elapsed time thus far and reset the
+ // timer afterwards.
+ t.duration += time.Since(t.start)
t.signal <- (*T)(nil) // Release main testing loop
<-t.startParallel // Wait for serial tests to finish
- // Assuming Parallel is the first thing a test does, which is reasonable,
- // reinitialize the test's start time because it's actually starting now.
t.start = time.Now()
}
@@ -437,7 +454,7 @@ func tRunner(t *T, test *InternalTest) {
// a call to runtime.Goexit, record the duration and send
// a signal saying that the test is done.
defer func() {
- t.duration = time.Now().Sub(t.start)
+ t.duration += time.Now().Sub(t.start)
// If the test panicked, print any test output before dying.
err := recover()
if !t.finished && err == nil {
@@ -484,7 +501,11 @@ func MainStart(matchString func(pat, str string) (bool, error), tests []Internal
// Run runs the tests. It returns an exit code to pass to os.Exit.
func (m *M) Run() int {
- flag.Parse()
+ // TestMain may have already called flag.Parse.
+ if !flag.Parsed() {
+ flag.Parse()
+ }
+
parseCpuList()
before()
@@ -704,6 +725,7 @@ var timer *time.Timer
func startAlarm() {
if *timeout > 0 {
timer = time.AfterFunc(*timeout, func() {
+ debug.SetTraceback("all")
panic(fmt.Sprintf("test timed out after %v", *timeout))
})
}