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/fsys"
27 "cmd/go/internal/modload"
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 }
46
47
48
49
50
51 func TestPackagesFor(loaderstate *modload.State, ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest, perr *Package) {
52 pmain, ptest, pxtest = TestPackagesAndErrors(loaderstate, 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 perr = p1
60 break
61 }
62 if p1.Incomplete {
63 ps := PackageList([]*Package{p1})
64 for _, p := range ps {
65 if p.Error != nil {
66 perr = p
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, perr
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 func TestPackagesAndErrors(loaderstate *modload.State, 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(loaderstate, 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(loaderstate, 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(loaderstate, 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 if ptest.Error == nil {
180 ptest.Error = ptestErr
181 }
182 ptest.Incomplete = ptest.Incomplete || incomplete
183 ptest.ForTest = p.ImportPath
184 ptest.GoFiles = nil
185 ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
186 ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
187 ptest.Target = ""
188
189
190
191
192
193
194
195
196
197
198
199
200 ptest.Imports = str.StringList(p.TestImports, p.Imports)
201 ptest.Internal.Imports = append(imports, p.Internal.Imports...)
202 ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
203 ptest.Internal.ForceLibrary = true
204 ptest.Internal.BuildInfo = nil
205 ptest.Internal.Build = new(build.Package)
206 *ptest.Internal.Build = *p.Internal.Build
207 m := map[string][]token.Position{}
208 for k, v := range p.Internal.Build.ImportPos {
209 m[k] = append(m[k], v...)
210 }
211 for k, v := range p.Internal.Build.TestImportPos {
212 m[k] = append(m[k], v...)
213 }
214 ptest.Internal.Build.ImportPos = m
215 if testEmbed == nil && len(p.Internal.Embed) > 0 {
216 testEmbed = map[string][]string{}
217 }
218 maps.Copy(testEmbed, p.Internal.Embed)
219 ptest.Internal.Embed = testEmbed
220 ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles)
221 ptest.Internal.OrigImportPath = p.Internal.OrigImportPath
222 ptest.Internal.PGOProfile = p.Internal.PGOProfile
223 ptest.Internal.Build.Directives = append(slices.Clip(p.Internal.Build.Directives), p.Internal.Build.TestDirectives...)
224 } else {
225 ptest = p
226 }
227
228
229 if len(p.XTestGoFiles) > 0 {
230 pxtest = &Package{
231 PackagePublic: PackagePublic{
232 Name: p.Name + "_test",
233 ImportPath: p.ImportPath + "_test",
234 Root: p.Root,
235 Dir: p.Dir,
236 Goroot: p.Goroot,
237 GoFiles: p.XTestGoFiles,
238 Imports: p.XTestImports,
239 ForTest: p.ImportPath,
240 Module: p.Module,
241 Error: pxtestErr,
242 Incomplete: pxtestIncomplete,
243 EmbedFiles: p.XTestEmbedFiles,
244 },
245 Internal: PackageInternal{
246 LocalPrefix: p.Internal.LocalPrefix,
247 Build: &build.Package{
248 ImportPos: p.Internal.Build.XTestImportPos,
249 Directives: p.Internal.Build.XTestDirectives,
250 },
251 Imports: ximports,
252 RawImports: rawXTestImports,
253
254 Asmflags: p.Internal.Asmflags,
255 Gcflags: p.Internal.Gcflags,
256 Ldflags: p.Internal.Ldflags,
257 Gccgoflags: p.Internal.Gccgoflags,
258 Embed: xtestEmbed,
259 OrigImportPath: p.Internal.OrigImportPath,
260 PGOProfile: p.Internal.PGOProfile,
261 },
262 }
263 if pxtestNeedsPtest {
264 pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
265 }
266 }
267
268
269 ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
270 gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
271
272
273 pmain = &Package{
274 PackagePublic: PackagePublic{
275 Name: "main",
276 Dir: p.Dir,
277 GoFiles: []string{"_testmain.go"},
278 ImportPath: p.ImportPath + ".test",
279 Root: p.Root,
280 Imports: str.StringList(TestMainDeps),
281 Module: p.Module,
282 },
283 Internal: PackageInternal{
284 Build: &build.Package{Name: "main"},
285 BuildInfo: p.Internal.BuildInfo,
286 Asmflags: p.Internal.Asmflags,
287 Gcflags: p.Internal.Gcflags,
288 Ldflags: ldflags,
289 Gccgoflags: gccgoflags,
290 OrigImportPath: p.Internal.OrigImportPath,
291 PGOProfile: p.Internal.PGOProfile,
292 },
293 }
294
295 pb := p.Internal.Build
296 pmain.DefaultGODEBUG = defaultGODEBUG(loaderstate, pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
297 if pmain.Internal.BuildInfo == nil || pmain.DefaultGODEBUG != p.DefaultGODEBUG {
298
299
300
301
302
303
304 pmain.setBuildInfo(ctx, opts.AutoVCS)
305 }
306
307
308
309 stk.Push(ImportInfo{Pkg: "testmain"})
310 deps := TestMainDeps
311 if cover != nil {
312 deps = append(deps, "internal/coverage/cfile")
313 }
314 ldDeps, err := LinkerDeps(loaderstate, p)
315 if err != nil && pmain.Error == nil {
316 pmain.Error = &PackageError{Err: err}
317 }
318 for _, d := range ldDeps {
319 deps = append(deps, d)
320 }
321 for _, dep := range deps {
322 if dep == ptest.ImportPath {
323 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
324 } else {
325 p1, err := loadImport(loaderstate, ctx, opts, pre, dep, "", nil, &stk, nil, 0)
326 if err != nil && pmain.Error == nil {
327 pmain.Error = err
328 pmain.Incomplete = true
329 }
330 pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
331 }
332 }
333 stk.Pop()
334
335 parallelizablePart := func() {
336 allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports))
337 allTestImports = append(allTestImports, pmain.Internal.Imports...)
338 allTestImports = append(allTestImports, imports...)
339 allTestImports = append(allTestImports, ximports...)
340 setToolFlags(loaderstate, allTestImports...)
341
342
343
344
345
346 t, err := loadTestFuncs(p)
347 if err != nil && pmain.Error == nil {
348 pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
349 }
350 t.Cover = cover
351 if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
352 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
353 pmain.Imports = append(pmain.Imports, ptest.ImportPath)
354 t.ImportTest = true
355 }
356 if pxtest != nil {
357 pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
358 pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
359 t.ImportXtest = true
360 }
361
362
363
364 sort.Strings(pmain.Imports)
365 w := 0
366 for _, path := range pmain.Imports {
367 if w == 0 || path != pmain.Imports[w-1] {
368 pmain.Imports[w] = path
369 w++
370 }
371 }
372 pmain.Imports = pmain.Imports[:w]
373 pmain.Internal.RawImports = str.StringList(pmain.Imports)
374
375
376 cycleErr := recompileForTest(pmain, p, ptest, pxtest)
377 if cycleErr != nil {
378 ptest.Error = cycleErr
379 ptest.Incomplete = true
380 }
381
382 if cover != nil {
383
384
385
386
387 ptest.Internal.Cover.Mode = p.Internal.Cover.Mode
388 pmain.Internal.Cover.Mode = "testmain"
389
390
391
392
393
394 if cover.Local {
395 ptest.Internal.Cover.Mode = cover.Mode
396 }
397 }
398
399 data, err := formatTestmain(t)
400 if err != nil && pmain.Error == nil {
401 pmain.Error = &PackageError{Err: err}
402 pmain.Incomplete = true
403 }
404
405
406 pmain.Internal.TestmainGo = &data
407 }
408
409 if done != nil {
410 go func() {
411 parallelizablePart()
412 done()
413 }()
414 } else {
415 parallelizablePart()
416 }
417
418 return pmain, ptest, pxtest
419 }
420
421
422
423
424
425
426
427
428
429
430 func recompileForTest(pmain, preal, ptest, pxtest *Package) *PackageError {
431
432
433
434 testCopy := map[*Package]*Package{preal: ptest}
435 for _, p := range PackageList([]*Package{pmain}) {
436 if p == preal {
437 continue
438 }
439
440 didSplit := p == pmain || p == pxtest || p == ptest
441 split := func() {
442 if didSplit {
443 return
444 }
445 didSplit = true
446 if testCopy[p] != nil {
447 panic("recompileForTest loop")
448 }
449 p1 := new(Package)
450 testCopy[p] = p1
451 *p1 = *p
452 p1.ForTest = preal.ImportPath
453 p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
454 copy(p1.Internal.Imports, p.Internal.Imports)
455 p1.Imports = make([]string, len(p.Imports))
456 copy(p1.Imports, p.Imports)
457 p = p1
458 p.Target = ""
459 p.Internal.BuildInfo = nil
460 p.Internal.ForceLibrary = true
461 p.Internal.PGOProfile = preal.Internal.PGOProfile
462 }
463
464
465 for i, imp := range p.Internal.Imports {
466 if p1 := testCopy[imp]; p1 != nil && p1 != imp {
467 split()
468
469
470
471
472 p.Internal.Imports[i] = p1
473 }
474 }
475
476
477
478
479
480
481
482 if p.Name == "main" && p != pmain && p != ptest {
483 split()
484 }
485
486
487 if preal.Internal.PGOProfile != "" && p.Internal.PGOProfile == "" {
488 split()
489 }
490 }
491
492
493
494 importerOf := map[*Package]*Package{}
495 for _, p := range ptest.Internal.Imports {
496 importerOf[p] = nil
497 }
498
499
500
501
502
503
504
505
506
507
508
509 q := slices.Clip(ptest.Internal.Imports)
510 for len(q) > 0 {
511 p := q[0]
512 q = q[1:]
513 if p == ptest {
514
515
516
517 var stk ImportStack
518 for p != nil {
519 importer, ok := importerOf[p]
520 if importer == nil && ok {
521 importer = ptest
522 }
523 stk = append(stk, ImportInfo{
524 Pkg: p.ImportPath,
525 Pos: extractFirstImport(importer.Internal.Build.ImportPos[p.ImportPath]),
526 })
527 p = importerOf[p]
528 }
529
530
531
532
533
534 stk = append(stk, ImportInfo{
535 Pkg: ptest.ImportPath,
536 })
537 slices.Reverse(stk)
538 return &PackageError{
539 ImportStack: stk,
540 Err: errors.New("import cycle not allowed in test"),
541 IsImportCycle: true,
542 }
543 }
544 for _, dep := range p.Internal.Imports {
545 if _, ok := importerOf[dep]; !ok {
546 importerOf[dep] = p
547 q = append(q, dep)
548 }
549 }
550 }
551
552 return nil
553 }
554
555
556
557 func isTestFunc(fn *ast.FuncDecl, arg string) bool {
558 if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
559 fn.Type.Params.List == nil ||
560 len(fn.Type.Params.List) != 1 ||
561 len(fn.Type.Params.List[0].Names) > 1 {
562 return false
563 }
564 ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
565 if !ok {
566 return false
567 }
568
569
570
571
572 if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
573 return true
574 }
575 if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
576 return true
577 }
578 return false
579 }
580
581
582
583
584 func isTest(name, prefix string) bool {
585 if !strings.HasPrefix(name, prefix) {
586 return false
587 }
588 if len(name) == len(prefix) {
589 return true
590 }
591 rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
592 return !unicode.IsLower(rune)
593 }
594
595
596
597
598 func loadTestFuncs(ptest *Package) (*testFuncs, error) {
599 t := &testFuncs{
600 Package: ptest,
601 }
602 var err error
603 for _, file := range ptest.TestGoFiles {
604 if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
605 err = lerr
606 }
607 }
608 for _, file := range ptest.XTestGoFiles {
609 if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
610 err = lerr
611 }
612 }
613 return t, err
614 }
615
616
617 func formatTestmain(t *testFuncs) ([]byte, error) {
618 var buf bytes.Buffer
619 tmpl := testmainTmpl
620 if err := tmpl.Execute(&buf, t); err != nil {
621 return nil, err
622 }
623 return buf.Bytes(), nil
624 }
625
626 type testFuncs struct {
627 Tests []testFunc
628 Benchmarks []testFunc
629 FuzzTargets []testFunc
630 Examples []testFunc
631 TestMain *testFunc
632 Package *Package
633 ImportTest bool
634 NeedTest bool
635 ImportXtest bool
636 NeedXtest bool
637 Cover *TestCover
638 }
639
640
641
642 func (t *testFuncs) ImportPath() string {
643 pkg := t.Package.ImportPath
644 if strings.HasPrefix(pkg, "_/") {
645 return ""
646 }
647 if pkg == "command-line-arguments" {
648 return ""
649 }
650 return pkg
651 }
652
653 func (t *testFuncs) ModulePath() string {
654 m := t.Package.Module
655 if m == nil {
656 return ""
657 }
658 return m.Path
659 }
660
661
662
663
664
665 func (t *testFuncs) Covered() string {
666 if t.Cover == nil || t.Cover.Paths == nil {
667 return ""
668 }
669 return " in " + strings.Join(t.Cover.Paths, ", ")
670 }
671
672 func (t *testFuncs) CoverSelectedPackages() string {
673 if t.Cover == nil || t.Cover.Paths == nil {
674 return `[]string{"` + t.Package.ImportPath + `"}`
675 }
676 var sb strings.Builder
677 fmt.Fprintf(&sb, "[]string{")
678 for k, p := range t.Cover.Pkgs {
679 if k != 0 {
680 sb.WriteString(", ")
681 }
682 fmt.Fprintf(&sb, `"%s"`, p.ImportPath)
683 }
684 sb.WriteString("}")
685 return sb.String()
686 }
687
688
689 func (t *testFuncs) Tested() string {
690 return t.Package.Name
691 }
692
693 type testFunc struct {
694 Package string
695 Name string
696 Output string
697 Unordered bool
698 }
699
700 var testFileSet = token.NewFileSet()
701
702 func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
703
704 src, err := fsys.Open(filename)
705 if err != nil {
706 return err
707 }
708 defer src.Close()
709 f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments|parser.SkipObjectResolution)
710 if err != nil {
711 return err
712 }
713 for _, d := range f.Decls {
714 n, ok := d.(*ast.FuncDecl)
715 if !ok {
716 continue
717 }
718 if n.Recv != nil {
719 continue
720 }
721 name := n.Name.String()
722 switch {
723 case name == "TestMain":
724 if isTestFunc(n, "T") {
725 t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
726 *doImport, *seen = true, true
727 continue
728 }
729 err := checkTestFunc(n, "M")
730 if err != nil {
731 return err
732 }
733 if t.TestMain != nil {
734 return errors.New("multiple definitions of TestMain")
735 }
736 t.TestMain = &testFunc{pkg, name, "", false}
737 *doImport, *seen = true, true
738 case isTest(name, "Test"):
739 err := checkTestFunc(n, "T")
740 if err != nil {
741 return err
742 }
743 t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
744 *doImport, *seen = true, true
745 case isTest(name, "Benchmark"):
746 err := checkTestFunc(n, "B")
747 if err != nil {
748 return err
749 }
750 t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
751 *doImport, *seen = true, true
752 case isTest(name, "Fuzz"):
753 err := checkTestFunc(n, "F")
754 if err != nil {
755 return err
756 }
757 t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false})
758 *doImport, *seen = true, true
759 }
760 }
761 ex := doc.Examples(f)
762 sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
763 for _, e := range ex {
764 *doImport = true
765 if e.Output == "" && !e.EmptyOutput {
766
767 continue
768 }
769 t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
770 *seen = true
771 }
772 return nil
773 }
774
775 func checkTestFunc(fn *ast.FuncDecl, arg string) error {
776 var why string
777 if !isTestFunc(fn, arg) {
778 why = fmt.Sprintf("must be: func %s(%s *testing.%s)", fn.Name.String(), strings.ToLower(arg), arg)
779 }
780 if fn.Type.TypeParams.NumFields() > 0 {
781 why = "test functions cannot have type parameters"
782 }
783 if why != "" {
784 pos := testFileSet.Position(fn.Pos())
785 return fmt.Errorf("%s: wrong signature for %s, %s", pos, fn.Name.String(), why)
786 }
787 return nil
788 }
789
790 var testmainTmpl = lazytemplate.New("main", `
791 // Code generated by 'go test'. DO NOT EDIT.
792
793 package main
794
795 import (
796 "os"
797 {{if .TestMain}}
798 "reflect"
799 {{end}}
800 "testing"
801 "testing/internal/testdeps"
802 {{if .Cover}}
803 "internal/coverage/cfile"
804 {{end}}
805
806 {{if .ImportTest}}
807 {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
808 {{end}}
809 {{if .ImportXtest}}
810 {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
811 {{end}}
812 )
813
814 var tests = []testing.InternalTest{
815 {{range .Tests}}
816 {"{{.Name}}", {{.Package}}.{{.Name}}},
817 {{end}}
818 }
819
820 var benchmarks = []testing.InternalBenchmark{
821 {{range .Benchmarks}}
822 {"{{.Name}}", {{.Package}}.{{.Name}}},
823 {{end}}
824 }
825
826 var fuzzTargets = []testing.InternalFuzzTarget{
827 {{range .FuzzTargets}}
828 {"{{.Name}}", {{.Package}}.{{.Name}}},
829 {{end}}
830 }
831
832 var examples = []testing.InternalExample{
833 {{range .Examples}}
834 {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
835 {{end}}
836 }
837
838 func init() {
839 {{if .Cover}}
840 testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
841 testdeps.Covered = {{printf "%q" .Covered}}
842 testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
843 testdeps.CoverSnapshotFunc = cfile.Snapshot
844 testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
845 testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
846
847 {{end}}
848 testdeps.ModulePath = {{.ModulePath | printf "%q"}}
849 testdeps.ImportPath = {{.ImportPath | printf "%q"}}
850 }
851
852 func main() {
853 m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
854 {{with .TestMain}}
855 {{.Package}}.{{.Name}}(m)
856 os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
857 {{else}}
858 os.Exit(m.Run())
859 {{end}}
860 }
861
862 `)
863
View as plain text