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