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