OSDN Git Service

PR go/48242
[pf3gnuchains/gcc-fork.git] / libgo / go / testing / testing.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // The testing package provides support for automated testing of Go packages.
6 // It is intended to be used in concert with the ``gotest'' utility, which automates
7 // execution of any function of the form
8 //     func TestXxx(*testing.T)
9 // where Xxx can be any alphanumeric string (but the first letter must not be in
10 // [a-z]) and serves to identify the test routine.
11 // These TestXxx routines should be declared within the package they are testing.
12 //
13 // Functions of the form
14 //     func BenchmarkXxx(*testing.B)
15 // are considered benchmarks, and are executed by gotest when the -test.bench
16 // flag is provided.
17 //
18 // A sample benchmark function looks like this:
19 //     func BenchmarkHello(b *testing.B) {
20 //         for i := 0; i < b.N; i++ {
21 //             fmt.Sprintf("hello")
22 //         }
23 //     }
24 // The benchmark package will vary b.N until the benchmark function lasts
25 // long enough to be timed reliably.  The output
26 //     testing.BenchmarkHello   500000        4076 ns/op
27 // means that the loop ran 500000 times at a speed of 4076 ns per loop.
28 //
29 // If a benchmark needs some expensive setup before running, the timer
30 // may be stopped:
31 //     func BenchmarkBigLen(b *testing.B) {
32 //         b.StopTimer()
33 //         big := NewBig()
34 //         b.StartTimer()
35 //         for i := 0; i < b.N; i++ {
36 //             big.Len()
37 //         }
38 //     }
39 package testing
40
41 import (
42         "flag"
43         "fmt"
44         "os"
45         "runtime"
46         "runtime/pprof"
47         "time"
48 )
49
50 var (
51         // The short flag requests that tests run more quickly, but its functionality
52         // is provided by test writers themselves.  The testing package is just its
53         // home.  The all.bash installation script sets it to make installation more
54         // efficient, but by default the flag is off so a plain "gotest" will do a
55         // full test of the package.
56         short = flag.Bool("test.short", false, "run smaller test suite to save time")
57
58         // Report as tests are run; default is silent for success.
59         chatty         = flag.Bool("test.v", false, "verbose: print additional output")
60         match          = flag.String("test.run", "", "regular expression to select tests to run")
61         memProfile     = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
62         memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
63         cpuProfile     = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
64         timeout        = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
65 )
66
67 // Short reports whether the -test.short flag is set.
68 func Short() bool {
69         return *short
70 }
71
72
73 // Insert final newline if needed and tabs after internal newlines.
74 func tabify(s string) string {
75         n := len(s)
76         if n > 0 && s[n-1] != '\n' {
77                 s += "\n"
78                 n++
79         }
80         for i := 0; i < n-1; i++ { // -1 to avoid final newline
81                 if s[i] == '\n' {
82                         return s[0:i+1] + "\t" + tabify(s[i+1:n])
83                 }
84         }
85         return s
86 }
87
88 // T is a type passed to Test functions to manage test state and support formatted test logs.
89 // Logs are accumulated during execution and dumped to standard error when done.
90 type T struct {
91         errors string
92         failed bool
93         ch     chan *T
94 }
95
96 // Fail marks the Test function as having failed but continues execution.
97 func (t *T) Fail() { t.failed = true }
98
99 // Failed returns whether the Test function has failed.
100 func (t *T) Failed() bool { return t.failed }
101
102 // FailNow marks the Test function as having failed and stops its execution.
103 // Execution will continue at the next Test.
104 func (t *T) FailNow() {
105         t.Fail()
106         t.ch <- t
107         runtime.Goexit()
108 }
109
110 // Log formats its arguments using default formatting, analogous to Print(),
111 // and records the text in the error log.
112 func (t *T) Log(args ...interface{}) { t.errors += "\t" + tabify(fmt.Sprintln(args...)) }
113
114 // Logf formats its arguments according to the format, analogous to Printf(),
115 // and records the text in the error log.
116 func (t *T) Logf(format string, args ...interface{}) {
117         t.errors += "\t" + tabify(fmt.Sprintf(format, args...))
118 }
119
120 // Error is equivalent to Log() followed by Fail().
121 func (t *T) Error(args ...interface{}) {
122         t.Log(args...)
123         t.Fail()
124 }
125
126 // Errorf is equivalent to Logf() followed by Fail().
127 func (t *T) Errorf(format string, args ...interface{}) {
128         t.Logf(format, args...)
129         t.Fail()
130 }
131
132 // Fatal is equivalent to Log() followed by FailNow().
133 func (t *T) Fatal(args ...interface{}) {
134         t.Log(args...)
135         t.FailNow()
136 }
137
138 // Fatalf is equivalent to Logf() followed by FailNow().
139 func (t *T) Fatalf(format string, args ...interface{}) {
140         t.Logf(format, args...)
141         t.FailNow()
142 }
143
144 // An internal type but exported because it is cross-package; part of the implementation
145 // of gotest.
146 type InternalTest struct {
147         Name string
148         F    func(*T)
149 }
150
151 func tRunner(t *T, test *InternalTest) {
152         test.F(t)
153         t.ch <- t
154 }
155
156 // An internal function but exported because it is cross-package; part of the implementation
157 // of gotest.
158 func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) {
159         flag.Parse()
160
161         before()
162         startAlarm()
163         RunTests(matchString, tests)
164         stopAlarm()
165         RunBenchmarks(matchString, benchmarks)
166         after()
167 }
168
169 func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
170         ok := true
171         if len(tests) == 0 {
172                 println("testing: warning: no tests to run")
173         }
174         for i := 0; i < len(tests); i++ {
175                 matched, err := matchString(*match, tests[i].Name)
176                 if err != nil {
177                         println("invalid regexp for -test.run:", err.String())
178                         os.Exit(1)
179                 }
180                 if !matched {
181                         continue
182                 }
183                 if *chatty {
184                         println("=== RUN ", tests[i].Name)
185                 }
186                 ns := -time.Nanoseconds()
187                 t := new(T)
188                 t.ch = make(chan *T)
189                 go tRunner(t, &tests[i])
190                 <-t.ch
191                 ns += time.Nanoseconds()
192                 tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
193                 if t.failed {
194                         println("--- FAIL:", tests[i].Name, tstr)
195                         print(t.errors)
196                         ok = false
197                 } else if *chatty {
198                         println("--- PASS:", tests[i].Name, tstr)
199                         print(t.errors)
200                 }
201         }
202         if !ok {
203                 println("FAIL")
204                 os.Exit(1)
205         }
206         println("PASS")
207 }
208
209 // before runs before all testing.
210 func before() {
211         if *memProfileRate > 0 {
212                 runtime.MemProfileRate = *memProfileRate
213         }
214         if *cpuProfile != "" {
215                 f, err := os.Open(*cpuProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
216                 if err != nil {
217                         fmt.Fprintf(os.Stderr, "testing: %s", err)
218                         return
219                 }
220                 if err := pprof.StartCPUProfile(f); err != nil {
221                         fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
222                         f.Close()
223                         return
224                 }
225                 // Could save f so after can call f.Close; not worth the effort.
226         }
227
228 }
229
230 // after runs after all testing.
231 func after() {
232         if *cpuProfile != "" {
233                 pprof.StopCPUProfile() // flushes profile to disk
234         }
235         if *memProfile != "" {
236                 f, err := os.Open(*memProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
237                 if err != nil {
238                         fmt.Fprintf(os.Stderr, "testing: %s", err)
239                         return
240                 }
241                 if err = pprof.WriteHeapProfile(f); err != nil {
242                         fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
243                 }
244                 f.Close()
245         }
246 }
247
248 var timer *time.Timer
249
250 // startAlarm starts an alarm if requested.
251 func startAlarm() {
252         if *timeout > 0 {
253                 timer = time.AfterFunc(*timeout*1e9, alarm)
254         }
255 }
256
257 // stopAlarm turns off the alarm.
258 func stopAlarm() {
259         if *timeout > 0 {
260                 timer.Stop()
261         }
262 }
263
264 // alarm is called if the timeout expires.
265 func alarm() {
266         panic("test timed out")
267 }