1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package load
6
7import (
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	"path/filepath"
19	"slices"
20	"sort"
21	"strings"
22	"unicode"
23	"unicode/utf8"
24
25	"cmd/go/internal/cfg"
26	"cmd/go/internal/fsys"
27	"cmd/go/internal/str"
28	"cmd/go/internal/trace"
29)
30
31var TestMainDeps = []string{
32	// Dependencies for testmain.
33	"os",
34	"reflect",
35	"testing",
36	"testing/internal/testdeps",
37}
38
39type TestCover struct {
40	Mode  string
41	Local bool
42	Pkgs  []*Package
43	Paths []string
44	Vars  []coverInfo
45}
46
47// TestPackagesFor is like TestPackagesAndErrors but it returns
48// an error if the test packages or their dependencies have errors.
49// Only test packages without errors are returned.
50func TestPackagesFor(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
51	pmain, ptest, pxtest = TestPackagesAndErrors(ctx, nil, opts, p, cover)
52	for _, p1 := range []*Package{ptest, pxtest, pmain} {
53		if p1 == nil {
54			// pxtest may be nil
55			continue
56		}
57		if p1.Error != nil {
58			err = p1.Error
59			break
60		}
61		if p1.Incomplete {
62			ps := PackageList([]*Package{p1})
63			for _, p := range ps {
64				if p.Error != nil {
65					err = p.Error
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, err
82}
83
84// TestPackagesAndErrors returns three packages:
85//   - pmain, the package main corresponding to the test binary (running tests in ptest and pxtest).
86//   - ptest, the package p compiled with added "package p" test files.
87//   - pxtest, the result of compiling any "package p_test" (external) test files.
88//
89// If the package has no "package p_test" test files, pxtest will be nil.
90// If the non-test compilation of package p can be reused
91// (for example, if there are no "package p" test files and
92// package p need not be instrumented for coverage or any other reason),
93// then the returned ptest == p.
94//
95// If done is non-nil, TestPackagesAndErrors will finish filling out the returned
96// package structs in a goroutine and call done once finished. The members of the
97// returned packages should not be accessed until done is called.
98//
99// The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
100// or else there's no point in any of this.
101func 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(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(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	// Test package.
175	if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
176		ptest = new(Package)
177		*ptest = *p
178		ptest.Error = ptestErr
179		ptest.Incomplete = incomplete
180		ptest.ForTest = p.ImportPath
181		ptest.GoFiles = nil
182		ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
183		ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
184		ptest.Target = ""
185		// Note: The preparation of the vet config requires that common
186		// indexes in ptest.Imports and ptest.Internal.RawImports
187		// all line up (but RawImports can be shorter than the others).
188		// That is, for 0 ≤ i < len(RawImports),
189		// RawImports[i] is the import string in the program text, and
190		// Imports[i] is the expanded import string (vendoring applied or relative path expanded away).
191		// Any implicitly added imports appear in Imports and Internal.Imports
192		// but not RawImports (because they were not in the source code).
193		// We insert TestImports, imports, and rawTestImports at the start of
194		// these lists to preserve the alignment.
195		// Note that p.Internal.Imports may not be aligned with p.Imports/p.Internal.RawImports,
196		// but we insert at the beginning there too just for consistency.
197		ptest.Imports = str.StringList(p.TestImports, p.Imports)
198		ptest.Internal.Imports = append(imports, p.Internal.Imports...)
199		ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
200		ptest.Internal.ForceLibrary = true
201		ptest.Internal.BuildInfo = nil
202		ptest.Internal.Build = new(build.Package)
203		*ptest.Internal.Build = *p.Internal.Build
204		m := map[string][]token.Position{}
205		for k, v := range p.Internal.Build.ImportPos {
206			m[k] = append(m[k], v...)
207		}
208		for k, v := range p.Internal.Build.TestImportPos {
209			m[k] = append(m[k], v...)
210		}
211		ptest.Internal.Build.ImportPos = m
212		if testEmbed == nil && len(p.Internal.Embed) > 0 {
213			testEmbed = map[string][]string{}
214		}
215		for k, v := range p.Internal.Embed {
216			testEmbed[k] = v
217		}
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	// External test package.
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	// Arrange for testing.Testing to report true.
268	ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
269	gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
270
271	// Build main package.
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
297	// The generated main also imports testing, regexp, and os.
298	// Also the linker introduces implicit dependencies reported by LinkerDeps.
299	stk.Push("testmain")
300	deps := TestMainDeps // cap==len, so safe for append
301	if cover != nil && cfg.Experiment.CoverageRedesign {
302		deps = append(deps, "internal/coverage/cfile")
303	}
304	ldDeps, err := LinkerDeps(p)
305	if err != nil && pmain.Error == nil {
306		pmain.Error = &PackageError{Err: err}
307	}
308	for _, d := range ldDeps {
309		deps = append(deps, d)
310	}
311	for _, dep := range deps {
312		if dep == ptest.ImportPath {
313			pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
314		} else {
315			p1, err := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0)
316			if err != nil && pmain.Error == nil {
317				pmain.Error = err
318				pmain.Incomplete = true
319			}
320			pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
321		}
322	}
323	stk.Pop()
324
325	parallelizablePart := func() {
326		if cover != nil && cover.Pkgs != nil && !cfg.Experiment.CoverageRedesign {
327			// Add imports, but avoid duplicates.
328			seen := map[*Package]bool{p: true, ptest: true}
329			for _, p1 := range pmain.Internal.Imports {
330				seen[p1] = true
331			}
332			for _, p1 := range cover.Pkgs {
333				if seen[p1] {
334					// Don't add duplicate imports.
335					continue
336				}
337				seen[p1] = true
338				pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
339			}
340		}
341
342		allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports))
343		allTestImports = append(allTestImports, pmain.Internal.Imports...)
344		allTestImports = append(allTestImports, imports...)
345		allTestImports = append(allTestImports, ximports...)
346		setToolFlags(allTestImports...)
347
348		// Do initial scan for metadata needed for writing _testmain.go
349		// Use that metadata to update the list of imports for package main.
350		// The list of imports is used by recompileForTest and by the loop
351		// afterward that gathers t.Cover information.
352		t, err := loadTestFuncs(p)
353		if err != nil && pmain.Error == nil {
354			pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
355		}
356		t.Cover = cover
357		if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
358			pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
359			pmain.Imports = append(pmain.Imports, ptest.ImportPath)
360			t.ImportTest = true
361		}
362		if pxtest != nil {
363			pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
364			pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
365			t.ImportXtest = true
366		}
367
368		// Sort and dedup pmain.Imports.
369		// Only matters for go list -test output.
370		sort.Strings(pmain.Imports)
371		w := 0
372		for _, path := range pmain.Imports {
373			if w == 0 || path != pmain.Imports[w-1] {
374				pmain.Imports[w] = path
375				w++
376			}
377		}
378		pmain.Imports = pmain.Imports[:w]
379		pmain.Internal.RawImports = str.StringList(pmain.Imports)
380
381		// Replace pmain's transitive dependencies with test copies, as necessary.
382		cycleErr := recompileForTest(pmain, p, ptest, pxtest)
383		if cycleErr != nil {
384			ptest.Error = cycleErr
385			ptest.Incomplete = true
386		}
387
388		if cover != nil {
389			if cfg.Experiment.CoverageRedesign {
390				// Here ptest needs to inherit the proper coverage mode (since
391				// it contains p's Go files), whereas pmain contains only
392				// test harness code (don't want to instrument it, and
393				// we don't want coverage hooks in the pkg init).
394				ptest.Internal.Cover.Mode = p.Internal.Cover.Mode
395				pmain.Internal.Cover.Mode = "testmain"
396			}
397			// Should we apply coverage analysis locally, only for this
398			// package and only for this test? Yes, if -cover is on but
399			// -coverpkg has not specified a list of packages for global
400			// coverage.
401			if cover.Local {
402				ptest.Internal.Cover.Mode = cover.Mode
403
404				if !cfg.Experiment.CoverageRedesign {
405					var coverFiles []string
406					coverFiles = append(coverFiles, ptest.GoFiles...)
407					coverFiles = append(coverFiles, ptest.CgoFiles...)
408					ptest.Internal.CoverVars = DeclareCoverVars(ptest, coverFiles...)
409				}
410			}
411
412			if !cfg.Experiment.CoverageRedesign {
413				for _, cp := range pmain.Internal.Imports {
414					if len(cp.Internal.CoverVars) > 0 {
415						t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars})
416					}
417				}
418			}
419		}
420
421		data, err := formatTestmain(t)
422		if err != nil && pmain.Error == nil {
423			pmain.Error = &PackageError{Err: err}
424			pmain.Incomplete = true
425		}
426		// Set TestmainGo even if it is empty: the presence of a TestmainGo
427		// indicates that this package is, in fact, a test main.
428		pmain.Internal.TestmainGo = &data
429	}
430
431	if done != nil {
432		go func() {
433			parallelizablePart()
434			done()
435		}()
436	} else {
437		parallelizablePart()
438	}
439
440	return pmain, ptest, pxtest
441}
442
443// recompileForTest copies and replaces certain packages in pmain's dependency
444// graph. This is necessary for two reasons. First, if ptest is different than
445// preal, packages that import the package under test should get ptest instead
446// of preal. This is particularly important if pxtest depends on functionality
447// exposed in test sources in ptest. Second, if there is a main package
448// (other than pmain) anywhere, we need to set p.Internal.ForceLibrary and
449// clear p.Internal.BuildInfo in the test copy to prevent link conflicts.
450// This may happen if both -coverpkg and the command line patterns include
451// multiple main packages.
452func recompileForTest(pmain, preal, ptest, pxtest *Package) *PackageError {
453	// The "test copy" of preal is ptest.
454	// For each package that depends on preal, make a "test copy"
455	// that depends on ptest. And so on, up the dependency tree.
456	testCopy := map[*Package]*Package{preal: ptest}
457	for _, p := range PackageList([]*Package{pmain}) {
458		if p == preal {
459			continue
460		}
461		// Copy on write.
462		didSplit := p == pmain || p == pxtest || p == ptest
463		split := func() {
464			if didSplit {
465				return
466			}
467			didSplit = true
468			if testCopy[p] != nil {
469				panic("recompileForTest loop")
470			}
471			p1 := new(Package)
472			testCopy[p] = p1
473			*p1 = *p
474			p1.ForTest = preal.ImportPath
475			p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
476			copy(p1.Internal.Imports, p.Internal.Imports)
477			p1.Imports = make([]string, len(p.Imports))
478			copy(p1.Imports, p.Imports)
479			p = p1
480			p.Target = ""
481			p.Internal.BuildInfo = nil
482			p.Internal.ForceLibrary = true
483			p.Internal.PGOProfile = preal.Internal.PGOProfile
484		}
485
486		// Update p.Internal.Imports to use test copies.
487		for i, imp := range p.Internal.Imports {
488			if p1 := testCopy[imp]; p1 != nil && p1 != imp {
489				split()
490
491				// If the test dependencies cause a cycle with pmain, this is
492				// where it is introduced.
493				// (There are no cycles in the graph until this assignment occurs.)
494				p.Internal.Imports[i] = p1
495			}
496		}
497
498		// Force main packages the test imports to be built as libraries.
499		// Normal imports of main packages are forbidden by the package loader,
500		// but this can still happen if -coverpkg patterns include main packages:
501		// covered packages are imported by pmain. Linking multiple packages
502		// compiled with '-p main' causes duplicate symbol errors.
503		// See golang.org/issue/30907, golang.org/issue/34114.
504		if p.Name == "main" && p != pmain && p != ptest {
505			split()
506		}
507		// Split and attach PGO information to test dependencies if preal
508		// is built with PGO.
509		if preal.Internal.PGOProfile != "" && p.Internal.PGOProfile == "" {
510			split()
511		}
512	}
513
514	// Do search to find cycle.
515	// importerOf maps each import path to its importer nearest to p.
516	importerOf := map[*Package]*Package{}
517	for _, p := range ptest.Internal.Imports {
518		importerOf[p] = nil
519	}
520
521	// q is a breadth-first queue of packages to search for target.
522	// Every package added to q has a corresponding entry in pathTo.
523	//
524	// We search breadth-first for two reasons:
525	//
526	// 	1. We want to report the shortest cycle.
527	//
528	// 	2. If p contains multiple cycles, the first cycle we encounter might not
529	// 	   contain target. To ensure termination, we have to break all cycles
530	// 	   other than the first.
531	q := slices.Clip(ptest.Internal.Imports)
532	for len(q) > 0 {
533		p := q[0]
534		q = q[1:]
535		if p == ptest {
536			// The stack is supposed to be in the order x imports y imports z.
537			// We collect in the reverse order: z is imported by y is imported
538			// by x, and then we reverse it.
539			var stk []string
540			for p != nil {
541				stk = append(stk, p.ImportPath)
542				p = importerOf[p]
543			}
544			// complete the cycle: we set importer[p] = nil to break the cycle
545			// in importerOf, it's an implicit importerOf[p] == pTest. Add it
546			// back here since we reached nil in the loop above to demonstrate
547			// the cycle as (for example) package p imports package q imports package r
548			// imports package p.
549			stk = append(stk, ptest.ImportPath)
550			slices.Reverse(stk)
551
552			return &PackageError{
553				ImportStack:   stk,
554				Err:           errors.New("import cycle not allowed in test"),
555				IsImportCycle: true,
556			}
557		}
558		for _, dep := range p.Internal.Imports {
559			if _, ok := importerOf[dep]; !ok {
560				importerOf[dep] = p
561				q = append(q, dep)
562			}
563		}
564	}
565
566	return nil
567}
568
569// isTestFunc tells whether fn has the type of a testing function. arg
570// specifies the parameter type we look for: B, F, M or T.
571func isTestFunc(fn *ast.FuncDecl, arg string) bool {
572	if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
573		fn.Type.Params.List == nil ||
574		len(fn.Type.Params.List) != 1 ||
575		len(fn.Type.Params.List[0].Names) > 1 {
576		return false
577	}
578	ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
579	if !ok {
580		return false
581	}
582	// We can't easily check that the type is *testing.M
583	// because we don't know how testing has been imported,
584	// but at least check that it's *M or *something.M.
585	// Same applies for B, F and T.
586	if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
587		return true
588	}
589	if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
590		return true
591	}
592	return false
593}
594
595// isTest tells whether name looks like a test (or benchmark, according to prefix).
596// It is a Test (say) if there is a character after Test that is not a lower-case letter.
597// We don't want TesticularCancer.
598func isTest(name, prefix string) bool {
599	if !strings.HasPrefix(name, prefix) {
600		return false
601	}
602	if len(name) == len(prefix) { // "Test" is ok
603		return true
604	}
605	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
606	return !unicode.IsLower(rune)
607}
608
609type coverInfo struct {
610	Package *Package
611	Vars    map[string]*CoverVar
612}
613
614// loadTestFuncs returns the testFuncs describing the tests that will be run.
615// The returned testFuncs is always non-nil, even if an error occurred while
616// processing test files.
617func loadTestFuncs(ptest *Package) (*testFuncs, error) {
618	t := &testFuncs{
619		Package: ptest,
620	}
621	var err error
622	for _, file := range ptest.TestGoFiles {
623		if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
624			err = lerr
625		}
626	}
627	for _, file := range ptest.XTestGoFiles {
628		if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
629			err = lerr
630		}
631	}
632	return t, err
633}
634
635// formatTestmain returns the content of the _testmain.go file for t.
636func formatTestmain(t *testFuncs) ([]byte, error) {
637	var buf bytes.Buffer
638	tmpl := testmainTmpl
639	if cfg.Experiment.CoverageRedesign {
640		tmpl = testmainTmplNewCoverage
641	}
642	if err := tmpl.Execute(&buf, t); err != nil {
643		return nil, err
644	}
645	return buf.Bytes(), nil
646}
647
648type testFuncs struct {
649	Tests       []testFunc
650	Benchmarks  []testFunc
651	FuzzTargets []testFunc
652	Examples    []testFunc
653	TestMain    *testFunc
654	Package     *Package
655	ImportTest  bool
656	NeedTest    bool
657	ImportXtest bool
658	NeedXtest   bool
659	Cover       *TestCover
660}
661
662// ImportPath returns the import path of the package being tested, if it is within GOPATH.
663// This is printed by the testing package when running benchmarks.
664func (t *testFuncs) ImportPath() string {
665	pkg := t.Package.ImportPath
666	if strings.HasPrefix(pkg, "_/") {
667		return ""
668	}
669	if pkg == "command-line-arguments" {
670		return ""
671	}
672	return pkg
673}
674
675// Covered returns a string describing which packages are being tested for coverage.
676// If the covered package is the same as the tested package, it returns the empty string.
677// Otherwise it is a comma-separated human-readable list of packages beginning with
678// " in", ready for use in the coverage message.
679func (t *testFuncs) Covered() string {
680	if t.Cover == nil || t.Cover.Paths == nil {
681		return ""
682	}
683	return " in " + strings.Join(t.Cover.Paths, ", ")
684}
685
686func (t *testFuncs) CoverSelectedPackages() string {
687	if t.Cover == nil || t.Cover.Paths == nil {
688		return `[]string{"` + t.Package.ImportPath + `"}`
689	}
690	var sb strings.Builder
691	fmt.Fprintf(&sb, "[]string{")
692	for k, p := range t.Cover.Pkgs {
693		if k != 0 {
694			sb.WriteString(", ")
695		}
696		fmt.Fprintf(&sb, `"%s"`, p.ImportPath)
697	}
698	sb.WriteString("}")
699	return sb.String()
700}
701
702// Tested returns the name of the package being tested.
703func (t *testFuncs) Tested() string {
704	return t.Package.Name
705}
706
707type testFunc struct {
708	Package   string // imported package name (_test or _xtest)
709	Name      string // function name
710	Output    string // output, for examples
711	Unordered bool   // output is allowed to be unordered.
712}
713
714var testFileSet = token.NewFileSet()
715
716func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
717	// Pass in the overlaid source if we have an overlay for this file.
718	src, err := fsys.Open(filename)
719	if err != nil {
720		return err
721	}
722	defer src.Close()
723	f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments|parser.SkipObjectResolution)
724	if err != nil {
725		return err
726	}
727	for _, d := range f.Decls {
728		n, ok := d.(*ast.FuncDecl)
729		if !ok {
730			continue
731		}
732		if n.Recv != nil {
733			continue
734		}
735		name := n.Name.String()
736		switch {
737		case name == "TestMain":
738			if isTestFunc(n, "T") {
739				t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
740				*doImport, *seen = true, true
741				continue
742			}
743			err := checkTestFunc(n, "M")
744			if err != nil {
745				return err
746			}
747			if t.TestMain != nil {
748				return errors.New("multiple definitions of TestMain")
749			}
750			t.TestMain = &testFunc{pkg, name, "", false}
751			*doImport, *seen = true, true
752		case isTest(name, "Test"):
753			err := checkTestFunc(n, "T")
754			if err != nil {
755				return err
756			}
757			t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
758			*doImport, *seen = true, true
759		case isTest(name, "Benchmark"):
760			err := checkTestFunc(n, "B")
761			if err != nil {
762				return err
763			}
764			t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
765			*doImport, *seen = true, true
766		case isTest(name, "Fuzz"):
767			err := checkTestFunc(n, "F")
768			if err != nil {
769				return err
770			}
771			t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false})
772			*doImport, *seen = true, true
773		}
774	}
775	ex := doc.Examples(f)
776	sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
777	for _, e := range ex {
778		*doImport = true // import test file whether executed or not
779		if e.Output == "" && !e.EmptyOutput {
780			// Don't run examples with no output.
781			continue
782		}
783		t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
784		*seen = true
785	}
786	return nil
787}
788
789func checkTestFunc(fn *ast.FuncDecl, arg string) error {
790	var why string
791	if !isTestFunc(fn, arg) {
792		why = fmt.Sprintf("must be: func %s(%s *testing.%s)", fn.Name.String(), strings.ToLower(arg), arg)
793	}
794	if fn.Type.TypeParams.NumFields() > 0 {
795		why = "test functions cannot have type parameters"
796	}
797	if why != "" {
798		pos := testFileSet.Position(fn.Pos())
799		return fmt.Errorf("%s: wrong signature for %s, %s", pos, fn.Name.String(), why)
800	}
801	return nil
802}
803
804var testmainTmpl = lazytemplate.New("main", `
805// Code generated by 'go test'. DO NOT EDIT.
806
807package main
808
809import (
810	"os"
811{{if .TestMain}}
812	"reflect"
813{{end}}
814	"testing"
815	"testing/internal/testdeps"
816
817{{if .ImportTest}}
818	{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
819{{end}}
820{{if .ImportXtest}}
821	{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
822{{end}}
823{{if .Cover}}
824{{range $i, $p := .Cover.Vars}}
825	_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
826{{end}}
827{{end}}
828)
829
830var tests = []testing.InternalTest{
831{{range .Tests}}
832	{"{{.Name}}", {{.Package}}.{{.Name}}},
833{{end}}
834}
835
836var benchmarks = []testing.InternalBenchmark{
837{{range .Benchmarks}}
838	{"{{.Name}}", {{.Package}}.{{.Name}}},
839{{end}}
840}
841
842var fuzzTargets = []testing.InternalFuzzTarget{
843{{range .FuzzTargets}}
844	{"{{.Name}}", {{.Package}}.{{.Name}}},
845{{end}}
846}
847
848var examples = []testing.InternalExample{
849{{range .Examples}}
850	{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
851{{end}}
852}
853
854func init() {
855	testdeps.ImportPath = {{.ImportPath | printf "%q"}}
856}
857
858{{if .Cover}}
859
860// Only updated by init functions, so no need for atomicity.
861var (
862	coverCounters = make(map[string][]uint32)
863	coverBlocks = make(map[string][]testing.CoverBlock)
864)
865
866func init() {
867	{{range $i, $p := .Cover.Vars}}
868	{{range $file, $cover := $p.Vars}}
869	coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
870	{{end}}
871	{{end}}
872}
873
874func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
875	if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
876		panic("coverage: mismatched sizes")
877	}
878	if coverCounters[fileName] != nil {
879		// Already registered.
880		return
881	}
882	coverCounters[fileName] = counter
883	block := make([]testing.CoverBlock, len(counter))
884	for i := range counter {
885		block[i] = testing.CoverBlock{
886			Line0: pos[3*i+0],
887			Col0: uint16(pos[3*i+2]),
888			Line1: pos[3*i+1],
889			Col1: uint16(pos[3*i+2]>>16),
890			Stmts: numStmts[i],
891		}
892	}
893	coverBlocks[fileName] = block
894}
895{{end}}
896
897func main() {
898{{if .Cover}}
899	testing.RegisterCover(testing.Cover{
900		Mode: {{printf "%q" .Cover.Mode}},
901		Counters: coverCounters,
902		Blocks: coverBlocks,
903		CoveredPackages: {{printf "%q" .Covered}},
904	})
905{{end}}
906	m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
907{{with .TestMain}}
908	{{.Package}}.{{.Name}}(m)
909	os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
910{{else}}
911	os.Exit(m.Run())
912{{end}}
913}
914
915`)
916
917var testmainTmplNewCoverage = lazytemplate.New("main", `
918// Code generated by 'go test'. DO NOT EDIT.
919
920package main
921
922import (
923	"os"
924{{if .TestMain}}
925	"reflect"
926{{end}}
927	"testing"
928	"testing/internal/testdeps"
929{{if .Cover}}
930	"internal/coverage/cfile"
931{{end}}
932
933{{if .ImportTest}}
934	{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
935{{end}}
936{{if .ImportXtest}}
937	{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
938{{end}}
939)
940
941var tests = []testing.InternalTest{
942{{range .Tests}}
943	{"{{.Name}}", {{.Package}}.{{.Name}}},
944{{end}}
945}
946
947var benchmarks = []testing.InternalBenchmark{
948{{range .Benchmarks}}
949	{"{{.Name}}", {{.Package}}.{{.Name}}},
950{{end}}
951}
952
953var fuzzTargets = []testing.InternalFuzzTarget{
954{{range .FuzzTargets}}
955	{"{{.Name}}", {{.Package}}.{{.Name}}},
956{{end}}
957}
958
959var examples = []testing.InternalExample{
960{{range .Examples}}
961	{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
962{{end}}
963}
964
965func init() {
966{{if .Cover}}
967	testdeps.CoverMode = {{printf "%q" .Cover.Mode}}
968	testdeps.Covered = {{printf "%q" .Covered}}
969	testdeps.CoverSelectedPackages = {{printf "%s" .CoverSelectedPackages}}
970	testdeps.CoverSnapshotFunc = cfile.Snapshot
971	testdeps.CoverProcessTestDirFunc = cfile.ProcessCoverTestDir
972	testdeps.CoverMarkProfileEmittedFunc = cfile.MarkProfileEmitted
973
974{{end}}
975	testdeps.ImportPath = {{.ImportPath | printf "%q"}}
976}
977
978func main() {
979	m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
980{{with .TestMain}}
981	{{.Package}}.{{.Name}}(m)
982	os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
983{{else}}
984	os.Exit(m.Run())
985{{end}}
986}
987
988`)
989