summaryrefslogtreecommitdiff
path: root/src/pkg/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/testing')
-rw-r--r--src/pkg/testing/quick/quick.go114
-rw-r--r--src/pkg/testing/script/script.go16
-rw-r--r--src/pkg/testing/testing.go99
3 files changed, 158 insertions, 71 deletions
diff --git a/src/pkg/testing/quick/quick.go b/src/pkg/testing/quick/quick.go
index a5568b048..52fd38d9c 100644
--- a/src/pkg/testing/quick/quick.go
+++ b/src/pkg/testing/quick/quick.go
@@ -53,96 +53,93 @@ const complexSize = 50
// If the type implements the Generator interface, that will be used.
// Note: in order to create arbitrary values for structs, all the members must be public.
func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
- if m, ok := reflect.MakeZero(t).Interface().(Generator); ok {
+ if m, ok := reflect.Zero(t).Interface().(Generator); ok {
return m.Generate(rand, complexSize), true
}
- switch concrete := t.(type) {
- case *reflect.BoolType:
+ switch concrete := t; concrete.Kind() {
+ case reflect.Bool:
return reflect.NewValue(rand.Int()&1 == 0), true
- case *reflect.FloatType, *reflect.IntType, *reflect.UintType, *reflect.ComplexType:
- switch t.Kind() {
- case reflect.Float32:
- return reflect.NewValue(randFloat32(rand)), true
- case reflect.Float64:
- return reflect.NewValue(randFloat64(rand)), true
- case reflect.Complex64:
- return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
- case reflect.Complex128:
- return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
- case reflect.Int16:
- return reflect.NewValue(int16(randInt64(rand))), true
- case reflect.Int32:
- return reflect.NewValue(int32(randInt64(rand))), true
- case reflect.Int64:
- return reflect.NewValue(randInt64(rand)), true
- case reflect.Int8:
- return reflect.NewValue(int8(randInt64(rand))), true
- case reflect.Int:
- return reflect.NewValue(int(randInt64(rand))), true
- case reflect.Uint16:
- return reflect.NewValue(uint16(randInt64(rand))), true
- case reflect.Uint32:
- return reflect.NewValue(uint32(randInt64(rand))), true
- case reflect.Uint64:
- return reflect.NewValue(uint64(randInt64(rand))), true
- case reflect.Uint8:
- return reflect.NewValue(uint8(randInt64(rand))), true
- case reflect.Uint:
- return reflect.NewValue(uint(randInt64(rand))), true
- case reflect.Uintptr:
- return reflect.NewValue(uintptr(randInt64(rand))), true
- }
- case *reflect.MapType:
+ case reflect.Float32:
+ return reflect.NewValue(randFloat32(rand)), true
+ case reflect.Float64:
+ return reflect.NewValue(randFloat64(rand)), true
+ case reflect.Complex64:
+ return reflect.NewValue(complex(randFloat32(rand), randFloat32(rand))), true
+ case reflect.Complex128:
+ return reflect.NewValue(complex(randFloat64(rand), randFloat64(rand))), true
+ case reflect.Int16:
+ return reflect.NewValue(int16(randInt64(rand))), true
+ case reflect.Int32:
+ return reflect.NewValue(int32(randInt64(rand))), true
+ case reflect.Int64:
+ return reflect.NewValue(randInt64(rand)), true
+ case reflect.Int8:
+ return reflect.NewValue(int8(randInt64(rand))), true
+ case reflect.Int:
+ return reflect.NewValue(int(randInt64(rand))), true
+ case reflect.Uint16:
+ return reflect.NewValue(uint16(randInt64(rand))), true
+ case reflect.Uint32:
+ return reflect.NewValue(uint32(randInt64(rand))), true
+ case reflect.Uint64:
+ return reflect.NewValue(uint64(randInt64(rand))), true
+ case reflect.Uint8:
+ return reflect.NewValue(uint8(randInt64(rand))), true
+ case reflect.Uint:
+ return reflect.NewValue(uint(randInt64(rand))), true
+ case reflect.Uintptr:
+ return reflect.NewValue(uintptr(randInt64(rand))), true
+ case reflect.Map:
numElems := rand.Intn(complexSize)
m := reflect.MakeMap(concrete)
for i := 0; i < numElems; i++ {
key, ok1 := Value(concrete.Key(), rand)
value, ok2 := Value(concrete.Elem(), rand)
if !ok1 || !ok2 {
- return nil, false
+ return reflect.Value{}, false
}
- m.SetElem(key, value)
+ m.SetMapIndex(key, value)
}
return m, true
- case *reflect.PtrType:
+ case reflect.Ptr:
v, ok := Value(concrete.Elem(), rand)
if !ok {
- return nil, false
+ return reflect.Value{}, false
}
- p := reflect.MakeZero(concrete)
- p.(*reflect.PtrValue).PointTo(v)
+ p := reflect.Zero(concrete)
+ p.Set(v.Addr())
return p, true
- case *reflect.SliceType:
+ case reflect.Slice:
numElems := rand.Intn(complexSize)
s := reflect.MakeSlice(concrete, numElems, numElems)
for i := 0; i < numElems; i++ {
v, ok := Value(concrete.Elem(), rand)
if !ok {
- return nil, false
+ return reflect.Value{}, false
}
- s.Elem(i).SetValue(v)
+ s.Index(i).Set(v)
}
return s, true
- case *reflect.StringType:
+ case reflect.String:
numChars := rand.Intn(complexSize)
codePoints := make([]int, numChars)
for i := 0; i < numChars; i++ {
codePoints[i] = rand.Intn(0x10ffff)
}
return reflect.NewValue(string(codePoints)), true
- case *reflect.StructType:
- s := reflect.MakeZero(t).(*reflect.StructValue)
+ case reflect.Struct:
+ s := reflect.Zero(t)
for i := 0; i < s.NumField(); i++ {
v, ok := Value(concrete.Field(i).Type, rand)
if !ok {
- return nil, false
+ return reflect.Value{}, false
}
- s.Field(i).SetValue(v)
+ s.Field(i).Set(v)
}
return s, true
default:
- return nil, false
+ return reflect.Value{}, false
}
return
@@ -247,7 +244,7 @@ func Check(function interface{}, config *Config) (err os.Error) {
err = SetupError("function returns more than one value.")
return
}
- if _, ok := fType.Out(0).(*reflect.BoolType); !ok {
+ if fType.Out(0).Kind() != reflect.Bool {
err = SetupError("function does not return a bool")
return
}
@@ -262,7 +259,7 @@ func Check(function interface{}, config *Config) (err os.Error) {
return
}
- if !f.Call(arguments)[0].(*reflect.BoolValue).Get() {
+ if !f.Call(arguments)[0].Bool() {
err = &CheckError{i + 1, toInterfaces(arguments)}
return
}
@@ -320,7 +317,7 @@ func CheckEqual(f, g interface{}, config *Config) (err os.Error) {
// arbitraryValues writes Values to args such that args contains Values
// suitable for calling f.
-func arbitraryValues(args []reflect.Value, f *reflect.FuncType, config *Config, rand *rand.Rand) (err os.Error) {
+func arbitraryValues(args []reflect.Value, f reflect.Type, config *Config, rand *rand.Rand) (err os.Error) {
if config.Values != nil {
config.Values(args, rand)
return
@@ -338,12 +335,13 @@ func arbitraryValues(args []reflect.Value, f *reflect.FuncType, config *Config,
return
}
-func functionAndType(f interface{}) (v *reflect.FuncValue, t *reflect.FuncType, ok bool) {
- v, ok = reflect.NewValue(f).(*reflect.FuncValue)
+func functionAndType(f interface{}) (v reflect.Value, t reflect.Type, ok bool) {
+ v = reflect.NewValue(f)
+ ok = v.Kind() == reflect.Func
if !ok {
return
}
- t = v.Type().(*reflect.FuncType)
+ t = v.Type()
return
}
diff --git a/src/pkg/testing/script/script.go b/src/pkg/testing/script/script.go
index 11f5a7425..b18018497 100644
--- a/src/pkg/testing/script/script.go
+++ b/src/pkg/testing/script/script.go
@@ -134,16 +134,16 @@ type empty struct {
}
func newEmptyInterface(e empty) reflect.Value {
- return reflect.NewValue(e).(*reflect.StructValue).Field(0)
+ return reflect.NewValue(e).Field(0)
}
func (s Send) send() {
// With reflect.ChanValue.Send, we must match the types exactly. So, if
// s.Channel is a chan interface{} we convert s.Value to an interface{}
// first.
- c := reflect.NewValue(s.Channel).(*reflect.ChanValue)
+ c := reflect.NewValue(s.Channel)
var v reflect.Value
- if iface, ok := c.Type().(*reflect.ChanType).Elem().(*reflect.InterfaceType); ok && iface.NumMethod() == 0 {
+ if iface := c.Type().Elem(); iface.Kind() == reflect.Interface && iface.NumMethod() == 0 {
v = newEmptyInterface(empty{s.Value})
} else {
v = reflect.NewValue(s.Value)
@@ -162,7 +162,7 @@ func (s Close) getSend() sendAction { return s }
func (s Close) getChannel() interface{} { return s.Channel }
-func (s Close) send() { reflect.NewValue(s.Channel).(*reflect.ChanValue).Close() }
+func (s Close) send() { reflect.NewValue(s.Channel).Close() }
// A ReceivedUnexpected error results if no active Events match a value
// received from a channel.
@@ -278,7 +278,7 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
continue
}
c := event.action.getChannel()
- if _, ok := reflect.NewValue(c).(*reflect.ChanValue); !ok {
+ if reflect.NewValue(c).Kind() != reflect.Chan {
return nil, SetupError("one of the channel values is not a channel")
}
@@ -303,11 +303,11 @@ func getChannels(events []*Event) ([]interface{}, os.Error) {
// channel repeatedly, wrapping them up as either a channelRecv or
// channelClosed structure, and forwards them to the multiplex channel.
func recvValues(multiplex chan<- interface{}, channel interface{}) {
- c := reflect.NewValue(channel).(*reflect.ChanValue)
+ c := reflect.NewValue(channel)
for {
- v := c.Recv()
- if c.Closed() {
+ v, ok := c.Recv()
+ if !ok {
multiplex <- channelClosed{channel}
return
}
diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go
index 324b5a70e..1e65528ef 100644
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -43,12 +43,31 @@ import (
"fmt"
"os"
"runtime"
+ "runtime/pprof"
"time"
)
-// Report as tests are run; default is silent for success.
-var chatty = flag.Bool("test.v", false, "verbose: print additional output")
-var match = flag.String("test.run", "", "regular expression to select tests to run")
+var (
+ // The short flag requests that tests run more quickly, but its functionality
+ // is provided by test writers themselves. The testing package is just its
+ // home. The all.bash installation script sets it to make installation more
+ // efficient, but by default the flag is off so a plain "gotest" will do a
+ // full test of the package.
+ short = flag.Bool("test.short", false, "run smaller test suite to save time")
+
+ // Report as tests are run; default is silent for success.
+ chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ match = flag.String("test.run", "", "regular expression to select tests to run")
+ memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
+ 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")
+)
+
+// Short reports whether the -test.short flag is set.
+func Short() bool {
+ return *short
+}
// Insert final newline if needed and tabs after internal newlines.
@@ -136,8 +155,18 @@ func tRunner(t *T, test *InternalTest) {
// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
-func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
+func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) {
flag.Parse()
+
+ before()
+ startAlarm()
+ RunTests(matchString, tests)
+ stopAlarm()
+ RunBenchmarks(matchString, benchmarks)
+ after()
+}
+
+func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
ok := true
if len(tests) == 0 {
println("testing: warning: no tests to run")
@@ -160,7 +189,7 @@ func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTe
go tRunner(t, &tests[i])
<-t.ch
ns += time.Nanoseconds()
- tstr := fmt.Sprintf("(%.1f seconds)", float64(ns)/1e9)
+ tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
if t.failed {
println("--- FAIL:", tests[i].Name, tstr)
print(t.errors)
@@ -176,3 +205,63 @@ func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTe
}
println("PASS")
}
+
+// before runs before all testing.
+func before() {
+ if *memProfileRate > 0 {
+ runtime.MemProfileRate = *memProfileRate
+ }
+ if *cpuProfile != "" {
+ f, err := os.Create(*cpuProfile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s", err)
+ return
+ }
+ if err := pprof.StartCPUProfile(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+ f.Close()
+ return
+ }
+ // Could save f so after can call f.Close; not worth the effort.
+ }
+
+}
+
+// after runs after all testing.
+func after() {
+ if *cpuProfile != "" {
+ pprof.StopCPUProfile() // flushes profile to disk
+ }
+ if *memProfile != "" {
+ f, err := os.Create(*memProfile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s", err)
+ return
+ }
+ if err = pprof.WriteHeapProfile(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
+ }
+ f.Close()
+ }
+}
+
+var timer *time.Timer
+
+// startAlarm starts an alarm if requested.
+func startAlarm() {
+ if *timeout > 0 {
+ timer = time.AfterFunc(*timeout*1e9, alarm)
+ }
+}
+
+// stopAlarm turns off the alarm.
+func stopAlarm() {
+ if *timeout > 0 {
+ timer.Stop()
+ }
+}
+
+// alarm is called if the timeout expires.
+func alarm() {
+ panic("test timed out")
+}