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