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