Source file
src/testing/testing.go
Documentation: testing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 package testing
218
219 import (
220 "bytes"
221 "errors"
222 "flag"
223 "fmt"
224 "internal/race"
225 "io"
226 "os"
227 "runtime"
228 "runtime/debug"
229 "runtime/trace"
230 "strconv"
231 "strings"
232 "sync"
233 "sync/atomic"
234 "time"
235 )
236
237 var (
238
239
240
241
242
243 short = flag.Bool("test.short", false, "run smaller test suite to save time")
244
245
246 failFast = flag.Bool("test.failfast", false, "do not start new tests after the first test failure")
247
248
249
250
251
252 outputDir = flag.String("test.outputdir", "", "write profiles to `dir`")
253
254
255 chatty = flag.Bool("test.v", false, "verbose: print additional output")
256 count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
257 coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to `file`")
258 matchList = flag.String("test.list", "", "list tests, examples, and benchmarks matching `regexp` then exit")
259 match = flag.String("test.run", "", "run only tests and examples matching `regexp`")
260 memProfile = flag.String("test.memprofile", "", "write a memory profile to `file`")
261 memProfileRate = flag.Int("test.memprofilerate", 0, "set memory profiling `rate` (see runtime.MemProfileRate)")
262 cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to `file`")
263 blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to `file`")
264 blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
265 mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
266 mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
267 traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
268 timeout = flag.Duration("test.timeout", 0, "panic test binary after duration `d` (default 0, timeout disabled)")
269 cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
270 parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
271 testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)")
272
273 haveExamples bool
274
275 cpuList []int
276 testlogFile *os.File
277
278 numFailed uint32
279 )
280
281
282
283 type common struct {
284 mu sync.RWMutex
285 output []byte
286 w io.Writer
287 ran bool
288 failed bool
289 skipped bool
290 done bool
291 helpers map[string]struct{}
292
293 chatty bool
294 finished bool
295 hasSub int32
296 raceErrors int
297 runner string
298
299 parent *common
300 level int
301 name string
302 start time.Time
303 duration time.Duration
304 barrier chan bool
305 signal chan bool
306 sub []*T
307 }
308
309
310 func Short() bool {
311 return *short
312 }
313
314
315
316
317 func CoverMode() string {
318 return cover.Mode
319 }
320
321
322 func Verbose() bool {
323 return *chatty
324 }
325
326
327
328
329
330
331 func (c *common) frameSkip(skip int) int {
332 if c.helpers == nil {
333 return skip
334 }
335 var pc [50]uintptr
336
337
338 n := runtime.Callers(skip+2, pc[:])
339 if n == 0 {
340 panic("testing: zero callers found")
341 }
342 frames := runtime.CallersFrames(pc[:n])
343 var frame runtime.Frame
344 more := true
345 for i := 0; more; i++ {
346 frame, more = frames.Next()
347 if frame.Function == c.runner {
348
349
350
351
352 return skip + i - 1
353 }
354 if _, ok := c.helpers[frame.Function]; !ok {
355
356 return skip + i
357 }
358 }
359 return skip
360 }
361
362
363
364
365 func (c *common) decorate(s string) string {
366 skip := c.frameSkip(3)
367 _, file, line, ok := runtime.Caller(skip)
368 if ok {
369
370 if index := strings.LastIndex(file, "/"); index >= 0 {
371 file = file[index+1:]
372 } else if index = strings.LastIndex(file, "\\"); index >= 0 {
373 file = file[index+1:]
374 }
375 } else {
376 file = "???"
377 line = 1
378 }
379 buf := new(bytes.Buffer)
380
381 buf.WriteByte('\t')
382 fmt.Fprintf(buf, "%s:%d: ", file, line)
383 lines := strings.Split(s, "\n")
384 if l := len(lines); l > 1 && lines[l-1] == "" {
385 lines = lines[:l-1]
386 }
387 for i, line := range lines {
388 if i > 0 {
389
390 buf.WriteString("\n\t\t")
391 }
392 buf.WriteString(line)
393 }
394 buf.WriteByte('\n')
395 return buf.String()
396 }
397
398
399
400 func (c *common) flushToParent(format string, args ...interface{}) {
401 p := c.parent
402 p.mu.Lock()
403 defer p.mu.Unlock()
404
405 fmt.Fprintf(p.w, format, args...)
406
407 c.mu.Lock()
408 defer c.mu.Unlock()
409 io.Copy(p.w, bytes.NewReader(c.output))
410 c.output = c.output[:0]
411 }
412
413 type indenter struct {
414 c *common
415 }
416
417 func (w indenter) Write(b []byte) (n int, err error) {
418 n = len(b)
419 for len(b) > 0 {
420 end := bytes.IndexByte(b, '\n')
421 if end == -1 {
422 end = len(b)
423 } else {
424 end++
425 }
426
427
428 const indent = " "
429 w.c.output = append(w.c.output, indent...)
430 w.c.output = append(w.c.output, b[:end]...)
431 b = b[end:]
432 }
433 return
434 }
435
436
437 func fmtDuration(d time.Duration) string {
438 return fmt.Sprintf("%.2fs", d.Seconds())
439 }
440
441
442 type TB interface {
443 Error(args ...interface{})
444 Errorf(format string, args ...interface{})
445 Fail()
446 FailNow()
447 Failed() bool
448 Fatal(args ...interface{})
449 Fatalf(format string, args ...interface{})
450 Log(args ...interface{})
451 Logf(format string, args ...interface{})
452 Name() string
453 Skip(args ...interface{})
454 SkipNow()
455 Skipf(format string, args ...interface{})
456 Skipped() bool
457 Helper()
458
459
460
461
462 private()
463 }
464
465 var _ TB = (*T)(nil)
466 var _ TB = (*B)(nil)
467
468
469
470
471
472
473
474
475
476
477
478 type T struct {
479 common
480 isParallel bool
481 context *testContext
482 }
483
484 func (c *common) private() {}
485
486
487 func (c *common) Name() string {
488 return c.name
489 }
490
491 func (c *common) setRan() {
492 if c.parent != nil {
493 c.parent.setRan()
494 }
495 c.mu.Lock()
496 defer c.mu.Unlock()
497 c.ran = true
498 }
499
500
501 func (c *common) Fail() {
502 if c.parent != nil {
503 c.parent.Fail()
504 }
505 c.mu.Lock()
506 defer c.mu.Unlock()
507
508 if c.done {
509 panic("Fail in goroutine after " + c.name + " has completed")
510 }
511 c.failed = true
512 }
513
514
515 func (c *common) Failed() bool {
516 c.mu.RLock()
517 failed := c.failed
518 c.mu.RUnlock()
519 return failed || c.raceErrors+race.Errors() > 0
520 }
521
522
523
524
525
526
527
528
529
530 func (c *common) FailNow() {
531 c.Fail()
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552 c.finished = true
553 runtime.Goexit()
554 }
555
556
557 func (c *common) log(s string) {
558 c.mu.Lock()
559 defer c.mu.Unlock()
560 c.output = append(c.output, c.decorate(s)...)
561 }
562
563
564
565
566
567 func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
568
569
570
571
572
573
574 func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
575
576
577 func (c *common) Error(args ...interface{}) {
578 c.log(fmt.Sprintln(args...))
579 c.Fail()
580 }
581
582
583 func (c *common) Errorf(format string, args ...interface{}) {
584 c.log(fmt.Sprintf(format, args...))
585 c.Fail()
586 }
587
588
589 func (c *common) Fatal(args ...interface{}) {
590 c.log(fmt.Sprintln(args...))
591 c.FailNow()
592 }
593
594
595 func (c *common) Fatalf(format string, args ...interface{}) {
596 c.log(fmt.Sprintf(format, args...))
597 c.FailNow()
598 }
599
600
601 func (c *common) Skip(args ...interface{}) {
602 c.log(fmt.Sprintln(args...))
603 c.SkipNow()
604 }
605
606
607 func (c *common) Skipf(format string, args ...interface{}) {
608 c.log(fmt.Sprintf(format, args...))
609 c.SkipNow()
610 }
611
612
613
614
615
616
617
618
619
620 func (c *common) SkipNow() {
621 c.skip()
622 c.finished = true
623 runtime.Goexit()
624 }
625
626 func (c *common) skip() {
627 c.mu.Lock()
628 defer c.mu.Unlock()
629 c.skipped = true
630 }
631
632
633 func (c *common) Skipped() bool {
634 c.mu.RLock()
635 defer c.mu.RUnlock()
636 return c.skipped
637 }
638
639
640
641
642
643
644 func (c *common) Helper() {
645 c.mu.Lock()
646 defer c.mu.Unlock()
647 if c.helpers == nil {
648 c.helpers = make(map[string]struct{})
649 }
650 c.helpers[callerName(1)] = struct{}{}
651 }
652
653
654
655 func callerName(skip int) string {
656
657 var pc [2]uintptr
658 n := runtime.Callers(skip+2, pc[:])
659 if n == 0 {
660 panic("testing: zero callers found")
661 }
662 frames := runtime.CallersFrames(pc[:n])
663 frame, _ := frames.Next()
664 return frame.Function
665 }
666
667
668
669
670
671 func (t *T) Parallel() {
672 if t.isParallel {
673 panic("testing: t.Parallel called multiple times")
674 }
675 t.isParallel = true
676
677
678
679
680 t.duration += time.Since(t.start)
681
682
683 t.parent.sub = append(t.parent.sub, t)
684 t.raceErrors += race.Errors()
685
686 if t.chatty {
687
688 root := t.parent
689 for ; root.parent != nil; root = root.parent {
690 }
691 root.mu.Lock()
692 fmt.Fprintf(root.w, "=== PAUSE %s\n", t.name)
693 root.mu.Unlock()
694 }
695
696 t.signal <- true
697 <-t.parent.barrier
698 t.context.waitParallel()
699
700 if t.chatty {
701
702 root := t.parent
703 for ; root.parent != nil; root = root.parent {
704 }
705 root.mu.Lock()
706 fmt.Fprintf(root.w, "=== CONT %s\n", t.name)
707 root.mu.Unlock()
708 }
709
710 t.start = time.Now()
711 t.raceErrors += -race.Errors()
712 }
713
714
715
716 type InternalTest struct {
717 Name string
718 F func(*T)
719 }
720
721 func tRunner(t *T, fn func(t *T)) {
722 t.runner = callerName(0)
723
724
725
726
727
728 defer func() {
729 if t.raceErrors+race.Errors() > 0 {
730 t.Errorf("race detected during execution of test")
731 }
732
733 t.duration += time.Since(t.start)
734
735 err := recover()
736 if !t.finished && err == nil {
737 err = fmt.Errorf("test executed panic(nil) or runtime.Goexit")
738 }
739 if err != nil {
740 t.Fail()
741 t.report()
742 panic(err)
743 }
744
745 if len(t.sub) > 0 {
746
747
748 t.context.release()
749
750 close(t.barrier)
751
752 for _, sub := range t.sub {
753 <-sub.signal
754 }
755 if !t.isParallel {
756
757 t.context.waitParallel()
758 }
759 } else if t.isParallel {
760
761
762 t.context.release()
763 }
764 t.report()
765
766
767
768 t.done = true
769 if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 {
770 t.setRan()
771 }
772 t.signal <- true
773 }()
774
775 t.start = time.Now()
776 t.raceErrors = -race.Errors()
777 fn(t)
778
779 if t.failed {
780 atomic.AddUint32(&numFailed, 1)
781 }
782 t.finished = true
783 }
784
785
786
787
788
789
790
791 func (t *T) Run(name string, f func(t *T)) bool {
792 atomic.StoreInt32(&t.hasSub, 1)
793 testName, ok, _ := t.context.match.fullName(&t.common, name)
794 if !ok || shouldFailFast() {
795 return true
796 }
797 t = &T{
798 common: common{
799 barrier: make(chan bool),
800 signal: make(chan bool),
801 name: testName,
802 parent: &t.common,
803 level: t.level + 1,
804 chatty: t.chatty,
805 },
806 context: t.context,
807 }
808 t.w = indenter{&t.common}
809
810 if t.chatty {
811
812 root := t.parent
813 for ; root.parent != nil; root = root.parent {
814 }
815 root.mu.Lock()
816 fmt.Fprintf(root.w, "=== RUN %s\n", t.name)
817 root.mu.Unlock()
818 }
819
820
821
822
823
824 go tRunner(t, f)
825 <-t.signal
826 return !t.failed
827 }
828
829
830
831 type testContext struct {
832 match *matcher
833
834 mu sync.Mutex
835
836
837 startParallel chan bool
838
839
840
841 running int
842
843
844 numWaiting int
845
846
847 maxParallel int
848 }
849
850 func newTestContext(maxParallel int, m *matcher) *testContext {
851 return &testContext{
852 match: m,
853 startParallel: make(chan bool),
854 maxParallel: maxParallel,
855 running: 1,
856 }
857 }
858
859 func (c *testContext) waitParallel() {
860 c.mu.Lock()
861 if c.running < c.maxParallel {
862 c.running++
863 c.mu.Unlock()
864 return
865 }
866 c.numWaiting++
867 c.mu.Unlock()
868 <-c.startParallel
869 }
870
871 func (c *testContext) release() {
872 c.mu.Lock()
873 if c.numWaiting == 0 {
874 c.running--
875 c.mu.Unlock()
876 return
877 }
878 c.numWaiting--
879 c.mu.Unlock()
880 c.startParallel <- true
881 }
882
883
884
885 var errMain = errors.New("testing: unexpected use of func Main")
886
887 type matchStringOnly func(pat, str string) (bool, error)
888
889 func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) }
890 func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain }
891 func (f matchStringOnly) StopCPUProfile() {}
892 func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
893 func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
894 func (f matchStringOnly) ImportPath() string { return "" }
895 func (f matchStringOnly) StartTestLog(io.Writer) {}
896 func (f matchStringOnly) StopTestLog() error { return errMain }
897
898
899
900
901
902
903
904 func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
905 os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
906 }
907
908
909 type M struct {
910 deps testDeps
911 tests []InternalTest
912 benchmarks []InternalBenchmark
913 examples []InternalExample
914
915 timer *time.Timer
916 afterOnce sync.Once
917
918 numRun int
919 }
920
921
922
923
924
925 type testDeps interface {
926 ImportPath() string
927 MatchString(pat, str string) (bool, error)
928 StartCPUProfile(io.Writer) error
929 StopCPUProfile()
930 StartTestLog(io.Writer)
931 StopTestLog() error
932 WriteHeapProfile(io.Writer) error
933 WriteProfileTo(string, io.Writer, int) error
934 }
935
936
937
938
939 func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
940 return &M{
941 deps: deps,
942 tests: tests,
943 benchmarks: benchmarks,
944 examples: examples,
945 }
946 }
947
948
949 func (m *M) Run() int {
950
951
952
953
954 m.numRun++
955
956
957 if !flag.Parsed() {
958 flag.Parse()
959 }
960
961 if *parallel < 1 {
962 fmt.Fprintln(os.Stderr, "testing: -parallel can only be given a positive integer")
963 flag.Usage()
964 return 2
965 }
966
967 if len(*matchList) != 0 {
968 listTests(m.deps.MatchString, m.tests, m.benchmarks, m.examples)
969 return 0
970 }
971
972 parseCpuList()
973
974 m.before()
975 defer m.after()
976 m.startAlarm()
977 haveExamples = len(m.examples) > 0
978 testRan, testOk := runTests(m.deps.MatchString, m.tests)
979 exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
980 m.stopAlarm()
981 if !testRan && !exampleRan && *matchBenchmarks == "" {
982 fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
983 }
984 if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
985 fmt.Println("FAIL")
986 return 1
987 }
988
989 fmt.Println("PASS")
990 return 0
991 }
992
993 func (t *T) report() {
994 if t.parent == nil {
995 return
996 }
997 dstr := fmtDuration(t.duration)
998 format := "--- %s: %s (%s)\n"
999 if t.Failed() {
1000 t.flushToParent(format, "FAIL", t.name, dstr)
1001 } else if t.chatty {
1002 if t.Skipped() {
1003 t.flushToParent(format, "SKIP", t.name, dstr)
1004 } else {
1005 t.flushToParent(format, "PASS", t.name, dstr)
1006 }
1007 }
1008 }
1009
1010 func listTests(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
1011 if _, err := matchString(*matchList, "non-empty"); err != nil {
1012 fmt.Fprintf(os.Stderr, "testing: invalid regexp in -test.list (%q): %s\n", *matchList, err)
1013 os.Exit(1)
1014 }
1015
1016 for _, test := range tests {
1017 if ok, _ := matchString(*matchList, test.Name); ok {
1018 fmt.Println(test.Name)
1019 }
1020 }
1021 for _, bench := range benchmarks {
1022 if ok, _ := matchString(*matchList, bench.Name); ok {
1023 fmt.Println(bench.Name)
1024 }
1025 }
1026 for _, example := range examples {
1027 if ok, _ := matchString(*matchList, example.Name); ok {
1028 fmt.Println(example.Name)
1029 }
1030 }
1031 }
1032
1033
1034
1035 func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
1036 ran, ok := runTests(matchString, tests)
1037 if !ran && !haveExamples {
1038 fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
1039 }
1040 return ok
1041 }
1042
1043 func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
1044 ok = true
1045 for _, procs := range cpuList {
1046 runtime.GOMAXPROCS(procs)
1047 for i := uint(0); i < *count; i++ {
1048 if shouldFailFast() {
1049 break
1050 }
1051 ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
1052 t := &T{
1053 common: common{
1054 signal: make(chan bool),
1055 barrier: make(chan bool),
1056 w: os.Stdout,
1057 chatty: *chatty,
1058 },
1059 context: ctx,
1060 }
1061 tRunner(t, func(t *T) {
1062 for _, test := range tests {
1063 t.Run(test.Name, test.F)
1064 }
1065
1066
1067
1068 go func() { <-t.signal }()
1069 })
1070 ok = ok && !t.Failed()
1071 ran = ran || t.ran
1072 }
1073 }
1074 return ran, ok
1075 }
1076
1077
1078 func (m *M) before() {
1079 if *memProfileRate > 0 {
1080 runtime.MemProfileRate = *memProfileRate
1081 }
1082 if *cpuProfile != "" {
1083 f, err := os.Create(toOutputDir(*cpuProfile))
1084 if err != nil {
1085 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1086 return
1087 }
1088 if err := m.deps.StartCPUProfile(f); err != nil {
1089 fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s\n", err)
1090 f.Close()
1091 return
1092 }
1093
1094 }
1095 if *traceFile != "" {
1096 f, err := os.Create(toOutputDir(*traceFile))
1097 if err != nil {
1098 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1099 return
1100 }
1101 if err := trace.Start(f); err != nil {
1102 fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s\n", err)
1103 f.Close()
1104 return
1105 }
1106
1107 }
1108 if *blockProfile != "" && *blockProfileRate >= 0 {
1109 runtime.SetBlockProfileRate(*blockProfileRate)
1110 }
1111 if *mutexProfile != "" && *mutexProfileFraction >= 0 {
1112 runtime.SetMutexProfileFraction(*mutexProfileFraction)
1113 }
1114 if *coverProfile != "" && cover.Mode == "" {
1115 fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
1116 os.Exit(2)
1117 }
1118 if *testlog != "" {
1119
1120
1121 var f *os.File
1122 var err error
1123 if m.numRun == 1 {
1124 f, err = os.Create(*testlog)
1125 } else {
1126 f, err = os.OpenFile(*testlog, os.O_WRONLY, 0)
1127 if err == nil {
1128 f.Seek(0, io.SeekEnd)
1129 }
1130 }
1131 if err != nil {
1132 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1133 os.Exit(2)
1134 }
1135 m.deps.StartTestLog(f)
1136 testlogFile = f
1137 }
1138 }
1139
1140
1141 func (m *M) after() {
1142 m.afterOnce.Do(func() {
1143 m.writeProfiles()
1144 })
1145 }
1146
1147 func (m *M) writeProfiles() {
1148 if *testlog != "" {
1149 if err := m.deps.StopTestLog(); err != nil {
1150 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
1151 os.Exit(2)
1152 }
1153 if err := testlogFile.Close(); err != nil {
1154 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
1155 os.Exit(2)
1156 }
1157 }
1158 if *cpuProfile != "" {
1159 m.deps.StopCPUProfile()
1160 }
1161 if *traceFile != "" {
1162 trace.Stop()
1163 }
1164 if *memProfile != "" {
1165 f, err := os.Create(toOutputDir(*memProfile))
1166 if err != nil {
1167 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1168 os.Exit(2)
1169 }
1170 runtime.GC()
1171 if err = m.deps.WriteHeapProfile(f); err != nil {
1172 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
1173 os.Exit(2)
1174 }
1175 f.Close()
1176 }
1177 if *blockProfile != "" && *blockProfileRate >= 0 {
1178 f, err := os.Create(toOutputDir(*blockProfile))
1179 if err != nil {
1180 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1181 os.Exit(2)
1182 }
1183 if err = m.deps.WriteProfileTo("block", f, 0); err != nil {
1184 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
1185 os.Exit(2)
1186 }
1187 f.Close()
1188 }
1189 if *mutexProfile != "" && *mutexProfileFraction >= 0 {
1190 f, err := os.Create(toOutputDir(*mutexProfile))
1191 if err != nil {
1192 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1193 os.Exit(2)
1194 }
1195 if err = m.deps.WriteProfileTo("mutex", f, 0); err != nil {
1196 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
1197 os.Exit(2)
1198 }
1199 f.Close()
1200 }
1201 if cover.Mode != "" {
1202 coverReport()
1203 }
1204 }
1205
1206
1207
1208 func toOutputDir(path string) string {
1209 if *outputDir == "" || path == "" {
1210 return path
1211 }
1212 if runtime.GOOS == "windows" {
1213
1214
1215
1216
1217
1218
1219
1220 if len(path) >= 2 {
1221 letter, colon := path[0], path[1]
1222 if ('a' <= letter && letter <= 'z' || 'A' <= letter && letter <= 'Z') && colon == ':' {
1223
1224 return path
1225 }
1226 }
1227 }
1228 if os.IsPathSeparator(path[0]) {
1229 return path
1230 }
1231 return fmt.Sprintf("%s%c%s", *outputDir, os.PathSeparator, path)
1232 }
1233
1234
1235 func (m *M) startAlarm() {
1236 if *timeout > 0 {
1237 m.timer = time.AfterFunc(*timeout, func() {
1238 m.after()
1239 debug.SetTraceback("all")
1240 panic(fmt.Sprintf("test timed out after %v", *timeout))
1241 })
1242 }
1243 }
1244
1245
1246 func (m *M) stopAlarm() {
1247 if *timeout > 0 {
1248 m.timer.Stop()
1249 }
1250 }
1251
1252 func parseCpuList() {
1253 for _, val := range strings.Split(*cpuListStr, ",") {
1254 val = strings.TrimSpace(val)
1255 if val == "" {
1256 continue
1257 }
1258 cpu, err := strconv.Atoi(val)
1259 if err != nil || cpu <= 0 {
1260 fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu\n", val)
1261 os.Exit(1)
1262 }
1263 cpuList = append(cpuList, cpu)
1264 }
1265 if cpuList == nil {
1266 cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
1267 }
1268 }
1269
1270 func shouldFailFast() bool {
1271 return *failFast && atomic.LoadUint32(&numFailed) > 0
1272 }
1273
View as plain text