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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 package testing
239
240 import (
241 "bytes"
242 "errors"
243 "flag"
244 "fmt"
245 "internal/race"
246 "io"
247 "math/rand"
248 "os"
249 "runtime"
250 "runtime/debug"
251 "runtime/trace"
252 "strconv"
253 "strings"
254 "sync"
255 "sync/atomic"
256 "time"
257 "unicode"
258 "unicode/utf8"
259 )
260
261 var initRan bool
262
263
264
265
266
267
268 func Init() {
269 if initRan {
270 return
271 }
272 initRan = true
273
274
275
276
277
278 short = flag.Bool("test.short", false, "run smaller test suite to save time")
279
280
281 failFast = flag.Bool("test.failfast", false, "do not start new tests after the first test failure")
282
283
284
285
286
287 outputDir = flag.String("test.outputdir", "", "write profiles to `dir`")
288
289 chatty = flag.Bool("test.v", false, "verbose: print additional output")
290 count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
291 coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to `file`")
292 matchList = flag.String("test.list", "", "list tests, examples, and benchmarks matching `regexp` then exit")
293 match = flag.String("test.run", "", "run only tests and examples matching `regexp`")
294 memProfile = flag.String("test.memprofile", "", "write an allocation profile to `file`")
295 memProfileRate = flag.Int("test.memprofilerate", 0, "set memory allocation profiling `rate` (see runtime.MemProfileRate)")
296 cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to `file`")
297 blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to `file`")
298 blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
299 mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
300 mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
301 panicOnExit0 = flag.Bool("test.paniconexit0", false, "panic on call to os.Exit(0)")
302 traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
303 timeout = flag.Duration("test.timeout", 0, "panic test binary after duration `d` (default 0, timeout disabled)")
304 cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
305 parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
306 testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)")
307 shuffle = flag.String("test.shuffle", "off", "randomize the execution order of tests and benchmarks")
308
309 initBenchmarkFlags()
310 }
311
312 var (
313
314 short *bool
315 failFast *bool
316 outputDir *string
317 chatty *bool
318 count *uint
319 coverProfile *string
320 matchList *string
321 match *string
322 memProfile *string
323 memProfileRate *int
324 cpuProfile *string
325 blockProfile *string
326 blockProfileRate *int
327 mutexProfile *string
328 mutexProfileFraction *int
329 panicOnExit0 *bool
330 traceFile *string
331 timeout *time.Duration
332 cpuListStr *string
333 parallel *int
334 shuffle *string
335 testlog *string
336
337 haveExamples bool
338
339 cpuList []int
340 testlogFile *os.File
341
342 numFailed uint32
343 )
344
345 type chattyPrinter struct {
346 w io.Writer
347 lastNameMu sync.Mutex
348 lastName string
349 }
350
351 func newChattyPrinter(w io.Writer) *chattyPrinter {
352 return &chattyPrinter{w: w}
353 }
354
355
356
357
358 func (p *chattyPrinter) Updatef(testName, format string, args ...interface{}) {
359 p.lastNameMu.Lock()
360 defer p.lastNameMu.Unlock()
361
362
363
364
365
366 p.lastName = testName
367 fmt.Fprintf(p.w, format, args...)
368 }
369
370
371
372 func (p *chattyPrinter) Printf(testName, format string, args ...interface{}) {
373 p.lastNameMu.Lock()
374 defer p.lastNameMu.Unlock()
375
376 if p.lastName == "" {
377 p.lastName = testName
378 } else if p.lastName != testName {
379 fmt.Fprintf(p.w, "=== CONT %s\n", testName)
380 p.lastName = testName
381 }
382
383 fmt.Fprintf(p.w, format, args...)
384 }
385
386
387
388 const maxStackLen = 50
389
390
391
392 type common struct {
393 mu sync.RWMutex
394 output []byte
395 w io.Writer
396 ran bool
397 failed bool
398 skipped bool
399 done bool
400 helperPCs map[uintptr]struct{}
401 helperNames map[string]struct{}
402 cleanups []func()
403 cleanupName string
404 cleanupPc []uintptr
405 finished bool
406
407 chatty *chattyPrinter
408 bench bool
409 hasSub int32
410 raceErrors int
411 runner string
412
413 parent *common
414 level int
415 creator []uintptr
416 name string
417 start time.Time
418 duration time.Duration
419 barrier chan bool
420 signal chan bool
421 sub []*T
422
423 tempDirMu sync.Mutex
424 tempDir string
425 tempDirErr error
426 tempDirSeq int32
427 }
428
429
430 func Short() bool {
431 if short == nil {
432 panic("testing: Short called before Init")
433 }
434
435 if !flag.Parsed() {
436 panic("testing: Short called before Parse")
437 }
438
439 return *short
440 }
441
442
443
444
445 func CoverMode() string {
446 return cover.Mode
447 }
448
449
450 func Verbose() bool {
451
452 if chatty == nil {
453 panic("testing: Verbose called before Init")
454 }
455 if !flag.Parsed() {
456 panic("testing: Verbose called before Parse")
457 }
458 return *chatty
459 }
460
461
462
463
464
465
466 func (c *common) frameSkip(skip int) runtime.Frame {
467
468
469 shouldUnlock := false
470 defer func() {
471 if shouldUnlock {
472 c.mu.Unlock()
473 }
474 }()
475 var pc [maxStackLen]uintptr
476
477
478 n := runtime.Callers(skip+2, pc[:])
479 if n == 0 {
480 panic("testing: zero callers found")
481 }
482 frames := runtime.CallersFrames(pc[:n])
483 var firstFrame, prevFrame, frame runtime.Frame
484 for more := true; more; prevFrame = frame {
485 frame, more = frames.Next()
486 if frame.Function == c.cleanupName {
487 frames = runtime.CallersFrames(c.cleanupPc)
488 continue
489 }
490 if firstFrame.PC == 0 {
491 firstFrame = frame
492 }
493 if frame.Function == c.runner {
494
495
496
497
498
499
500 if c.level > 1 {
501 frames = runtime.CallersFrames(c.creator)
502 parent := c.parent
503
504
505
506 if shouldUnlock {
507 c.mu.Unlock()
508 }
509 c = parent
510
511
512
513 shouldUnlock = true
514 c.mu.Lock()
515 continue
516 }
517 return prevFrame
518 }
519
520 if c.helperNames == nil {
521 c.helperNames = make(map[string]struct{})
522 for pc := range c.helperPCs {
523 c.helperNames[pcToName(pc)] = struct{}{}
524 }
525 }
526 if _, ok := c.helperNames[frame.Function]; !ok {
527
528 return frame
529 }
530 }
531 return firstFrame
532 }
533
534
535
536
537 func (c *common) decorate(s string, skip int) string {
538 frame := c.frameSkip(skip)
539 file := frame.File
540 line := frame.Line
541 if file != "" {
542
543 if index := strings.LastIndex(file, "/"); index >= 0 {
544 file = file[index+1:]
545 } else if index = strings.LastIndex(file, "\\"); index >= 0 {
546 file = file[index+1:]
547 }
548 } else {
549 file = "???"
550 }
551 if line == 0 {
552 line = 1
553 }
554 buf := new(strings.Builder)
555
556 buf.WriteString(" ")
557 fmt.Fprintf(buf, "%s:%d: ", file, line)
558 lines := strings.Split(s, "\n")
559 if l := len(lines); l > 1 && lines[l-1] == "" {
560 lines = lines[:l-1]
561 }
562 for i, line := range lines {
563 if i > 0 {
564
565 buf.WriteString("\n ")
566 }
567 buf.WriteString(line)
568 }
569 buf.WriteByte('\n')
570 return buf.String()
571 }
572
573
574
575 func (c *common) flushToParent(testName, format string, args ...interface{}) {
576 p := c.parent
577 p.mu.Lock()
578 defer p.mu.Unlock()
579
580 c.mu.Lock()
581 defer c.mu.Unlock()
582
583 if len(c.output) > 0 {
584 format += "%s"
585 args = append(args[:len(args):len(args)], c.output)
586 c.output = c.output[:0]
587 }
588
589 if c.chatty != nil && p.w == c.chatty.w {
590
591
592
593
594
595
596
597
598
599 c.chatty.Updatef(testName, format, args...)
600 } else {
601
602
603 fmt.Fprintf(p.w, format, args...)
604 }
605 }
606
607 type indenter struct {
608 c *common
609 }
610
611 func (w indenter) Write(b []byte) (n int, err error) {
612 n = len(b)
613 for len(b) > 0 {
614 end := bytes.IndexByte(b, '\n')
615 if end == -1 {
616 end = len(b)
617 } else {
618 end++
619 }
620
621
622 const indent = " "
623 w.c.output = append(w.c.output, indent...)
624 w.c.output = append(w.c.output, b[:end]...)
625 b = b[end:]
626 }
627 return
628 }
629
630
631 func fmtDuration(d time.Duration) string {
632 return fmt.Sprintf("%.2fs", d.Seconds())
633 }
634
635
636 type TB interface {
637 Cleanup(func())
638 Error(args ...interface{})
639 Errorf(format string, args ...interface{})
640 Fail()
641 FailNow()
642 Failed() bool
643 Fatal(args ...interface{})
644 Fatalf(format string, args ...interface{})
645 Helper()
646 Log(args ...interface{})
647 Logf(format string, args ...interface{})
648 Name() string
649 Setenv(key, value string)
650 Skip(args ...interface{})
651 SkipNow()
652 Skipf(format string, args ...interface{})
653 Skipped() bool
654 TempDir() string
655
656
657
658
659 private()
660 }
661
662 var _ TB = (*T)(nil)
663 var _ TB = (*B)(nil)
664
665
666
667
668
669
670
671
672
673
674 type T struct {
675 common
676 isParallel bool
677 isEnvSet bool
678 context *testContext
679 }
680
681 func (c *common) private() {}
682
683
684
685
686
687
688 func (c *common) Name() string {
689 return c.name
690 }
691
692 func (c *common) setRan() {
693 if c.parent != nil {
694 c.parent.setRan()
695 }
696 c.mu.Lock()
697 defer c.mu.Unlock()
698 c.ran = true
699 }
700
701
702 func (c *common) Fail() {
703 if c.parent != nil {
704 c.parent.Fail()
705 }
706 c.mu.Lock()
707 defer c.mu.Unlock()
708
709 if c.done {
710 panic("Fail in goroutine after " + c.name + " has completed")
711 }
712 c.failed = true
713 }
714
715
716 func (c *common) Failed() bool {
717 c.mu.RLock()
718 failed := c.failed
719 c.mu.RUnlock()
720 return failed || c.raceErrors+race.Errors() > 0
721 }
722
723
724
725
726
727
728
729
730
731 func (c *common) FailNow() {
732 c.Fail()
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753 c.mu.Lock()
754 c.finished = true
755 c.mu.Unlock()
756 runtime.Goexit()
757 }
758
759
760 func (c *common) log(s string) {
761 c.logDepth(s, 3)
762 }
763
764
765 func (c *common) logDepth(s string, depth int) {
766 c.mu.Lock()
767 defer c.mu.Unlock()
768 if c.done {
769
770
771 for parent := c.parent; parent != nil; parent = parent.parent {
772 parent.mu.Lock()
773 defer parent.mu.Unlock()
774 if !parent.done {
775 parent.output = append(parent.output, parent.decorate(s, depth+1)...)
776 return
777 }
778 }
779 panic("Log in goroutine after " + c.name + " has completed: " + s)
780 } else {
781 if c.chatty != nil {
782 if c.bench {
783
784
785 fmt.Print(c.decorate(s, depth+1))
786 } else {
787 c.chatty.Printf(c.name, "%s", c.decorate(s, depth+1))
788 }
789
790 return
791 }
792 c.output = append(c.output, c.decorate(s, depth+1)...)
793 }
794 }
795
796
797
798
799
800 func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
801
802
803
804
805
806
807 func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
808
809
810 func (c *common) Error(args ...interface{}) {
811 c.log(fmt.Sprintln(args...))
812 c.Fail()
813 }
814
815
816 func (c *common) Errorf(format string, args ...interface{}) {
817 c.log(fmt.Sprintf(format, args...))
818 c.Fail()
819 }
820
821
822 func (c *common) Fatal(args ...interface{}) {
823 c.log(fmt.Sprintln(args...))
824 c.FailNow()
825 }
826
827
828 func (c *common) Fatalf(format string, args ...interface{}) {
829 c.log(fmt.Sprintf(format, args...))
830 c.FailNow()
831 }
832
833
834 func (c *common) Skip(args ...interface{}) {
835 c.log(fmt.Sprintln(args...))
836 c.SkipNow()
837 }
838
839
840 func (c *common) Skipf(format string, args ...interface{}) {
841 c.log(fmt.Sprintf(format, args...))
842 c.SkipNow()
843 }
844
845
846
847
848
849
850
851
852
853 func (c *common) SkipNow() {
854 c.mu.Lock()
855 c.skipped = true
856 c.finished = true
857 c.mu.Unlock()
858 runtime.Goexit()
859 }
860
861
862 func (c *common) Skipped() bool {
863 c.mu.RLock()
864 defer c.mu.RUnlock()
865 return c.skipped
866 }
867
868
869
870
871 func (c *common) Helper() {
872 c.mu.Lock()
873 defer c.mu.Unlock()
874 if c.helperPCs == nil {
875 c.helperPCs = make(map[uintptr]struct{})
876 }
877
878 var pc [1]uintptr
879 n := runtime.Callers(2, pc[:])
880 if n == 0 {
881 panic("testing: zero callers found")
882 }
883 if _, found := c.helperPCs[pc[0]]; !found {
884 c.helperPCs[pc[0]] = struct{}{}
885 c.helperNames = nil
886 }
887 }
888
889
890
891
892 func (c *common) Cleanup(f func()) {
893 var pc [maxStackLen]uintptr
894
895 n := runtime.Callers(2, pc[:])
896 cleanupPc := pc[:n]
897
898 fn := func() {
899 defer func() {
900 c.mu.Lock()
901 defer c.mu.Unlock()
902 c.cleanupName = ""
903 c.cleanupPc = nil
904 }()
905
906 name := callerName(0)
907 c.mu.Lock()
908 c.cleanupName = name
909 c.cleanupPc = cleanupPc
910 c.mu.Unlock()
911
912 f()
913 }
914
915 c.mu.Lock()
916 defer c.mu.Unlock()
917 c.cleanups = append(c.cleanups, fn)
918 }
919
920
921
922
923
924
925 func (c *common) TempDir() string {
926
927
928 c.tempDirMu.Lock()
929 var nonExistent bool
930 if c.tempDir == "" {
931 nonExistent = true
932 } else {
933 _, err := os.Stat(c.tempDir)
934 nonExistent = os.IsNotExist(err)
935 if err != nil && !nonExistent {
936 c.Fatalf("TempDir: %v", err)
937 }
938 }
939
940 if nonExistent {
941 c.Helper()
942
943
944
945
946 mapper := func(r rune) rune {
947 if r < utf8.RuneSelf {
948 const allowed = "!#$%&()+,-.=@^_{}~ "
949 if '0' <= r && r <= '9' ||
950 'a' <= r && r <= 'z' ||
951 'A' <= r && r <= 'Z' {
952 return r
953 }
954 if strings.ContainsRune(allowed, r) {
955 return r
956 }
957 } else if unicode.IsLetter(r) || unicode.IsNumber(r) {
958 return r
959 }
960 return -1
961 }
962 pattern := strings.Map(mapper, c.Name())
963 c.tempDir, c.tempDirErr = os.MkdirTemp("", pattern)
964 if c.tempDirErr == nil {
965 c.Cleanup(func() {
966 if err := os.RemoveAll(c.tempDir); err != nil {
967 c.Errorf("TempDir RemoveAll cleanup: %v", err)
968 }
969 })
970 }
971 }
972 c.tempDirMu.Unlock()
973
974 if c.tempDirErr != nil {
975 c.Fatalf("TempDir: %v", c.tempDirErr)
976 }
977 seq := atomic.AddInt32(&c.tempDirSeq, 1)
978 dir := fmt.Sprintf("%s%c%03d", c.tempDir, os.PathSeparator, seq)
979 if err := os.Mkdir(dir, 0777); err != nil {
980 c.Fatalf("TempDir: %v", err)
981 }
982 return dir
983 }
984
985
986
987
988
989
990 func (c *common) Setenv(key, value string) {
991 prevValue, ok := os.LookupEnv(key)
992
993 if err := os.Setenv(key, value); err != nil {
994 c.Fatalf("cannot set environment variable: %v", err)
995 }
996
997 if ok {
998 c.Cleanup(func() {
999 os.Setenv(key, prevValue)
1000 })
1001 } else {
1002 c.Cleanup(func() {
1003 os.Unsetenv(key)
1004 })
1005 }
1006 }
1007
1008
1009 type panicHandling int
1010
1011 const (
1012 normalPanic panicHandling = iota
1013 recoverAndReturnPanic
1014 )
1015
1016
1017
1018
1019 func (c *common) runCleanup(ph panicHandling) (panicVal interface{}) {
1020 if ph == recoverAndReturnPanic {
1021 defer func() {
1022 panicVal = recover()
1023 }()
1024 }
1025
1026
1027
1028 defer func() {
1029 c.mu.Lock()
1030 recur := len(c.cleanups) > 0
1031 c.mu.Unlock()
1032 if recur {
1033 c.runCleanup(normalPanic)
1034 }
1035 }()
1036
1037 for {
1038 var cleanup func()
1039 c.mu.Lock()
1040 if len(c.cleanups) > 0 {
1041 last := len(c.cleanups) - 1
1042 cleanup = c.cleanups[last]
1043 c.cleanups = c.cleanups[:last]
1044 }
1045 c.mu.Unlock()
1046 if cleanup == nil {
1047 return nil
1048 }
1049 cleanup()
1050 }
1051 }
1052
1053
1054
1055 func callerName(skip int) string {
1056 var pc [1]uintptr
1057 n := runtime.Callers(skip+2, pc[:])
1058 if n == 0 {
1059 panic("testing: zero callers found")
1060 }
1061 return pcToName(pc[0])
1062 }
1063
1064 func pcToName(pc uintptr) string {
1065 pcs := []uintptr{pc}
1066 frames := runtime.CallersFrames(pcs)
1067 frame, _ := frames.Next()
1068 return frame.Function
1069 }
1070
1071
1072
1073
1074
1075 func (t *T) Parallel() {
1076 if t.isParallel {
1077 panic("testing: t.Parallel called multiple times")
1078 }
1079 if t.isEnvSet {
1080 panic("testing: t.Parallel called after t.Setenv; cannot set environment variables in parallel tests")
1081 }
1082 t.isParallel = true
1083
1084
1085
1086
1087 t.duration += time.Since(t.start)
1088
1089
1090 t.parent.sub = append(t.parent.sub, t)
1091 t.raceErrors += race.Errors()
1092
1093 if t.chatty != nil {
1094
1095
1096
1097
1098
1099
1100 t.chatty.Updatef(t.name, "=== PAUSE %s\n", t.name)
1101 }
1102
1103 t.signal <- true
1104 <-t.parent.barrier
1105 t.context.waitParallel()
1106
1107 if t.chatty != nil {
1108 t.chatty.Updatef(t.name, "=== CONT %s\n", t.name)
1109 }
1110
1111 t.start = time.Now()
1112 t.raceErrors += -race.Errors()
1113 }
1114
1115
1116
1117
1118
1119
1120 func (t *T) Setenv(key, value string) {
1121 if t.isParallel {
1122 panic("testing: t.Setenv called after t.Parallel; cannot set environment variables in parallel tests")
1123 }
1124
1125 t.isEnvSet = true
1126
1127 t.common.Setenv(key, value)
1128 }
1129
1130
1131
1132 type InternalTest struct {
1133 Name string
1134 F func(*T)
1135 }
1136
1137 var errNilPanicOrGoexit = errors.New("test executed panic(nil) or runtime.Goexit")
1138
1139 func tRunner(t *T, fn func(t *T)) {
1140 t.runner = callerName(0)
1141
1142
1143
1144
1145
1146 defer func() {
1147 if t.Failed() {
1148 atomic.AddUint32(&numFailed, 1)
1149 }
1150
1151 if t.raceErrors+race.Errors() > 0 {
1152 t.Errorf("race detected during execution of test")
1153 }
1154
1155
1156 err := recover()
1157 signal := true
1158
1159 t.mu.RLock()
1160 finished := t.finished
1161 t.mu.RUnlock()
1162 if !finished && err == nil {
1163 err = errNilPanicOrGoexit
1164 for p := t.parent; p != nil; p = p.parent {
1165 p.mu.RLock()
1166 finished = p.finished
1167 p.mu.RUnlock()
1168 if finished {
1169 t.Errorf("%v: subtest may have called FailNow on a parent test", err)
1170 err = nil
1171 signal = false
1172 break
1173 }
1174 }
1175 }
1176
1177
1178 didPanic := false
1179 defer func() {
1180 if didPanic {
1181 return
1182 }
1183 if err != nil {
1184 panic(err)
1185 }
1186
1187
1188
1189 t.signal <- signal
1190 }()
1191
1192 doPanic := func(err interface{}) {
1193 t.Fail()
1194 if r := t.runCleanup(recoverAndReturnPanic); r != nil {
1195 t.Logf("cleanup panicked with %v", r)
1196 }
1197
1198 for root := &t.common; root.parent != nil; root = root.parent {
1199 root.mu.Lock()
1200 root.duration += time.Since(root.start)
1201 d := root.duration
1202 root.mu.Unlock()
1203 root.flushToParent(root.name, "--- FAIL: %s (%s)\n", root.name, fmtDuration(d))
1204 if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
1205 fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
1206 }
1207 }
1208 didPanic = true
1209 panic(err)
1210 }
1211 if err != nil {
1212 doPanic(err)
1213 }
1214
1215 t.duration += time.Since(t.start)
1216
1217 if len(t.sub) > 0 {
1218
1219
1220 t.context.release()
1221
1222 close(t.barrier)
1223
1224 for _, sub := range t.sub {
1225 <-sub.signal
1226 }
1227 cleanupStart := time.Now()
1228 err := t.runCleanup(recoverAndReturnPanic)
1229 t.duration += time.Since(cleanupStart)
1230 if err != nil {
1231 doPanic(err)
1232 }
1233 if !t.isParallel {
1234
1235 t.context.waitParallel()
1236 }
1237 } else if t.isParallel {
1238
1239
1240 t.context.release()
1241 }
1242 t.report()
1243
1244
1245
1246 t.done = true
1247 if t.parent != nil && atomic.LoadInt32(&t.hasSub) == 0 {
1248 t.setRan()
1249 }
1250 }()
1251 defer func() {
1252 if len(t.sub) == 0 {
1253 t.runCleanup(normalPanic)
1254 }
1255 }()
1256
1257 t.start = time.Now()
1258 t.raceErrors = -race.Errors()
1259 fn(t)
1260
1261
1262 t.mu.Lock()
1263 t.finished = true
1264 t.mu.Unlock()
1265 }
1266
1267
1268
1269
1270
1271
1272
1273 func (t *T) Run(name string, f func(t *T)) bool {
1274 atomic.StoreInt32(&t.hasSub, 1)
1275 testName, ok, _ := t.context.match.fullName(&t.common, name)
1276 if !ok || shouldFailFast() {
1277 return true
1278 }
1279
1280
1281
1282 var pc [maxStackLen]uintptr
1283 n := runtime.Callers(2, pc[:])
1284 t = &T{
1285 common: common{
1286 barrier: make(chan bool),
1287 signal: make(chan bool, 1),
1288 name: testName,
1289 parent: &t.common,
1290 level: t.level + 1,
1291 creator: pc[:n],
1292 chatty: t.chatty,
1293 },
1294 context: t.context,
1295 }
1296 t.w = indenter{&t.common}
1297
1298 if t.chatty != nil {
1299 t.chatty.Updatef(t.name, "=== RUN %s\n", t.name)
1300 }
1301
1302
1303
1304
1305
1306 go tRunner(t, f)
1307 if !<-t.signal {
1308
1309
1310 runtime.Goexit()
1311 }
1312 return !t.failed
1313 }
1314
1315
1316
1317
1318
1319 func (t *T) Deadline() (deadline time.Time, ok bool) {
1320 deadline = t.context.deadline
1321 return deadline, !deadline.IsZero()
1322 }
1323
1324
1325
1326 type testContext struct {
1327 match *matcher
1328 deadline time.Time
1329
1330 mu sync.Mutex
1331
1332
1333 startParallel chan bool
1334
1335
1336
1337 running int
1338
1339
1340 numWaiting int
1341
1342
1343 maxParallel int
1344 }
1345
1346 func newTestContext(maxParallel int, m *matcher) *testContext {
1347 return &testContext{
1348 match: m,
1349 startParallel: make(chan bool),
1350 maxParallel: maxParallel,
1351 running: 1,
1352 }
1353 }
1354
1355 func (c *testContext) waitParallel() {
1356 c.mu.Lock()
1357 if c.running < c.maxParallel {
1358 c.running++
1359 c.mu.Unlock()
1360 return
1361 }
1362 c.numWaiting++
1363 c.mu.Unlock()
1364 <-c.startParallel
1365 }
1366
1367 func (c *testContext) release() {
1368 c.mu.Lock()
1369 if c.numWaiting == 0 {
1370 c.running--
1371 c.mu.Unlock()
1372 return
1373 }
1374 c.numWaiting--
1375 c.mu.Unlock()
1376 c.startParallel <- true
1377 }
1378
1379
1380
1381 var errMain = errors.New("testing: unexpected use of func Main")
1382
1383 type matchStringOnly func(pat, str string) (bool, error)
1384
1385 func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) }
1386 func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain }
1387 func (f matchStringOnly) StopCPUProfile() {}
1388 func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
1389 func (f matchStringOnly) ImportPath() string { return "" }
1390 func (f matchStringOnly) StartTestLog(io.Writer) {}
1391 func (f matchStringOnly) StopTestLog() error { return errMain }
1392 func (f matchStringOnly) SetPanicOnExit0(bool) {}
1393
1394
1395
1396
1397
1398
1399
1400 func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
1401 os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
1402 }
1403
1404
1405 type M struct {
1406 deps testDeps
1407 tests []InternalTest
1408 benchmarks []InternalBenchmark
1409 examples []InternalExample
1410
1411 timer *time.Timer
1412 afterOnce sync.Once
1413
1414 numRun int
1415
1416
1417
1418 exitCode int
1419 }
1420
1421
1422
1423
1424
1425 type testDeps interface {
1426 ImportPath() string
1427 MatchString(pat, str string) (bool, error)
1428 SetPanicOnExit0(bool)
1429 StartCPUProfile(io.Writer) error
1430 StopCPUProfile()
1431 StartTestLog(io.Writer)
1432 StopTestLog() error
1433 WriteProfileTo(string, io.Writer, int) error
1434 }
1435
1436
1437
1438
1439 func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
1440 Init()
1441 return &M{
1442 deps: deps,
1443 tests: tests,
1444 benchmarks: benchmarks,
1445 examples: examples,
1446 }
1447 }
1448
1449
1450 func (m *M) Run() (code int) {
1451 defer func() {
1452 code = m.exitCode
1453 }()
1454
1455
1456
1457
1458
1459 m.numRun++
1460
1461
1462 if !flag.Parsed() {
1463 flag.Parse()
1464 }
1465
1466 if *parallel < 1 {
1467 fmt.Fprintln(os.Stderr, "testing: -parallel can only be given a positive integer")
1468 flag.Usage()
1469 m.exitCode = 2
1470 return
1471 }
1472
1473 if len(*matchList) != 0 {
1474 listTests(m.deps.MatchString, m.tests, m.benchmarks, m.examples)
1475 m.exitCode = 0
1476 return
1477 }
1478
1479 if *shuffle != "off" {
1480 var n int64
1481 var err error
1482 if *shuffle == "on" {
1483 n = time.Now().UnixNano()
1484 } else {
1485 n, err = strconv.ParseInt(*shuffle, 10, 64)
1486 if err != nil {
1487 fmt.Fprintln(os.Stderr, `testing: -shuffle should be "off", "on", or a valid integer:`, err)
1488 m.exitCode = 2
1489 return
1490 }
1491 }
1492 fmt.Println("-test.shuffle", n)
1493 rng := rand.New(rand.NewSource(n))
1494 rng.Shuffle(len(m.tests), func(i, j int) { m.tests[i], m.tests[j] = m.tests[j], m.tests[i] })
1495 rng.Shuffle(len(m.benchmarks), func(i, j int) { m.benchmarks[i], m.benchmarks[j] = m.benchmarks[j], m.benchmarks[i] })
1496 }
1497
1498 parseCpuList()
1499
1500 m.before()
1501 defer m.after()
1502 deadline := m.startAlarm()
1503 haveExamples = len(m.examples) > 0
1504 testRan, testOk := runTests(m.deps.MatchString, m.tests, deadline)
1505 exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
1506 m.stopAlarm()
1507 if !testRan && !exampleRan && *matchBenchmarks == "" {
1508 fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
1509 }
1510 if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
1511 fmt.Println("FAIL")
1512 m.exitCode = 1
1513 return
1514 }
1515
1516 fmt.Println("PASS")
1517 m.exitCode = 0
1518 return
1519 }
1520
1521 func (t *T) report() {
1522 if t.parent == nil {
1523 return
1524 }
1525 dstr := fmtDuration(t.duration)
1526 format := "--- %s: %s (%s)\n"
1527 if t.Failed() {
1528 t.flushToParent(t.name, format, "FAIL", t.name, dstr)
1529 } else if t.chatty != nil {
1530 if t.Skipped() {
1531 t.flushToParent(t.name, format, "SKIP", t.name, dstr)
1532 } else {
1533 t.flushToParent(t.name, format, "PASS", t.name, dstr)
1534 }
1535 }
1536 }
1537
1538 func listTests(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
1539 if _, err := matchString(*matchList, "non-empty"); err != nil {
1540 fmt.Fprintf(os.Stderr, "testing: invalid regexp in -test.list (%q): %s\n", *matchList, err)
1541 os.Exit(1)
1542 }
1543
1544 for _, test := range tests {
1545 if ok, _ := matchString(*matchList, test.Name); ok {
1546 fmt.Println(test.Name)
1547 }
1548 }
1549 for _, bench := range benchmarks {
1550 if ok, _ := matchString(*matchList, bench.Name); ok {
1551 fmt.Println(bench.Name)
1552 }
1553 }
1554 for _, example := range examples {
1555 if ok, _ := matchString(*matchList, example.Name); ok {
1556 fmt.Println(example.Name)
1557 }
1558 }
1559 }
1560
1561
1562
1563 func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
1564 var deadline time.Time
1565 if *timeout > 0 {
1566 deadline = time.Now().Add(*timeout)
1567 }
1568 ran, ok := runTests(matchString, tests, deadline)
1569 if !ran && !haveExamples {
1570 fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
1571 }
1572 return ok
1573 }
1574
1575 func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest, deadline time.Time) (ran, ok bool) {
1576 ok = true
1577 for _, procs := range cpuList {
1578 runtime.GOMAXPROCS(procs)
1579 for i := uint(0); i < *count; i++ {
1580 if shouldFailFast() {
1581 break
1582 }
1583 ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
1584 ctx.deadline = deadline
1585 t := &T{
1586 common: common{
1587 signal: make(chan bool, 1),
1588 barrier: make(chan bool),
1589 w: os.Stdout,
1590 },
1591 context: ctx,
1592 }
1593 if Verbose() {
1594 t.chatty = newChattyPrinter(t.w)
1595 }
1596 tRunner(t, func(t *T) {
1597 for _, test := range tests {
1598 t.Run(test.Name, test.F)
1599 }
1600 })
1601 select {
1602 case <-t.signal:
1603 default:
1604 panic("internal error: tRunner exited without sending on t.signal")
1605 }
1606 ok = ok && !t.Failed()
1607 ran = ran || t.ran
1608 }
1609 }
1610 return ran, ok
1611 }
1612
1613
1614 func (m *M) before() {
1615 if *memProfileRate > 0 {
1616 runtime.MemProfileRate = *memProfileRate
1617 }
1618 if *cpuProfile != "" {
1619 f, err := os.Create(toOutputDir(*cpuProfile))
1620 if err != nil {
1621 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1622 return
1623 }
1624 if err := m.deps.StartCPUProfile(f); err != nil {
1625 fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s\n", err)
1626 f.Close()
1627 return
1628 }
1629
1630 }
1631 if *traceFile != "" {
1632 f, err := os.Create(toOutputDir(*traceFile))
1633 if err != nil {
1634 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1635 return
1636 }
1637 if err := trace.Start(f); err != nil {
1638 fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s\n", err)
1639 f.Close()
1640 return
1641 }
1642
1643 }
1644 if *blockProfile != "" && *blockProfileRate >= 0 {
1645 runtime.SetBlockProfileRate(*blockProfileRate)
1646 }
1647 if *mutexProfile != "" && *mutexProfileFraction >= 0 {
1648 runtime.SetMutexProfileFraction(*mutexProfileFraction)
1649 }
1650 if *coverProfile != "" && cover.Mode == "" {
1651 fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
1652 os.Exit(2)
1653 }
1654 if *testlog != "" {
1655
1656
1657 var f *os.File
1658 var err error
1659 if m.numRun == 1 {
1660 f, err = os.Create(*testlog)
1661 } else {
1662 f, err = os.OpenFile(*testlog, os.O_WRONLY, 0)
1663 if err == nil {
1664 f.Seek(0, io.SeekEnd)
1665 }
1666 }
1667 if err != nil {
1668 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1669 os.Exit(2)
1670 }
1671 m.deps.StartTestLog(f)
1672 testlogFile = f
1673 }
1674 if *panicOnExit0 {
1675 m.deps.SetPanicOnExit0(true)
1676 }
1677 }
1678
1679
1680 func (m *M) after() {
1681 m.afterOnce.Do(func() {
1682 m.writeProfiles()
1683 })
1684
1685
1686
1687
1688 if *panicOnExit0 {
1689 m.deps.SetPanicOnExit0(false)
1690 }
1691 }
1692
1693 func (m *M) writeProfiles() {
1694 if *testlog != "" {
1695 if err := m.deps.StopTestLog(); err != nil {
1696 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
1697 os.Exit(2)
1698 }
1699 if err := testlogFile.Close(); err != nil {
1700 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
1701 os.Exit(2)
1702 }
1703 }
1704 if *cpuProfile != "" {
1705 m.deps.StopCPUProfile()
1706 }
1707 if *traceFile != "" {
1708 trace.Stop()
1709 }
1710 if *memProfile != "" {
1711 f, err := os.Create(toOutputDir(*memProfile))
1712 if err != nil {
1713 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1714 os.Exit(2)
1715 }
1716 runtime.GC()
1717 if err = m.deps.WriteProfileTo("allocs", f, 0); err != nil {
1718 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
1719 os.Exit(2)
1720 }
1721 f.Close()
1722 }
1723 if *blockProfile != "" && *blockProfileRate >= 0 {
1724 f, err := os.Create(toOutputDir(*blockProfile))
1725 if err != nil {
1726 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1727 os.Exit(2)
1728 }
1729 if err = m.deps.WriteProfileTo("block", f, 0); err != nil {
1730 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
1731 os.Exit(2)
1732 }
1733 f.Close()
1734 }
1735 if *mutexProfile != "" && *mutexProfileFraction >= 0 {
1736 f, err := os.Create(toOutputDir(*mutexProfile))
1737 if err != nil {
1738 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
1739 os.Exit(2)
1740 }
1741 if err = m.deps.WriteProfileTo("mutex", f, 0); err != nil {
1742 fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *mutexProfile, err)
1743 os.Exit(2)
1744 }
1745 f.Close()
1746 }
1747 if cover.Mode != "" {
1748 coverReport()
1749 }
1750 }
1751
1752
1753
1754 func toOutputDir(path string) string {
1755 if *outputDir == "" || path == "" {
1756 return path
1757 }
1758
1759
1760
1761
1762
1763
1764
1765 if runtime.GOOS == "windows" && len(path) >= 2 {
1766 letter, colon := path[0], path[1]
1767 if ('a' <= letter && letter <= 'z' || 'A' <= letter && letter <= 'Z') && colon == ':' {
1768
1769 return path
1770 }
1771 }
1772 if os.IsPathSeparator(path[0]) {
1773 return path
1774 }
1775 return fmt.Sprintf("%s%c%s", *outputDir, os.PathSeparator, path)
1776 }
1777
1778
1779 func (m *M) startAlarm() time.Time {
1780 if *timeout <= 0 {
1781 return time.Time{}
1782 }
1783
1784 deadline := time.Now().Add(*timeout)
1785 m.timer = time.AfterFunc(*timeout, func() {
1786 m.after()
1787 debug.SetTraceback("all")
1788 panic(fmt.Sprintf("test timed out after %v", *timeout))
1789 })
1790 return deadline
1791 }
1792
1793
1794 func (m *M) stopAlarm() {
1795 if *timeout > 0 {
1796 m.timer.Stop()
1797 }
1798 }
1799
1800 func parseCpuList() {
1801 for _, val := range strings.Split(*cpuListStr, ",") {
1802 val = strings.TrimSpace(val)
1803 if val == "" {
1804 continue
1805 }
1806 cpu, err := strconv.Atoi(val)
1807 if err != nil || cpu <= 0 {
1808 fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu\n", val)
1809 os.Exit(1)
1810 }
1811 cpuList = append(cpuList, cpu)
1812 }
1813 if cpuList == nil {
1814 cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
1815 }
1816 }
1817
1818 func shouldFailFast() bool {
1819 return *failFast && atomic.LoadUint32(&numFailed) > 0
1820 }
1821
View as plain text