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