github.com/bir3/gocompiler@v0.3.205/src/cmd/gocmd/internal/load/test.go (about)

     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  
     5  package load
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"github.com/bir3/gocompiler/src/go/ast"
    13  	"github.com/bir3/gocompiler/src/go/build"
    14  	"github.com/bir3/gocompiler/src/go/doc"
    15  	"github.com/bir3/gocompiler/src/go/parser"
    16  	"github.com/bir3/gocompiler/src/go/token"
    17  	"github.com/bir3/gocompiler/src/internal/lazytemplate"
    18  	"path/filepath"
    19  	"sort"
    20  	"strings"
    21  	"unicode"
    22  	"unicode/utf8"
    23  
    24  	"github.com/bir3/gocompiler/src/cmd/gocmd/internal/cfg"
    25  	"github.com/bir3/gocompiler/src/cmd/gocmd/internal/fsys"
    26  	"github.com/bir3/gocompiler/src/cmd/gocmd/internal/str"
    27  	"github.com/bir3/gocompiler/src/cmd/gocmd/internal/trace"
    28  )
    29  
    30  var TestMainDeps = []string{
    31  	// Dependencies for testmain.
    32  	"os",
    33  	"reflect",
    34  	"testing",
    35  	"testing/internal/testdeps",
    36  }
    37  
    38  type TestCover struct {
    39  	Mode  string
    40  	Local bool
    41  	Pkgs  []*Package
    42  	Paths []string
    43  	Vars  []coverInfo
    44  }
    45  
    46  // TestPackagesFor is like TestPackagesAndErrors but it returns
    47  // an error if the test packages or their dependencies have errors.
    48  // Only test packages without errors are returned.
    49  func TestPackagesFor(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
    50  	pmain, ptest, pxtest = TestPackagesAndErrors(ctx, opts, p, cover)
    51  	for _, p1 := range []*Package{ptest, pxtest, pmain} {
    52  		if p1 == nil {
    53  			// pxtest may be nil
    54  			continue
    55  		}
    56  		if p1.Error != nil {
    57  			err = p1.Error
    58  			break
    59  		}
    60  		if len(p1.DepsErrors) > 0 {
    61  			perr := p1.DepsErrors[0]
    62  			err = perr
    63  			break
    64  		}
    65  	}
    66  	if pmain.Error != nil || len(pmain.DepsErrors) > 0 {
    67  		pmain = nil
    68  	}
    69  	if ptest.Error != nil || len(ptest.DepsErrors) > 0 {
    70  		ptest = nil
    71  	}
    72  	if pxtest != nil && (pxtest.Error != nil || len(pxtest.DepsErrors) > 0) {
    73  		pxtest = nil
    74  	}
    75  	return pmain, ptest, pxtest, err
    76  }
    77  
    78  // TestPackagesAndErrors returns three packages:
    79  //   - pmain, the package main corresponding to the test binary (running tests in ptest and pxtest).
    80  //   - ptest, the package p compiled with added "package p" test files.
    81  //   - pxtest, the result of compiling any "package p_test" (external) test files.
    82  //
    83  // If the package has no "package p_test" test files, pxtest will be nil.
    84  // If the non-test compilation of package p can be reused
    85  // (for example, if there are no "package p" test files and
    86  // package p need not be instrumented for coverage or any other reason),
    87  // then the returned ptest == p.
    88  //
    89  // An error is returned if the testmain source cannot be completely generated
    90  // (for example, due to a syntax error in a test file). No error will be
    91  // returned for errors loading packages, but the Error or DepsError fields
    92  // of the returned packages may be set.
    93  //
    94  // The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
    95  // or else there's no point in any of this.
    96  func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
    97  	ctx, span := trace.StartSpan(ctx, "load.TestPackagesAndErrors")
    98  	defer span.Done()
    99  
   100  	pre := newPreload()
   101  	defer pre.flush()
   102  	allImports := append([]string{}, p.TestImports...)
   103  	allImports = append(allImports, p.XTestImports...)
   104  	pre.preloadImports(ctx, opts, allImports, p.Internal.Build)
   105  
   106  	var ptestErr, pxtestErr *PackageError
   107  	var imports, ximports []*Package
   108  	var stk ImportStack
   109  	var testEmbed, xtestEmbed map[string][]string
   110  	stk.Push(p.ImportPath + " (test)")
   111  	rawTestImports := str.StringList(p.TestImports)
   112  	for i, path := range p.TestImports {
   113  		p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
   114  		if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
   115  			// Same error that loadPackage returns (via reusePackage) in pkg.go.
   116  			// Can't change that code, because that code is only for loading the
   117  			// non-test copy of a package.
   118  			ptestErr = &PackageError{
   119  				ImportStack:   importCycleStack(p1, p.ImportPath),
   120  				Err:           errors.New("import cycle not allowed in test"),
   121  				IsImportCycle: true,
   122  			}
   123  		}
   124  		p.TestImports[i] = p1.ImportPath
   125  		imports = append(imports, p1)
   126  	}
   127  	var err error
   128  	p.TestEmbedFiles, testEmbed, err = resolveEmbed(p.Dir, p.TestEmbedPatterns)
   129  	if err != nil && ptestErr == nil {
   130  		ptestErr = &PackageError{
   131  			ImportStack: stk.Copy(),
   132  			Err:         err,
   133  		}
   134  		embedErr := err.(*EmbedError)
   135  		ptestErr.setPos(p.Internal.Build.TestEmbedPatternPos[embedErr.Pattern])
   136  	}
   137  	stk.Pop()
   138  
   139  	stk.Push(p.ImportPath + "_test")
   140  	pxtestNeedsPtest := false
   141  	rawXTestImports := str.StringList(p.XTestImports)
   142  	for i, path := range p.XTestImports {
   143  		p1 := loadImport(ctx, opts, pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
   144  		if p1.ImportPath == p.ImportPath {
   145  			pxtestNeedsPtest = true
   146  		} else {
   147  			ximports = append(ximports, p1)
   148  		}
   149  		p.XTestImports[i] = p1.ImportPath
   150  	}
   151  	p.XTestEmbedFiles, xtestEmbed, err = resolveEmbed(p.Dir, p.XTestEmbedPatterns)
   152  	if err != nil && pxtestErr == nil {
   153  		pxtestErr = &PackageError{
   154  			ImportStack: stk.Copy(),
   155  			Err:         err,
   156  		}
   157  		embedErr := err.(*EmbedError)
   158  		pxtestErr.setPos(p.Internal.Build.XTestEmbedPatternPos[embedErr.Pattern])
   159  	}
   160  	stk.Pop()
   161  
   162  	// Test package.
   163  	if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
   164  		ptest = new(Package)
   165  		*ptest = *p
   166  		ptest.Error = ptestErr
   167  		ptest.ForTest = p.ImportPath
   168  		ptest.GoFiles = nil
   169  		ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
   170  		ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
   171  		ptest.Target = ""
   172  		// Note: The preparation of the vet config requires that common
   173  		// indexes in ptest.Imports and ptest.Internal.RawImports
   174  		// all line up (but RawImports can be shorter than the others).
   175  		// That is, for 0 ≤ i < len(RawImports),
   176  		// RawImports[i] is the import string in the program text, and
   177  		// Imports[i] is the expanded import string (vendoring applied or relative path expanded away).
   178  		// Any implicitly added imports appear in Imports and Internal.Imports
   179  		// but not RawImports (because they were not in the source code).
   180  		// We insert TestImports, imports, and rawTestImports at the start of
   181  		// these lists to preserve the alignment.
   182  		// Note that p.Internal.Imports may not be aligned with p.Imports/p.Internal.RawImports,
   183  		// but we insert at the beginning there too just for consistency.
   184  		ptest.Imports = str.StringList(p.TestImports, p.Imports)
   185  		ptest.Internal.Imports = append(imports, p.Internal.Imports...)
   186  		ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
   187  		ptest.Internal.ForceLibrary = true
   188  		ptest.Internal.BuildInfo = ""
   189  		ptest.Internal.Build = new(build.Package)
   190  		*ptest.Internal.Build = *p.Internal.Build
   191  		m := map[string][]token.Position{}
   192  		for k, v := range p.Internal.Build.ImportPos {
   193  			m[k] = append(m[k], v...)
   194  		}
   195  		for k, v := range p.Internal.Build.TestImportPos {
   196  			m[k] = append(m[k], v...)
   197  		}
   198  		ptest.Internal.Build.ImportPos = m
   199  		if testEmbed == nil && len(p.Internal.Embed) > 0 {
   200  			testEmbed = map[string][]string{}
   201  		}
   202  		for k, v := range p.Internal.Embed {
   203  			testEmbed[k] = v
   204  		}
   205  		ptest.Internal.Embed = testEmbed
   206  		ptest.EmbedFiles = str.StringList(p.EmbedFiles, p.TestEmbedFiles)
   207  		ptest.Internal.OrigImportPath = p.Internal.OrigImportPath
   208  		ptest.collectDeps()
   209  	} else {
   210  		ptest = p
   211  	}
   212  
   213  	// External test package.
   214  	if len(p.XTestGoFiles) > 0 {
   215  		pxtest = &Package{
   216  			PackagePublic: PackagePublic{
   217  				Name:       p.Name + "_test",
   218  				ImportPath: p.ImportPath + "_test",
   219  				Root:       p.Root,
   220  				Dir:        p.Dir,
   221  				Goroot:     p.Goroot,
   222  				GoFiles:    p.XTestGoFiles,
   223  				Imports:    p.XTestImports,
   224  				ForTest:    p.ImportPath,
   225  				Module:     p.Module,
   226  				Error:      pxtestErr,
   227  				EmbedFiles: p.XTestEmbedFiles,
   228  			},
   229  			Internal: PackageInternal{
   230  				LocalPrefix: p.Internal.LocalPrefix,
   231  				Build: &build.Package{
   232  					ImportPos: p.Internal.Build.XTestImportPos,
   233  				},
   234  				Imports:    ximports,
   235  				RawImports: rawXTestImports,
   236  
   237  				Asmflags:       p.Internal.Asmflags,
   238  				Gcflags:        p.Internal.Gcflags,
   239  				Ldflags:        p.Internal.Ldflags,
   240  				Gccgoflags:     p.Internal.Gccgoflags,
   241  				Embed:          xtestEmbed,
   242  				OrigImportPath: p.Internal.OrigImportPath,
   243  			},
   244  		}
   245  		if pxtestNeedsPtest {
   246  			pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
   247  		}
   248  		pxtest.collectDeps()
   249  	}
   250  
   251  	// Build main package.
   252  	pmain = &Package{
   253  		PackagePublic: PackagePublic{
   254  			Name:       "main",
   255  			Dir:        p.Dir,
   256  			GoFiles:    []string{"_testmain.go"},
   257  			ImportPath: p.ImportPath + ".test",
   258  			Root:       p.Root,
   259  			Imports:    str.StringList(TestMainDeps),
   260  			Module:     p.Module,
   261  		},
   262  		Internal: PackageInternal{
   263  			Build:          &build.Package{Name: "main"},
   264  			BuildInfo:      p.Internal.BuildInfo,
   265  			Asmflags:       p.Internal.Asmflags,
   266  			Gcflags:        p.Internal.Gcflags,
   267  			Ldflags:        p.Internal.Ldflags,
   268  			Gccgoflags:     p.Internal.Gccgoflags,
   269  			OrigImportPath: p.Internal.OrigImportPath,
   270  		},
   271  	}
   272  
   273  	// The generated main also imports testing, regexp, and os.
   274  	// Also the linker introduces implicit dependencies reported by LinkerDeps.
   275  	stk.Push("testmain")
   276  	deps := TestMainDeps // cap==len, so safe for append
   277  	for _, d := range LinkerDeps(p) {
   278  		deps = append(deps, d)
   279  	}
   280  	for _, dep := range deps {
   281  		if dep == ptest.ImportPath {
   282  			pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
   283  		} else {
   284  			p1 := loadImport(ctx, opts, pre, dep, "", nil, &stk, nil, 0)
   285  			pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
   286  		}
   287  	}
   288  	stk.Pop()
   289  
   290  	if cover != nil && cover.Pkgs != nil && !cfg.Experiment.CoverageRedesign {
   291  		// Add imports, but avoid duplicates.
   292  		seen := map[*Package]bool{p: true, ptest: true}
   293  		for _, p1 := range pmain.Internal.Imports {
   294  			seen[p1] = true
   295  		}
   296  		for _, p1 := range cover.Pkgs {
   297  			if seen[p1] {
   298  				// Don't add duplicate imports.
   299  				continue
   300  			}
   301  			seen[p1] = true
   302  			pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
   303  		}
   304  	}
   305  
   306  	allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports))
   307  	allTestImports = append(allTestImports, pmain.Internal.Imports...)
   308  	allTestImports = append(allTestImports, imports...)
   309  	allTestImports = append(allTestImports, ximports...)
   310  	setToolFlags(allTestImports...)
   311  
   312  	// Do initial scan for metadata needed for writing _testmain.go
   313  	// Use that metadata to update the list of imports for package main.
   314  	// The list of imports is used by recompileForTest and by the loop
   315  	// afterward that gathers t.Cover information.
   316  	t, err := loadTestFuncs(ptest)
   317  	if err != nil && pmain.Error == nil {
   318  		pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
   319  	}
   320  	t.Cover = cover
   321  	if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
   322  		pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
   323  		pmain.Imports = append(pmain.Imports, ptest.ImportPath)
   324  		t.ImportTest = true
   325  	}
   326  	if pxtest != nil {
   327  		pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
   328  		pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
   329  		t.ImportXtest = true
   330  	}
   331  	pmain.collectDeps()
   332  
   333  	// Sort and dedup pmain.Imports.
   334  	// Only matters for go list -test output.
   335  	sort.Strings(pmain.Imports)
   336  	w := 0
   337  	for _, path := range pmain.Imports {
   338  		if w == 0 || path != pmain.Imports[w-1] {
   339  			pmain.Imports[w] = path
   340  			w++
   341  		}
   342  	}
   343  	pmain.Imports = pmain.Imports[:w]
   344  	pmain.Internal.RawImports = str.StringList(pmain.Imports)
   345  
   346  	// Replace pmain's transitive dependencies with test copies, as necessary.
   347  	recompileForTest(pmain, p, ptest, pxtest)
   348  
   349  	if cover != nil {
   350  		if cfg.Experiment.CoverageRedesign {
   351  			// Here ptest needs to inherit the proper coverage mode (since
   352  			// it contains p's Go files), whereas pmain contains only
   353  			// test harness code (don't want to instrument it, and
   354  			// we don't want coverage hooks in the pkg init).
   355  			ptest.Internal.CoverMode = p.Internal.CoverMode
   356  			pmain.Internal.CoverMode = "testmain"
   357  		}
   358  		// Should we apply coverage analysis locally, only for this
   359  		// package and only for this test? Yes, if -cover is on but
   360  		// -coverpkg has not specified a list of packages for global
   361  		// coverage.
   362  		if cover.Local {
   363  			ptest.Internal.CoverMode = cover.Mode
   364  
   365  			if !cfg.Experiment.CoverageRedesign {
   366  				var coverFiles []string
   367  				coverFiles = append(coverFiles, ptest.GoFiles...)
   368  				coverFiles = append(coverFiles, ptest.CgoFiles...)
   369  				ptest.Internal.CoverVars = DeclareCoverVars(ptest, coverFiles...)
   370  			}
   371  		}
   372  
   373  		if !cfg.Experiment.CoverageRedesign {
   374  			for _, cp := range pmain.Internal.Imports {
   375  				if len(cp.Internal.CoverVars) > 0 {
   376  					t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars})
   377  				}
   378  			}
   379  		}
   380  	}
   381  
   382  	data, err := formatTestmain(t)
   383  	if err != nil && pmain.Error == nil {
   384  		pmain.Error = &PackageError{Err: err}
   385  	}
   386  	// Set TestmainGo even if it is empty: the presence of a TestmainGo
   387  	// indicates that this package is, in fact, a test main.
   388  	pmain.Internal.TestmainGo = &data
   389  
   390  	return pmain, ptest, pxtest
   391  }
   392  
   393  // importCycleStack returns an import stack from p to the package whose import
   394  // path is target.
   395  func importCycleStack(p *Package, target string) []string {
   396  	// importerOf maps each import path to its importer nearest to p.
   397  	importerOf := map[string]string{p.ImportPath: ""}
   398  
   399  	// q is a breadth-first queue of packages to search for target.
   400  	// Every package added to q has a corresponding entry in pathTo.
   401  	//
   402  	// We search breadth-first for two reasons:
   403  	//
   404  	// 	1. We want to report the shortest cycle.
   405  	//
   406  	// 	2. If p contains multiple cycles, the first cycle we encounter might not
   407  	// 	   contain target. To ensure termination, we have to break all cycles
   408  	// 	   other than the first.
   409  	q := []*Package{p}
   410  
   411  	for len(q) > 0 {
   412  		p := q[0]
   413  		q = q[1:]
   414  		if path := p.ImportPath; path == target {
   415  			var stk []string
   416  			for path != "" {
   417  				stk = append(stk, path)
   418  				path = importerOf[path]
   419  			}
   420  			return stk
   421  		}
   422  		for _, dep := range p.Internal.Imports {
   423  			if _, ok := importerOf[dep.ImportPath]; !ok {
   424  				importerOf[dep.ImportPath] = p.ImportPath
   425  				q = append(q, dep)
   426  			}
   427  		}
   428  	}
   429  
   430  	panic("lost path to cycle")
   431  }
   432  
   433  // recompileForTest copies and replaces certain packages in pmain's dependency
   434  // graph. This is necessary for two reasons. First, if ptest is different than
   435  // preal, packages that import the package under test should get ptest instead
   436  // of preal. This is particularly important if pxtest depends on functionality
   437  // exposed in test sources in ptest. Second, if there is a main package
   438  // (other than pmain) anywhere, we need to set p.Internal.ForceLibrary and
   439  // clear p.Internal.BuildInfo in the test copy to prevent link conflicts.
   440  // This may happen if both -coverpkg and the command line patterns include
   441  // multiple main packages.
   442  func recompileForTest(pmain, preal, ptest, pxtest *Package) {
   443  	// The "test copy" of preal is ptest.
   444  	// For each package that depends on preal, make a "test copy"
   445  	// that depends on ptest. And so on, up the dependency tree.
   446  	testCopy := map[*Package]*Package{preal: ptest}
   447  	for _, p := range PackageList([]*Package{pmain}) {
   448  		if p == preal {
   449  			continue
   450  		}
   451  		// Copy on write.
   452  		didSplit := p == pmain || p == pxtest
   453  		split := func() {
   454  			if didSplit {
   455  				return
   456  			}
   457  			didSplit = true
   458  			if testCopy[p] != nil {
   459  				panic("recompileForTest loop")
   460  			}
   461  			p1 := new(Package)
   462  			testCopy[p] = p1
   463  			*p1 = *p
   464  			p1.ForTest = preal.ImportPath
   465  			p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
   466  			copy(p1.Internal.Imports, p.Internal.Imports)
   467  			p1.Imports = make([]string, len(p.Imports))
   468  			copy(p1.Imports, p.Imports)
   469  			p = p1
   470  			p.Target = ""
   471  			p.Internal.BuildInfo = ""
   472  			p.Internal.ForceLibrary = true
   473  		}
   474  
   475  		// Update p.Internal.Imports to use test copies.
   476  		for i, imp := range p.Internal.Imports {
   477  			if p1 := testCopy[imp]; p1 != nil && p1 != imp {
   478  				split()
   479  				p.Internal.Imports[i] = p1
   480  			}
   481  		}
   482  
   483  		// Force main packages the test imports to be built as libraries.
   484  		// Normal imports of main packages are forbidden by the package loader,
   485  		// but this can still happen if -coverpkg patterns include main packages:
   486  		// covered packages are imported by pmain. Linking multiple packages
   487  		// compiled with '-p main' causes duplicate symbol errors.
   488  		// See golang.org/issue/30907, golang.org/issue/34114.
   489  		if p.Name == "main" && p != pmain && p != ptest {
   490  			split()
   491  		}
   492  	}
   493  }
   494  
   495  // isTestFunc tells whether fn has the type of a testing function. arg
   496  // specifies the parameter type we look for: B, M or T.
   497  func isTestFunc(fn *ast.FuncDecl, arg string) bool {
   498  	if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
   499  		fn.Type.Params.List == nil ||
   500  		len(fn.Type.Params.List) != 1 ||
   501  		len(fn.Type.Params.List[0].Names) > 1 {
   502  		return false
   503  	}
   504  	ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
   505  	if !ok {
   506  		return false
   507  	}
   508  	// We can't easily check that the type is *testing.M
   509  	// because we don't know how testing has been imported,
   510  	// but at least check that it's *M or *something.M.
   511  	// Same applies for B and T.
   512  	if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
   513  		return true
   514  	}
   515  	if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
   516  		return true
   517  	}
   518  	return false
   519  }
   520  
   521  // isTest tells whether name looks like a test (or benchmark, according to prefix).
   522  // It is a Test (say) if there is a character after Test that is not a lower-case letter.
   523  // We don't want TesticularCancer.
   524  func isTest(name, prefix string) bool {
   525  	if !strings.HasPrefix(name, prefix) {
   526  		return false
   527  	}
   528  	if len(name) == len(prefix) { // "Test" is ok
   529  		return true
   530  	}
   531  	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
   532  	return !unicode.IsLower(rune)
   533  }
   534  
   535  type coverInfo struct {
   536  	Package *Package
   537  	Vars    map[string]*CoverVar
   538  }
   539  
   540  // loadTestFuncs returns the testFuncs describing the tests that will be run.
   541  // The returned testFuncs is always non-nil, even if an error occurred while
   542  // processing test files.
   543  func loadTestFuncs(ptest *Package) (*testFuncs, error) {
   544  	t := &testFuncs{
   545  		Package: ptest,
   546  	}
   547  	var err error
   548  	for _, file := range ptest.TestGoFiles {
   549  		if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
   550  			err = lerr
   551  		}
   552  	}
   553  	for _, file := range ptest.XTestGoFiles {
   554  		if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
   555  			err = lerr
   556  		}
   557  	}
   558  	return t, err
   559  }
   560  
   561  // formatTestmain returns the content of the _testmain.go file for t.
   562  func formatTestmain(t *testFuncs) ([]byte, error) {
   563  	var buf bytes.Buffer
   564  	tmpl := testmainTmpl
   565  	if cfg.Experiment.CoverageRedesign {
   566  		tmpl = testmainTmplNewCoverage
   567  	}
   568  	if err := tmpl.Execute(&buf, t); err != nil {
   569  		return nil, err
   570  	}
   571  	return buf.Bytes(), nil
   572  }
   573  
   574  type testFuncs struct {
   575  	Tests       []testFunc
   576  	Benchmarks  []testFunc
   577  	FuzzTargets []testFunc
   578  	Examples    []testFunc
   579  	TestMain    *testFunc
   580  	Package     *Package
   581  	ImportTest  bool
   582  	NeedTest    bool
   583  	ImportXtest bool
   584  	NeedXtest   bool
   585  	Cover       *TestCover
   586  }
   587  
   588  // ImportPath returns the import path of the package being tested, if it is within GOPATH.
   589  // This is printed by the testing package when running benchmarks.
   590  func (t *testFuncs) ImportPath() string {
   591  	pkg := t.Package.ImportPath
   592  	if strings.HasPrefix(pkg, "_/") {
   593  		return ""
   594  	}
   595  	if pkg == "command-line-arguments" {
   596  		return ""
   597  	}
   598  	return pkg
   599  }
   600  
   601  // Covered returns a string describing which packages are being tested for coverage.
   602  // If the covered package is the same as the tested package, it returns the empty string.
   603  // Otherwise it is a comma-separated human-readable list of packages beginning with
   604  // " in", ready for use in the coverage message.
   605  func (t *testFuncs) Covered() string {
   606  	if t.Cover == nil || t.Cover.Paths == nil {
   607  		return ""
   608  	}
   609  	return " in " + strings.Join(t.Cover.Paths, ", ")
   610  }
   611  
   612  // Tested returns the name of the package being tested.
   613  func (t *testFuncs) Tested() string {
   614  	return t.Package.Name
   615  }
   616  
   617  type testFunc struct {
   618  	Package   string // imported package name (_test or _xtest)
   619  	Name      string // function name
   620  	Output    string // output, for examples
   621  	Unordered bool   // output is allowed to be unordered.
   622  }
   623  
   624  var testFileSet = token.NewFileSet()
   625  
   626  func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
   627  	// Pass in the overlaid source if we have an overlay for this file.
   628  	src, err := fsys.Open(filename)
   629  	if err != nil {
   630  		return err
   631  	}
   632  	defer src.Close()
   633  	f, err := parser.ParseFile(testFileSet, filename, src, parser.ParseComments|parser.SkipObjectResolution)
   634  	if err != nil {
   635  		return err
   636  	}
   637  	for _, d := range f.Decls {
   638  		n, ok := d.(*ast.FuncDecl)
   639  		if !ok {
   640  			continue
   641  		}
   642  		if n.Recv != nil {
   643  			continue
   644  		}
   645  		name := n.Name.String()
   646  		switch {
   647  		case name == "TestMain":
   648  			if isTestFunc(n, "T") {
   649  				t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
   650  				*doImport, *seen = true, true
   651  				continue
   652  			}
   653  			err := checkTestFunc(n, "M")
   654  			if err != nil {
   655  				return err
   656  			}
   657  			if t.TestMain != nil {
   658  				return errors.New("multiple definitions of TestMain")
   659  			}
   660  			t.TestMain = &testFunc{pkg, name, "", false}
   661  			*doImport, *seen = true, true
   662  		case isTest(name, "Test"):
   663  			err := checkTestFunc(n, "T")
   664  			if err != nil {
   665  				return err
   666  			}
   667  			t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
   668  			*doImport, *seen = true, true
   669  		case isTest(name, "Benchmark"):
   670  			err := checkTestFunc(n, "B")
   671  			if err != nil {
   672  				return err
   673  			}
   674  			t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
   675  			*doImport, *seen = true, true
   676  		case isTest(name, "Fuzz"):
   677  			err := checkTestFunc(n, "F")
   678  			if err != nil {
   679  				return err
   680  			}
   681  			t.FuzzTargets = append(t.FuzzTargets, testFunc{pkg, name, "", false})
   682  			*doImport, *seen = true, true
   683  		}
   684  	}
   685  	ex := doc.Examples(f)
   686  	sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
   687  	for _, e := range ex {
   688  		*doImport = true // import test file whether executed or not
   689  		if e.Output == "" && !e.EmptyOutput {
   690  			// Don't run examples with no output.
   691  			continue
   692  		}
   693  		t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
   694  		*seen = true
   695  	}
   696  	return nil
   697  }
   698  
   699  func checkTestFunc(fn *ast.FuncDecl, arg string) error {
   700  	var why string
   701  	if !isTestFunc(fn, arg) {
   702  		why = fmt.Sprintf("must be: func %s(%s *testing.%s)", fn.Name.String(), strings.ToLower(arg), arg)
   703  	}
   704  	if fn.Type.TypeParams.NumFields() > 0 {
   705  		why = "test functions cannot have type parameters"
   706  	}
   707  	if why != "" {
   708  		pos := testFileSet.Position(fn.Pos())
   709  		return fmt.Errorf("%s: wrong signature for %s, %s", pos, fn.Name.String(), why)
   710  	}
   711  	return nil
   712  }
   713  
   714  var testmainTmpl = lazytemplate.New("main", `
   715  // Code generated by 'go test'. DO NOT EDIT.
   716  
   717  package main
   718  
   719  import (
   720  	"os"
   721  {{if .TestMain}}
   722  	"reflect"
   723  {{end}}
   724  	"testing"
   725  	"testing/internal/testdeps"
   726  
   727  {{if .ImportTest}}
   728  	{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
   729  {{end}}
   730  {{if .ImportXtest}}
   731  	{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
   732  {{end}}
   733  {{if .Cover}}
   734  {{range $i, $p := .Cover.Vars}}
   735  	_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
   736  {{end}}
   737  {{end}}
   738  )
   739  
   740  var tests = []testing.InternalTest{
   741  {{range .Tests}}
   742  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   743  {{end}}
   744  }
   745  
   746  var benchmarks = []testing.InternalBenchmark{
   747  {{range .Benchmarks}}
   748  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   749  {{end}}
   750  }
   751  
   752  var fuzzTargets = []testing.InternalFuzzTarget{
   753  {{range .FuzzTargets}}
   754  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   755  {{end}}
   756  }
   757  
   758  var examples = []testing.InternalExample{
   759  {{range .Examples}}
   760  	{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
   761  {{end}}
   762  }
   763  
   764  func init() {
   765  	testdeps.ImportPath = {{.ImportPath | printf "%q"}}
   766  }
   767  
   768  {{if .Cover}}
   769  
   770  // Only updated by init functions, so no need for atomicity.
   771  var (
   772  	coverCounters = make(map[string][]uint32)
   773  	coverBlocks = make(map[string][]testing.CoverBlock)
   774  )
   775  
   776  func init() {
   777  	{{range $i, $p := .Cover.Vars}}
   778  	{{range $file, $cover := $p.Vars}}
   779  	coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
   780  	{{end}}
   781  	{{end}}
   782  }
   783  
   784  func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
   785  	if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
   786  		panic("coverage: mismatched sizes")
   787  	}
   788  	if coverCounters[fileName] != nil {
   789  		// Already registered.
   790  		return
   791  	}
   792  	coverCounters[fileName] = counter
   793  	block := make([]testing.CoverBlock, len(counter))
   794  	for i := range counter {
   795  		block[i] = testing.CoverBlock{
   796  			Line0: pos[3*i+0],
   797  			Col0: uint16(pos[3*i+2]),
   798  			Line1: pos[3*i+1],
   799  			Col1: uint16(pos[3*i+2]>>16),
   800  			Stmts: numStmts[i],
   801  		}
   802  	}
   803  	coverBlocks[fileName] = block
   804  }
   805  {{end}}
   806  
   807  func main() {
   808  {{if .Cover}}
   809  	testing.RegisterCover(testing.Cover{
   810  		Mode: {{printf "%q" .Cover.Mode}},
   811  		Counters: coverCounters,
   812  		Blocks: coverBlocks,
   813  		CoveredPackages: {{printf "%q" .Covered}},
   814  	})
   815  {{end}}
   816  	m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
   817  {{with .TestMain}}
   818  	{{.Package}}.{{.Name}}(m)
   819  	os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
   820  {{else}}
   821  	os.Exit(m.Run())
   822  {{end}}
   823  }
   824  
   825  `)
   826  
   827  var testmainTmplNewCoverage = lazytemplate.New("main", `
   828  // Code generated by 'go test'. DO NOT EDIT.
   829  
   830  package main
   831  
   832  import (
   833  	"os"
   834  {{if .Cover}}
   835  	_ "unsafe"
   836  {{end}}
   837  {{if .TestMain}}
   838  	"reflect"
   839  {{end}}
   840  	"testing"
   841  	"testing/internal/testdeps"
   842  
   843  {{if .ImportTest}}
   844  	{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
   845  {{end}}
   846  {{if .ImportXtest}}
   847  	{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
   848  {{end}}
   849  )
   850  
   851  var tests = []testing.InternalTest{
   852  {{range .Tests}}
   853  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   854  {{end}}
   855  }
   856  
   857  var benchmarks = []testing.InternalBenchmark{
   858  {{range .Benchmarks}}
   859  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   860  {{end}}
   861  }
   862  
   863  var fuzzTargets = []testing.InternalFuzzTarget{
   864  {{range .FuzzTargets}}
   865  	{"{{.Name}}", {{.Package}}.{{.Name}}},
   866  {{end}}
   867  }
   868  
   869  var examples = []testing.InternalExample{
   870  {{range .Examples}}
   871  	{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
   872  {{end}}
   873  }
   874  
   875  func init() {
   876  	testdeps.ImportPath = {{.ImportPath | printf "%q"}}
   877  }
   878  
   879  {{if .Cover}}
   880  
   881  //go:linkname runtime_coverage_processCoverTestDir runtime/coverage.processCoverTestDir
   882  func runtime_coverage_processCoverTestDir(dir string, cfile string, cmode string, cpkgs string) error
   883  
   884  //go:linkname testing_registerCover2 testing.registerCover2
   885  func testing_registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error))
   886  
   887  //go:linkname runtime_coverage_markProfileEmitted runtime/coverage.markProfileEmitted
   888  func runtime_coverage_markProfileEmitted(val bool)
   889  
   890  func coverTearDown(coverprofile string, gocoverdir string) (string, error) {
   891  	var err error
   892  	if gocoverdir == "" {
   893  		gocoverdir, err = os.MkdirTemp("", "gocoverdir")
   894  		if err != nil {
   895  			return "error setting GOCOVERDIR: bad os.MkdirTemp return", err
   896  		}
   897  		defer os.RemoveAll(gocoverdir)
   898  	}
   899  	runtime_coverage_markProfileEmitted(true)
   900  	cmode := {{printf "%q" .Cover.Mode}}
   901  	if err := runtime_coverage_processCoverTestDir(gocoverdir, coverprofile, cmode, {{printf "%q" .Covered}}); err != nil {
   902  		return "error generating coverage report", err
   903  	}
   904  	return "", nil
   905  }
   906  {{end}}
   907  
   908  func main() {
   909  {{if .Cover}}
   910  	testing_registerCover2({{printf "%q" .Cover.Mode}}, coverTearDown)
   911  {{end}}
   912  	m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
   913  {{with .TestMain}}
   914  	{{.Package}}.{{.Name}}(m)
   915  	os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
   916  {{else}}
   917  	os.Exit(m.Run())
   918  {{end}}
   919  }
   920  
   921  `)