1
2
3
4
5 package load
6
7 import (
8 "bytes"
9 "context"
10 "errors"
11 "fmt"
12 "go/ast"
13 "go/build"
14 "go/doc"
15 "go/parser"
16 "go/token"
17 "internal/lazytemplate"
18 "path/filepath"
19 "slices"
20 "sort"
21 "strings"
22 "unicode"
23 "unicode/utf8"
24
25 "cmd/go/internal/cfg"
26 "cmd/go/internal/fsys"
27 "cmd/go/internal/str"
28 "cmd/go/internal/trace"
29 )
30
31 var TestMainDeps = []string{
32
33 "os",
34 "reflect",
35 "testing",
36 "testing/internal/testdeps",
37 }
38
39 type TestCover struct {
40 Mode string
41 Local bool
42 Pkgs []*Package
43 Paths []string
44 Vars []coverInfo
45 }
46
47
48
49
50 func TestPackagesFor(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
51 pmain, ptest, pxtest = TestPackagesAndErrors(ctx, nil, opts, p, cover)
52 for _, p1 := range []*Package{ptest, pxtest, pmain} {
53 if p1 == nil {
54
55 continue
56 }
57 if p1.Error != nil {
58 err = p1.Error
59 break
60 }
61 if p1.Incomplete {
62 ps := PackageList([]*Package{p1})
63 for _, p := range ps {
64 if p.Error != nil {
65 err = p.Error
66 break
67 }
68 }
69 break
70 }
71 }
72 if pmain.Error != nil || pmain.Incomplete {
73 pmain = nil
74 }
75 if ptest.Error != nil || ptest.Incomplete {
76 ptest = nil
77 }
78 if pxtest != nil && (pxtest.Error != nil || pxtest.Incomplete) {
79 pxtest = nil
80 }
81 return pmain, ptest, pxtest, err
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
102 ctx, span := trace.StartSpan(ctx, "load.TestPackagesAndErrors")
103 defer span.Done()
104
105 pre := newPreload()
106 defer pre.flush()
107 allImports := append([]string{}, p.TestImports...)
108 allImports = append(allImports, p.XTestImports...)
109 pre.preloadImports(ctx, opts, allImports, p.Internal.Build)
110
111 var ptestErr, pxtestErr *PackageError
112 var imports, ximports []*Package
113 var stk ImportStack
114 var testEmbed, xtestEmbed map[string][]string
115 var incomplete bool
116 stk.Push(p.ImportPath + " (test)")
117 rawTestImports := str.StringList(p.TestImports)
118 for i, path := range p.TestImports {
119 p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
120 if err != nil && ptestErr == nil {
121 ptestErr = err
122 incomplete = true
123 }
124 if p1.Incomplete {
125 incomplete = true
126 }
127 p.TestImports[i] = p1.ImportPath
128 imports = append(imports, p1)
129 }
130 var err error
131 p.TestEmbedFiles, testEmbed, err = resolveEmbed(p.Dir, p.TestEmbedPatterns)
132 if err != nil {
133 ptestErr = &PackageError{
134 ImportStack: stk.Copy(),
135 Err: err,
136 }
137 incomplete = true
138 embedErr := err.(*EmbedError)
139 ptestErr.setPos(p.Internal.Build.TestEmbedPatternPos[embedErr.Pattern])
140 }
141 stk.Pop()
142
143 stk.Push(p.ImportPath + "_test")
144 pxtestNeedsPtest := false
145 var pxtestIncomplete bool
146 rawXTestImports := str.StringList(p.XTestImports)
147 for i, path := range p.XTestImports {
148 p1, err := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
149 if err != nil && pxtestErr == nil {
150 pxtestErr = err
151 }
152 if p1.Incomplete {
153 pxtestIncomplete = true
154 }
155 if p1.ImportPath == p.ImportPath {
156 pxtestNeedsPtest = true
157 } else {
158 ximports = append(ximports, p1)
159 }
160 p.XTestImports[i] = p1.ImportPath
161 }
162 p.XTestEmbedFiles, xtestEmbed, err = resolveEmbed(p.Dir, p.XTestEmbedPatterns)
163 if err != nil && pxtestErr == nil {
164 pxtestErr = &PackageError{
165 ImportStack: stk.Copy(),
166 Err: err,
167 }
168 embedErr := err.(*EmbedError)
169 pxtestErr.setPos(p.Internal.Build.XTestEmbedPatternPos[embedErr.Pattern])
170 }
171 pxtestIncomplete = pxtestIncomplete || pxtestErr != nil
172 stk.Pop()
173
174
175 if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
176 ptest = new(Package)
177 *ptest = *p
178 ptest.Error = ptestErr
179 ptest.Incomplete = incomplete
180 ptest.ForTest = p.ImportPath
181 ptest.GoFiles = nil
182 ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
183 ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
184 ptest.Target = ""
185
186
187
188
189
190
191
192
193
194
195
196
197 ptest.Imports = str.StringList(p.TestImports, p.Imports)
198 ptest.Internal.Imports = append(imports, p.Internal.Imports...)
199 ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
200 ptest.Internal.ForceLibrary = true
201 ptest.Internal.BuildInfo = nil
202 ptest.Internal.Build = new(build.Package)
203 *ptest.Internal.Build = *p.Internal.Build
204 m := map[string][]token.Position{}
205 for k, v := range p.Internal.Build.ImportPos {
206 m[k] = append(m[k], v...)
207 }
208 for k, v := range p.Internal.Build.TestImportPos {
209 m[k] = append(m[k], v...)
210 }
211 ptest.Internal.Build.ImportPos = m
212 if testEmbed == nil && len(p.Internal.Embed) > 0 {
213 testEmbed = map[string][]string{}
214 }
215 for k, v := range p.Internal.Embed {
216 testEmbed[k] = v
217 }
218 ptest.Internal.Embed = testEmbed
219 ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles)
220 ptest.Internal.OrigImportPath = p.Internal.OrigImportPath
221 ptest.Internal.PGOProfile = p.Internal.PGOProfile
222 ptest.Internal.Build.Directives = append(slices.Clip(p.Internal.Build.Directives), p.Internal.Build.TestDirectives...)
223 } else {
224 ptest = p
225 }
226
227
228 if len(p.XTestGoFiles) > 0 {
229 pxtest = &Package{
230 PackagePublic: PackagePublic{
231 Name: p.Name + "_test",
232 ImportPath: p.ImportPath + "_test",
233 Root: p.Root,
234 Dir: p.Dir,
235 Goroot: p.Goroot,
236 GoFiles: p.XTestGoFiles,
237 Imports: p.XTestImports,
238 ForTest: p.ImportPath,
239 Module: p.Module,
240 Error: pxtestErr,
241 Incomplete: pxtestIncomplete,
242 EmbedFiles: p.XTestEmbedFiles,
243 },
244 Internal: PackageInternal{
245 LocalPrefix: p.Internal.LocalPrefix,
246 Build: &build.Package{
247 ImportPos: p.Internal.Build.XTestImportPos,
248 Directives: p.Internal.Build.XTestDirectives,
249 },
250 Imports: ximports,
251 RawImports: rawXTestImports,
252
253 Asmflags: p.Internal.Asmflags,
254 Gcflags: p.Internal.Gcflags,
255 Ldflags: p.Internal.Ldflags,
256 Gccgoflags: p.Internal.Gccgoflags,
257 Embed: xtestEmbed,
258 OrigImportPath: p.Internal.OrigImportPath,
259 PGOProfile: p.Internal.PGOProfile,
260 },
261 }
262 if pxtestNeedsPtest {
263 pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
264 }
265 }
266
267
268 ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
269 gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
270
271
272 pmain = &Package{
273 PackagePublic: PackagePublic{
274 Name: "main",
275 Dir: p.Dir,
276 GoFiles: []string{"_testmain.go"},
277 ImportPath: p.ImportPath + ".test",
278 Root: p.Root,
279 Imports: str.StringList(TestMainDeps),
280 Module: p.Module,
281 },
282 Internal: PackageInternal{
283 Build: &build.Package{Name: "main"},
284 BuildInfo: p.Internal.BuildInfo,
285 Asmflags: p.Internal.Asmflags,
286 Gcflags: p.Internal.Gcflags,
287 Ldflags: ldflags,
288 Gccgoflags: gccgoflags,
289 OrigImportPath: p.Internal.OrigImportPath,
290 PGOProfile: p.Internal.PGOProfile,
291 },
292 }
293
294 pb := p.Internal.Build
295 pmain.DefaultGODEBUG = defaultGODEBUG(pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
296
297
298
299 stk.Push("testmain")
300 deps := TestMainDeps
301 if cover != nil && cfg.Experiment.CoverageRedesign {
302 deps = append(deps, "internal/coverage/cfile")
303 }
304 ldDeps, err := LinkerDeps(p)
305 if err != nil && pmain.Error == nil {
306 pmain.Error = &PackageError{Err: err}
307 }
308 for _, d := range ldDeps {
309 deps = append(deps, d)
310 }
311 for _, dep := range deps {
312 if dep == ptest.ImportPath {
313 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
314 } else {
315 p1, err := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0)
316 if err != nil && pmain.Error == nil {
317 pmain.Error = err
318 pmain.Incomplete = true
319 }
320 pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
321 }
322 }
323 stk.Pop()
324
325 parallelizablePart := func() {
326 if cover != nil && cover.Pkgs != nil && !cfg.Experiment.CoverageRedesign {
327
328 seen := map[*Package]bool{p: true, ptest: true}
329 for _, p1 := range pmain.Internal.Imports {
330 seen[p1] = true
331 }
332 for _, p1 := range cover.Pkgs {
333 if seen[p1] {
334
335 continue
336 }
337 seen[p1] = true
338 pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
339 }
340 }
341
342 allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports))
343 allTestImports = append(allTestImports, pmain.Internal.Imports...)
344 allTestImports = append(allTestImports, imports...)
345 allTestImports = append(allTestImports, ximports...)
346 setToolFlags(allTestImports...)
347
348
349
350
351
352 t, err := loadTestFuncs(p)
353 if err != nil && pmain.Error == nil {
354 pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
355 }
356 t.Cover = cover
357 if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
358 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
359 pmain.Imports = append(pmain.Imports, ptest.ImportPath)
360 t.ImportTest = true
361 }
362 if pxtest != nil {
363 pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
364 pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
365 t.ImportXtest = true
366 }
367
368
369
370 sort.Strings(pmain.Imports)
371 w := 0
372 for _, path := range pmain.Imports {
373 if w == 0 || path != pmain.Imports[w-1] {
374 pmain.Imports[w] = path
375 w++
376 }
377 }
378 pmain.Imports = pmain.Imports[:w]
379 pmain.Internal.RawImports = str.StringList(pmain.Imports)
380
381
382 cycleErr := recompileForTest(pmain, p, ptest, pxtest)
383 if cycleErr != nil {
384 ptest.Error = cycleErr
385 ptest.Incomplete = true
386 }
387
388 if cover != nil {
389 if cfg.Experiment.CoverageRedesign {
390
391
392
393
394 ptest.Internal.Cover.Mode = p.Internal.Cover.Mode
395 pmain.Internal.Cover.Mode = "testmain"
396 }
397
398
399
400
401 if cover.Local {
402 ptest.Internal.Cover.Mode = cover.Mode
403
404 if !cfg.Experiment.CoverageRedesign {
405 var coverFiles []string
406 coverFiles = append(coverFiles, ptest.GoFiles...)
407 coverFiles = append(coverFiles, ptest.CgoFiles...)
408 ptest.Internal.CoverVars = DeclareCoverVars(ptest, coverFiles...)
409 }
410 }
411
412 if !cfg.Experiment.CoverageRedesign {
413 for _, cp := range pmain.Internal.Imports {
414 if len(cp.Internal.CoverVars) > 0 {
415 t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars})
416 }
417 }
418 }
419 }
420
421 data, err := formatTestmain(t)
422 if err != nil && pmain.Error == nil {
423 pmain.Error = &PackageError{Err: err}
424 pmain.Incomplete = true
425 }
426
427
428 pmain.Internal.TestmainGo = &data
429 }
430
431 if done != nil {
432 go func() {
433 parallelizablePart()
434 done()
435 }()
436 } else {
437 parallelizablePart()
438 }
439
440 return pmain, ptest, pxtest
441 }
442
443
444
445
446
447
448
449
450
451
452 func recompileForTest(pmain, preal, ptest, pxtest *Package) *PackageError {
453
454
455
456 testCopy := map[*Package]*Package{preal: ptest}
457 for _, p := range PackageList([]*Package{pmain}) {
458 if p == preal {
459 continue
460 }
461
462 didSplit := p == pmain || p == pxtest || p == ptest
463 split := func() {
464 if didSplit {
465 return
466 }
467 didSplit = true
468 if testCopy[p] != nil {
469 panic("recompileForTest loop")
470 }
471 p1 := new(Package)
472 testCopy[p] = p1
473 *p1 = *p
474 p1.ForTest = preal.ImportPath
475 p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
476 copy(p1.Internal.Imports, p.Internal.Imports)
477 p1.Imports = make([]string, len(p.Imports))
478 copy(p1.Imports, p.Imports)
479 p = p1
480 p.Target = ""
481 p.Internal.BuildInfo = nil
482 p.Internal.ForceLibrary = true
483 p.Internal.PGOProfile = preal.Internal.PGOProfile
484 }
485
486
487 for i, imp := range p.Internal.Imports {
488 if p1 := testCopy[imp]; p1 != nil && p1 != imp {
489 split()
490
491
492
493
494 p.Internal.Imports[i] = p1
495 }
496 }
497
498
499
500
501
502
503
504 if p.Name == "main" && p != pmain && p != ptest {
505 split()
506 }
507
508
509 if preal.Internal.PGOProfile != "" && p.Internal.PGOProfile == "" {
510 split()
511 }
512 }
513
514
515
516 importerOf := map[*Package]*Package{}
517 for _, p := range ptest.Internal.Imports {
518 importerOf[p] = nil
519 }
520
521
522
523
524
525
526
527
528
529
530
531 q := slices.Clip(ptest.Internal.Imports)
532 for len(q) > 0 {
533 p := q[0]
534 q = q[1:]
535 if p == ptest {
536
537
538
539 var stk []string
540 for p != nil {
541 stk = append(stk, p.ImportPath)
542 p = importerOf[p]
543 }
544
545
546
547
548
549 stk = append(stk, ptest.ImportPath)
550 slices.Reverse(stk)
551
552 return &PackageError{
553 ImportStack: stk,
554 Err: errors.New("import cycle not allowed in test"),
555 IsImportCycle: true,
556 }
557 }
558 for _, dep := range p.Internal.Imports {
559 if _, ok := importerOf[dep]; !ok {
560 importerOf[dep] = p
561 q = append(q, dep)
562 }
563 }
564 }
565
566 return nil
567 }
568
569
570
571 func isTestFunc(fn *ast.FuncDecl, arg string) bool {
572 if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
573 fn.Type.Params.List == nil ||
574 len(fn.Type.Params.List) != 1 ||
575 len(fn.Type.Params.List[0].Names) > 1 {
576 return false
577 }
578 ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
579 if !ok {
580 return false
581 }
582
583
584
585
586 if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
587 return true
588 }
589 if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
590 return true
591 }
592 return false
593 }
594
595
596
597
598 func isTest(name, prefix string) bool {
599 if !strings.HasPrefix(name, prefix) {
600 return false
601 }
602 if len(name) == len(prefix) {
603 return true
604 }
605 rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
606 return !unicode.IsLower(rune)
607 }
608
609 type coverInfo struct {
610 Package *Package
611 Vars map[string]*CoverVar
612 }
613
614
615
616
617 func loadTestFuncs(ptest *Package) (*testFuncs, error) {
618 t := &testFuncs{
619 Package: ptest,
620 }
621 var err error
622 for _, file := range ptest.TestGoFiles {
623 if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
624 err = lerr
625 }
626 }
627 for _, file := range ptest.XTestGoFiles {
628 if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
629 err = lerr
630 }
631 }
632 return t, err
633 }
634
635
636 func formatTestmain(t *testFuncs) ([]byte, error) {
637 var buf bytes.Buffer
638 tmpl := testmainTmpl
639 if cfg.Experiment.CoverageRedesign {
640 tmpl = testmainTmplNewCoverage
641 }
642 if err := tmpl.Execute(&buf, t); err != nil {
643 return nil, err
644 }
645 return buf.Bytes(), nil
646 }
647
648 type testFuncs struct {
649 Tests []testFunc
650 Benchmarks []testFunc
651 FuzzTargets []testFunc
652 Examples []testFunc
653 TestMain *testFunc
654 Package *Package
655 ImportTest bool
656 NeedTest bool
657 ImportXtest bool
658 NeedXtest bool
659 Cover *TestCover
660 }
661
662
663
664 func (t *testFuncs) ImportPath() string {
665 pkg := t.Package.ImportPath
666 if strings.HasPrefix(pkg, "_/") {
667 return ""
668 }
669 if pkg == "command-line-arguments" {
670 return ""
671 }
672 return pkg
673 }
674
675
676
677
678
679 func (t *testFuncs) Covered() string {
680 if t.Cover == nil || t.Cover.Paths == nil {
681 return ""
682 }
683 return " in " + strings.Join(t.Cover.Paths, ", ")
684 }
685
686 func (t *testFuncs) CoverSelectedPackages() string {
687 if t.Cover == nil || t.Cover.Paths == nil {
688 return `[]string{"` + t.Package.ImportPath + `"}`
689 }
690 var sb strings.Builder
691 fmt.Fprintf(&sb, "[]string{")
692 for k, p := range t.Cover.Pkgs {
693 if k != 0 {
694 sb.WriteString(", ")
695 }
696 fmt.Fprintf(&sb, `"%s"`, p.ImportPath)
697 }
698 sb.WriteString("}")
699 return sb.String()
700 }
701
702
703 func (t *testFuncs) Tested() string {
704 return t.Package.Name
705 }
706
707 type testFunc struct {
708 Package string
709 Name string
710 Output string
711 Unordered bool
712 }
713
714 var testFileSet = token.NewFileSet()
715
716 func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
717
718 src, err := fsys.Open(filename)
719 if err != nil {
720 return err
721 }
722 defer src.Close()
723 f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments|parser.SkipObjectResolution)
724 if err != nil {
725 return err
726 }
727 for _, d := range f.Decls {
728 n, ok := d.(*ast.FuncDecl)
729 if !ok {
730 continue
731 }
732 if n.Recv != nil {
733 continue
734 }
735 name := n.Name.String()
736 switch {
737 case name == "TestMain":
738 if isTestFunc(n, "T") {
739 t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
740 *doImport, *seen = true, true
741 continue
742 }
743 err := checkTestFunc(n, "M")
744 if err != nil {
745 return err
746 }
747 if t.TestMain != nil {
748 return errors.New("multiple definitions of TestMain")
749 }
750 t.TestMain = &testFunc{pkg, name, "", false}
751 *doImport, *seen = true, true
752 case isTest(name, "Test"):
753 err := checkTestFunc(n, "T")
754 if err != nil {
755 return err
756 }
757 t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
758 *doImport, *seen = true, true
759 case isTest(name, "Benchmark"):
760 err := checkTestFunc(n, "B")
761 if err != nil {
762 return err
763 }
764 t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
765 *doImport, *seen = true, true
766 case isTest(name, "Fuzz"):
767 err := checkTestFunc(n, "F")
768 if err != nil {
769 return err
770 }
771 t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false})
772 *doImport, *seen = true, true
773 }
774 }
775 ex := doc.Examples(f)
776 sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
777 for _, e := range ex {
778 *doImport = true
779 if e.Output == "" && !e.EmptyOutput {
780
781 continue
782 }
783 t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
784 *seen = true
785 }
786 return nil
787 }
788
789 func checkTestFunc(fn *ast.FuncDecl, arg string) error {
790 var why string
791 if !isTestFunc(fn, arg) {
792 why = fmt.Sprintf("must be: func %s(%s *testing.%s)", fn.Name.String(), strings.ToLower(arg), arg)
793 }
794 if fn.Type.TypeParams.NumFields() > 0 {
795 why = "test functions cannot have type parameters"
796 }
797 if why != "" {
798 pos := testFileSet.Position(fn.Pos())
799 return fmt.Errorf("%s: wrong signature for %s, %s", pos, fn.Name.String(), why)
800 }
801 return nil
802 }
803
804 var testmainTmpl = lazytemplate.New("main", `
805 // Code generated by 'go test'. DO NOT EDIT.
806
807 package main
808
809 import (
810 "os"
811 {{if .TestMain}}
812 "reflect"
813 {{end}}
814 "testing"
815 "testing/internal/testdeps"
816
817 {{if .ImportTest}}
818 {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
819 {{end}}
820 {{if .ImportXtest}}
821 {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
822 {{end}}
823 {{if .Cover}}
824 {{range $i, $p := .Cover.Vars}}
825 _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
826 {{end}}
827 {{end}}
828 )
829
830 var tests = []testing.InternalTest{
831 {{range .Tests}}
832 {"{{.Name}}", {{.Package}}.{{.Name}}},
833 {{end}}
834 }
835
836 var benchmarks = []testing.InternalBenchmark{
837 {{range .Benchmarks}}
838 {"{{.Name}}", {{.Package}}.{{.Name}}},
839 {{end}}
840 }
841
842 var fuzzTargets = []testing.InternalFuzzTarget{
843 {{range .FuzzTargets}}
844 {"{{.Name}}", {{.Package}}.{{.Name}}},
845 {{end}}
846 }
847
848 var examples = []testing.InternalExample{
849 {{range .Examples}}
850 {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
851 {{end}}
852 }
853
854 func init() {
855 testdeps.ImportPath = {{.ImportPath | printf "%q"}}
856 }
857
858 {{if .Cover}}
859
860 // Only updated by init functions, so no need for atomicity.
861 var (
862 coverCounters = make(map[string][]uint32)
863 coverBlocks = make(map[string][]testing.CoverBlock)
864 )
865
866 func init() {
867 {{range $i, $p := .Cover.Vars}}
868 {{range $file, $cover := $p.Vars}}
869 coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
870 {{end}}
871 {{end}}
872 }
873
874 func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
875 if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
876 panic("coverage: mismatched sizes")
877 }
878 if coverCounters[fileName] != nil {
879 // Already registered.
880 return
881 }
882 coverCounters[fileName] = counter
883 block := make([]testing.CoverBlock, len(counter))
884 for i := range counter {
885 block[i] = testing.CoverBlock{
886 Line0: pos[3*i+0],
887 Col0: uint16(pos[3*i+2]),
888 Line1: pos[3*i+1],
889 Col1: uint16(pos[3*i+2]>>16),
890 Stmts: numStmts[i],
891 }
892 }
893 coverBlocks[fileName] = block
894 }
895 {{end}}
896
897 func main() {
898 {{if .Cover}}
899 testing.RegisterCover(testing.Cover{
900 Mode: {{printf "%q" .Cover.Mode}},
901 Counters: coverCounters,
902 Blocks: coverBlocks,
903 CoveredPackages: {{printf "%q" .Covered}},
904 })
905 {{end}}
906 m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
907 {{with .TestMain}}
908 {{.Package}}.{{.Name}}(m)
909 os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
910 {{else}}
911 os.Exit(m.Run())
912 {{end}}
913 }
914
915 `)
916
917 var testmainTmplNewCoverage = lazytemplate.New("main", `
918 // Code generated by 'go test'. DO NOT EDIT.
919
920 package main
921
922 import (
923 "os"
924 {{if .TestMain}}
925 "reflect"
926 {{end}}
927 "testing"
928 "testing/internal/testdeps"
929 {{if .Cover}}
930 "internal/coverage/cfile"
931 {{end}}
932
933 {{if .ImportTest}}
934 {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
935 {{end}}
936 {{if .ImportXtest}}
937 {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
938 {{end}}
939 )
940
941 var tests = []testing.InternalTest{
942 {{range .Tests}}
943 {"{{.Name}}", {{.Package}}.{{.Name}}},
944 {{end}}
945 }
946
947 var benchmarks = []testing.InternalBenchmark{
948 {{range .Benchmarks}}
949 {"{{.Name}}", {{.Package}}.{{.Name}}},
950 {{end}}
951 }
952
953 var fuzzTargets = []testing.InternalFuzzTarget{
954 {{range .FuzzTargets}}
955 {"{{.Name}}", {{.Package}}.{{.Name}}},
956 {{end}}
957 }
958
959 var examples = []testing.InternalExample{
960 {{range .Examples}}
961 {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
962 {{end}}
963 }
964
965 func init() {
966 {{if .Cover}}
967 testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
968 testdeps.Covered = {{printf "%q" .Covered}}
969 testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
970 testdeps.CoverSnapshotFunc = cfile.Snapshot
971 testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
972 testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
973
974 {{end}}
975 testdeps.ImportPath = {{.ImportPath | printf "%q"}}
976 }
977
978 func main() {
979 m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
980 {{with .TestMain}}
981 {{.Package}}.{{.Name}}(m)
982 os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
983 {{else}}
984 os.Exit(m.Run())
985 {{end}}
986 }
987
988 `)
989
View as plain text