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