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(ld *modload.Loader, ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest, perr *Package) {
52 pmain, ptest, pxtest = TestPackagesAndErrors(ld, 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(ld *modload.Loader, 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(ld, 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
120 for i, path := range p.TestImports {
121 p1, err := loadImport(ld, 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
133 var ptestCompiledImports []string
134 if hasSimd := hasSimd(p.TestImports); hasSimd {
135 p1, err := loadImport(ld, ctx, opts, pre, SimdBridgePkg, p.Dir, p, &stk, nil, ResolveImport|allowSimdInternalBridge)
136 if err != nil && ptestErr == nil {
137 ptestErr = err
138 incomplete = true
139 }
140 if p1.Incomplete {
141 incomplete = true
142 }
143 imports = append(imports, p1)
144 ptestCompiledImports = append(ptestCompiledImports, p1.ImportPath)
145 }
146 var err error
147 p.TestEmbedFiles, testEmbed, err = resolveEmbed(p.Dir, p.TestEmbedPatterns)
148 if err != nil {
149 ptestErr = &PackageError{
150 ImportStack: stk.Copy(),
151 Err: err,
152 }
153 incomplete = true
154 embedErr := err.(*EmbedError)
155 ptestErr.setPos(p.Internal.Build.TestEmbedPatternPos[embedErr.Pattern])
156 }
157 stk.Pop()
158
159 stk.Push(ImportInfo{Pkg: p.ImportPath + "_test"})
160 pxtestNeedsPtest := false
161 var pxtestIncomplete bool
162 rawXTestImports := str.StringList(p.XTestImports)
163
164 for i, path := range p.XTestImports {
165 p1, err := loadImport(ld, ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
166 if err != nil && pxtestErr == nil {
167 pxtestErr = err
168 }
169 if p1.Incomplete {
170 pxtestIncomplete = true
171 }
172 if p1.ImportPath == p.ImportPath {
173 pxtestNeedsPtest = true
174 } else {
175 ximports = append(ximports, p1)
176 }
177 p.XTestImports[i] = p1.ImportPath
178 }
179
180 var pxtestCompiledImports []string
181 if hasSimd := hasSimd(p.XTestImports); hasSimd {
182 p1, err := loadImport(ld, ctx, opts, pre, SimdBridgePkg, p.Dir, p, &stk, nil, ResolveImport|allowSimdInternalBridge)
183 if err != nil && pxtestErr == nil {
184 pxtestErr = err
185 }
186 if p1.Incomplete {
187 pxtestIncomplete = true
188 }
189 ximports = append(ximports, p1)
190 pxtestCompiledImports = append(pxtestCompiledImports, p1.ImportPath)
191 }
192 p.XTestEmbedFiles, xtestEmbed, err = resolveEmbed(p.Dir, p.XTestEmbedPatterns)
193 if err != nil && pxtestErr == nil {
194 pxtestErr = &PackageError{
195 ImportStack: stk.Copy(),
196 Err: err,
197 }
198 embedErr := err.(*EmbedError)
199 pxtestErr.setPos(p.Internal.Build.XTestEmbedPatternPos[embedErr.Pattern])
200 }
201 pxtestIncomplete = pxtestIncomplete || pxtestErr != nil
202 stk.Pop()
203
204
205 if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
206 ptest = new(Package)
207 *ptest = *p
208 if ptest.Error == nil {
209 ptest.Error = ptestErr
210 }
211 ptest.Incomplete = ptest.Incomplete || incomplete
212 ptest.ForTest = p.ImportPath
213 ptest.GoFiles = nil
214 ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
215 ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
216 ptest.Target = ""
217
218
219
220
221
222
223
224
225
226
227
228
229 ptest.Imports = str.StringList(p.TestImports, p.Imports)
230 ptest.Internal.Imports = append(imports, p.Internal.Imports...)
231 ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
232 ptest.Internal.CompiledImports = slices.Clone(p.Internal.CompiledImports)
233 for _, path := range ptestCompiledImports {
234 if !slices.Contains(ptest.Internal.CompiledImports, path) {
235 ptest.Internal.CompiledImports = append(ptest.Internal.CompiledImports, path)
236 }
237 }
238 ptest.Internal.ForceLibrary = true
239 ptest.Internal.BuildInfo = nil
240 ptest.Internal.Build = new(build.Package)
241 *ptest.Internal.Build = *p.Internal.Build
242 m := map[string][]token.Position{}
243 for k, v := range p.Internal.Build.ImportPos {
244 m[k] = append(m[k], v...)
245 }
246 for k, v := range p.Internal.Build.TestImportPos {
247 m[k] = append(m[k], v...)
248 }
249 ptest.Internal.Build.ImportPos = m
250 if testEmbed == nil && len(p.Internal.Embed) > 0 {
251 testEmbed = map[string][]string{}
252 }
253 maps.Copy(testEmbed, p.Internal.Embed)
254 ptest.Internal.Embed = testEmbed
255 ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles)
256 ptest.Internal.OrigImportPath = p.Internal.OrigImportPath
257 ptest.Internal.PGOProfile = p.Internal.PGOProfile
258 ptest.Internal.Build.Directives = append(slices.Clip(p.Internal.Build.Directives), p.Internal.Build.TestDirectives...)
259 } else {
260 ptest = p
261 }
262
263
264 if len(p.XTestGoFiles) > 0 {
265 pxtest = &Package{
266 PackagePublic: PackagePublic{
267 Name: p.Name + "_test",
268 ImportPath: p.ImportPath + "_test",
269 Root: p.Root,
270 Dir: p.Dir,
271 Goroot: p.Goroot,
272 GoFiles: p.XTestGoFiles,
273 Imports: p.XTestImports,
274 ForTest: p.ImportPath,
275 Module: p.Module,
276 Error: pxtestErr,
277 Incomplete: pxtestIncomplete,
278 EmbedFiles: p.XTestEmbedFiles,
279 },
280 Internal: PackageInternal{
281 LocalPrefix: p.Internal.LocalPrefix,
282 Build: &build.Package{
283 ImportPos: p.Internal.Build.XTestImportPos,
284 Directives: p.Internal.Build.XTestDirectives,
285 },
286 Imports: ximports,
287 RawImports: rawXTestImports,
288 CompiledImports: pxtestCompiledImports,
289
290 Asmflags: p.Internal.Asmflags,
291 Gcflags: p.Internal.Gcflags,
292 Ldflags: p.Internal.Ldflags,
293 Gccgoflags: p.Internal.Gccgoflags,
294 Embed: xtestEmbed,
295 OrigImportPath: p.Internal.OrigImportPath,
296 PGOProfile: p.Internal.PGOProfile,
297 },
298 }
299 if pxtestNeedsPtest {
300 pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
301 }
302 }
303
304
305 ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
306 gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
307
308
309 pmain = &Package{
310 PackagePublic: PackagePublic{
311 Name: "main",
312 Dir: p.Dir,
313 GoFiles: []string{"_testmain.go"},
314 ImportPath: p.ImportPath + ".test",
315 Root: p.Root,
316 Imports: str.StringList(TestMainDeps),
317 Module: p.Module,
318 },
319 Internal: PackageInternal{
320 Build: &build.Package{Name: "main"},
321 BuildInfo: p.Internal.BuildInfo,
322 Asmflags: p.Internal.Asmflags,
323 Gcflags: p.Internal.Gcflags,
324 Ldflags: ldflags,
325 Gccgoflags: gccgoflags,
326 OrigImportPath: p.Internal.OrigImportPath,
327 PGOProfile: p.Internal.PGOProfile,
328 },
329 }
330
331 pb := p.Internal.Build
332 pmain.DefaultGODEBUG = defaultGODEBUG(ld, pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
333
334
335
336 stk.Push(ImportInfo{Pkg: "testmain"})
337 deps := TestMainDeps
338 if cover != nil {
339 deps = append(deps, "internal/coverage/cfile")
340 }
341 ldDeps, err := LinkerDeps(ld, p)
342 if err != nil && pmain.Error == nil {
343 pmain.Error = &PackageError{Err: err}
344 }
345 for _, d := range ldDeps {
346 deps = append(deps, d)
347 }
348 for _, dep := range deps {
349 if dep == ptest.ImportPath {
350 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
351 } else {
352 p1, err := loadImport(ld, ctx, opts, pre, dep, "", nil, &stk, nil, 0)
353 if err != nil && pmain.Error == nil {
354 pmain.Error = err
355 pmain.Incomplete = true
356 }
357 pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
358 }
359 }
360 stk.Pop()
361
362 parallelizablePart := func() {
363
364
365
366
367 t, err := loadTestFuncs(p)
368 if err != nil && pmain.Error == nil {
369 pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
370 }
371 t.Cover = cover
372 if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
373 pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
374 pmain.Imports = append(pmain.Imports, ptest.ImportPath)
375 t.ImportTest = true
376 }
377 if pxtest != nil {
378 pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
379 pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
380 t.ImportXtest = true
381 }
382
383
384
385 sort.Strings(pmain.Imports)
386 w := 0
387 for _, path := range pmain.Imports {
388 if w == 0 || path != pmain.Imports[w-1] {
389 pmain.Imports[w] = path
390 w++
391 }
392 }
393 pmain.Imports = pmain.Imports[:w]
394 pmain.Internal.RawImports = str.StringList(pmain.Imports)
395
396
397 cycleErr := recompileForTest(pmain, p, ptest, pxtest)
398 if cycleErr != nil {
399 ptest.Error = cycleErr
400 ptest.Incomplete = true
401 }
402
403 if !opts.SuppressBuildInfo {
404
405
406
407
408
409 pmain.setBuildInfo(ctx, ld.Fetcher(), opts.AutoVCS)
410 }
411
412 if cover != nil {
413
414
415
416
417 ptest.Internal.Cover.Mode = p.Internal.Cover.Mode
418 pmain.Internal.Cover.Mode = "testmain"
419
420
421
422
423
424 if cover.Local {
425 ptest.Internal.Cover.Mode = cover.Mode
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
626
627
628 func loadTestFuncs(ptest *Package) (*testFuncs, error) {
629 t := &testFuncs{
630 Package: ptest,
631 }
632 var err error
633 for _, file := range ptest.TestGoFiles {
634 if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
635 err = lerr
636 }
637 }
638 for _, file := range ptest.XTestGoFiles {
639 if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
640 err = lerr
641 }
642 }
643 return t, err
644 }
645
646
647 func formatTestmain(t *testFuncs) ([]byte, error) {
648 var buf bytes.Buffer
649 tmpl := testmainTmpl
650 if err := tmpl.Execute(&buf, t); err != nil {
651 return nil, err
652 }
653 return buf.Bytes(), nil
654 }
655
656 type testFuncs struct {
657 Tests []testFunc
658 Benchmarks []testFunc
659 FuzzTargets []testFunc
660 Examples []testFunc
661 TestMain *testFunc
662 Package *Package
663 ImportTest bool
664 NeedTest bool
665 ImportXtest bool
666 NeedXtest bool
667 Cover *TestCover
668 }
669
670
671
672 func (t *testFuncs) ImportPath() string {
673 pkg := t.Package.ImportPath
674 if strings.HasPrefix(pkg, "_/") {
675 return ""
676 }
677 if pkg == "command-line-arguments" {
678 return ""
679 }
680 return pkg
681 }
682
683 func (t *testFuncs) ModulePath() string {
684 m := t.Package.Module
685 if m == nil {
686 return ""
687 }
688 return m.Path
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 {{if .Cover}}
833 "internal/coverage/cfile"
834 {{end}}
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 )
843
844 var tests = []testing.InternalTest{
845 {{range .Tests}}
846 {"{{.Name}}", {{.Package}}.{{.Name}}},
847 {{end}}
848 }
849
850 var benchmarks = []testing.InternalBenchmark{
851 {{range .Benchmarks}}
852 {"{{.Name}}", {{.Package}}.{{.Name}}},
853 {{end}}
854 }
855
856 var fuzzTargets = []testing.InternalFuzzTarget{
857 {{range .FuzzTargets}}
858 {"{{.Name}}", {{.Package}}.{{.Name}}},
859 {{end}}
860 }
861
862 var examples = []testing.InternalExample{
863 {{range .Examples}}
864 {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
865 {{end}}
866 }
867
868 func init() {
869 {{if .Cover}}
870 testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
871 testdeps.Covered = {{printf "%q" .Covered}}
872 testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
873 testdeps.CoverSnapshotFunc = cfile.Snapshot
874 testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
875 testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
876
877 {{end}}
878 testdeps.ModulePath = {{.ModulePath | printf "%q"}}
879 testdeps.ImportPath = {{.ImportPath | printf "%q"}}
880 }
881
882 func main() {
883 m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
884 {{with .TestMain}}
885 {{.Package}}.{{.Name}}(m)
886 os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
887 {{else}}
888 os.Exit(m.Run())
889 {{end}}
890 }
891
892 `)
893
View as plain text