...

Source file src/pkg/cmd/go/internal/load/test.go

     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		"cmd/go/internal/base"
    10		"cmd/go/internal/str"
    11		"errors"
    12		"fmt"
    13		"go/ast"
    14		"go/build"
    15		"go/doc"
    16		"go/parser"
    17		"go/token"
    18		"internal/lazytemplate"
    19		"path/filepath"
    20		"sort"
    21		"strings"
    22		"unicode"
    23		"unicode/utf8"
    24	)
    25	
    26	var TestMainDeps = []string{
    27		// Dependencies for testmain.
    28		"os",
    29		"testing",
    30		"testing/internal/testdeps",
    31	}
    32	
    33	type TestCover struct {
    34		Mode     string
    35		Local    bool
    36		Pkgs     []*Package
    37		Paths    []string
    38		Vars     []coverInfo
    39		DeclVars func(*Package, ...string) map[string]*CoverVar
    40	}
    41	
    42	// TestPackagesFor is like TestPackagesAndErrors but it returns
    43	// an error if the test packages or their dependencies have errors.
    44	// Only test packages without errors are returned.
    45	func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
    46		pmain, ptest, pxtest = TestPackagesAndErrors(p, cover)
    47		for _, p1 := range []*Package{ptest, pxtest, pmain} {
    48			if p1 == nil {
    49				// pxtest may be nil
    50				continue
    51			}
    52			if p1.Error != nil {
    53				err = p1.Error
    54				break
    55			}
    56			if len(p1.DepsErrors) > 0 {
    57				perr := p1.DepsErrors[0]
    58				perr.Pos = "" // show full import stack
    59				err = perr
    60				break
    61			}
    62		}
    63		if pmain.Error != nil || len(pmain.DepsErrors) > 0 {
    64			pmain = nil
    65		}
    66		if ptest.Error != nil || len(ptest.DepsErrors) > 0 {
    67			ptest = nil
    68		}
    69		if pxtest != nil && (pxtest.Error != nil || len(pxtest.DepsErrors) > 0) {
    70			pxtest = nil
    71		}
    72		return pmain, ptest, pxtest, err
    73	}
    74	
    75	// TestPackagesAndErrors returns three packages:
    76	//	- pmain, the package main corresponding to the test binary (running tests in ptest and pxtest).
    77	//	- ptest, the package p compiled with added "package p" test files.
    78	//	- pxtest, the result of compiling any "package p_test" (external) test files.
    79	//
    80	// If the package has no "package p_test" test files, pxtest will be nil.
    81	// If the non-test compilation of package p can be reused
    82	// (for example, if there are no "package p" test files and
    83	// package p need not be instrumented for coverage or any other reason),
    84	// then the returned ptest == p.
    85	//
    86	// An error is returned if the testmain source cannot be completely generated
    87	// (for example, due to a syntax error in a test file). No error will be
    88	// returned for errors loading packages, but the Error or DepsError fields
    89	// of the returned packages may be set.
    90	//
    91	// The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
    92	// or else there's no point in any of this.
    93	func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
    94		pre := newPreload()
    95		defer pre.flush()
    96		allImports := append([]string{}, p.TestImports...)
    97		allImports = append(allImports, p.XTestImports...)
    98		pre.preloadImports(allImports, p.Internal.Build)
    99	
   100		var ptestErr, pxtestErr *PackageError
   101		var imports, ximports []*Package
   102		var stk ImportStack
   103		stk.Push(p.ImportPath + " (test)")
   104		rawTestImports := str.StringList(p.TestImports)
   105		for i, path := range p.TestImports {
   106			p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
   107			if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
   108				// Same error that loadPackage returns (via reusePackage) in pkg.go.
   109				// Can't change that code, because that code is only for loading the
   110				// non-test copy of a package.
   111				ptestErr = &PackageError{
   112					ImportStack:   testImportStack(stk[0], p1, p.ImportPath),
   113					Err:           "import cycle not allowed in test",
   114					IsImportCycle: true,
   115				}
   116			}
   117			p.TestImports[i] = p1.ImportPath
   118			imports = append(imports, p1)
   119		}
   120		stk.Pop()
   121		stk.Push(p.ImportPath + "_test")
   122		pxtestNeedsPtest := false
   123		rawXTestImports := str.StringList(p.XTestImports)
   124		for i, path := range p.XTestImports {
   125			p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
   126			if p1.ImportPath == p.ImportPath {
   127				pxtestNeedsPtest = true
   128			} else {
   129				ximports = append(ximports, p1)
   130			}
   131			p.XTestImports[i] = p1.ImportPath
   132		}
   133		stk.Pop()
   134	
   135		// Test package.
   136		if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
   137			ptest = new(Package)
   138			*ptest = *p
   139			ptest.Error = ptestErr
   140			ptest.ForTest = p.ImportPath
   141			ptest.GoFiles = nil
   142			ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
   143			ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
   144			ptest.Target = ""
   145			// Note: The preparation of the vet config requires that common
   146			// indexes in ptest.Imports and ptest.Internal.RawImports
   147			// all line up (but RawImports can be shorter than the others).
   148			// That is, for 0 ≤ i < len(RawImports),
   149			// RawImports[i] is the import string in the program text, and
   150			// Imports[i] is the expanded import string (vendoring applied or relative path expanded away).
   151			// Any implicitly added imports appear in Imports and Internal.Imports
   152			// but not RawImports (because they were not in the source code).
   153			// We insert TestImports, imports, and rawTestImports at the start of
   154			// these lists to preserve the alignment.
   155			// Note that p.Internal.Imports may not be aligned with p.Imports/p.Internal.RawImports,
   156			// but we insert at the beginning there too just for consistency.
   157			ptest.Imports = str.StringList(p.TestImports, p.Imports)
   158			ptest.Internal.Imports = append(imports, p.Internal.Imports...)
   159			ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
   160			ptest.Internal.ForceLibrary = true
   161			ptest.Internal.BuildInfo = ""
   162			ptest.Internal.Build = new(build.Package)
   163			*ptest.Internal.Build = *p.Internal.Build
   164			m := map[string][]token.Position{}
   165			for k, v := range p.Internal.Build.ImportPos {
   166				m[k] = append(m[k], v...)
   167			}
   168			for k, v := range p.Internal.Build.TestImportPos {
   169				m[k] = append(m[k], v...)
   170			}
   171			ptest.Internal.Build.ImportPos = m
   172			ptest.collectDeps()
   173		} else {
   174			ptest = p
   175		}
   176	
   177		// External test package.
   178		if len(p.XTestGoFiles) > 0 {
   179			pxtest = &Package{
   180				PackagePublic: PackagePublic{
   181					Name:       p.Name + "_test",
   182					ImportPath: p.ImportPath + "_test",
   183					Root:       p.Root,
   184					Dir:        p.Dir,
   185					Goroot:     p.Goroot,
   186					GoFiles:    p.XTestGoFiles,
   187					Imports:    p.XTestImports,
   188					ForTest:    p.ImportPath,
   189					Error:      pxtestErr,
   190				},
   191				Internal: PackageInternal{
   192					LocalPrefix: p.Internal.LocalPrefix,
   193					Build: &build.Package{
   194						ImportPos: p.Internal.Build.XTestImportPos,
   195					},
   196					Imports:    ximports,
   197					RawImports: rawXTestImports,
   198	
   199					Asmflags:   p.Internal.Asmflags,
   200					Gcflags:    p.Internal.Gcflags,
   201					Ldflags:    p.Internal.Ldflags,
   202					Gccgoflags: p.Internal.Gccgoflags,
   203				},
   204			}
   205			if pxtestNeedsPtest {
   206				pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
   207			}
   208			pxtest.collectDeps()
   209		}
   210	
   211		// Build main package.
   212		pmain = &Package{
   213			PackagePublic: PackagePublic{
   214				Name:       "main",
   215				Dir:        p.Dir,
   216				GoFiles:    []string{"_testmain.go"},
   217				ImportPath: p.ImportPath + ".test",
   218				Root:       p.Root,
   219				Imports:    str.StringList(TestMainDeps),
   220			},
   221			Internal: PackageInternal{
   222				Build:      &build.Package{Name: "main"},
   223				BuildInfo:  p.Internal.BuildInfo,
   224				Asmflags:   p.Internal.Asmflags,
   225				Gcflags:    p.Internal.Gcflags,
   226				Ldflags:    p.Internal.Ldflags,
   227				Gccgoflags: p.Internal.Gccgoflags,
   228			},
   229		}
   230	
   231		// The generated main also imports testing, regexp, and os.
   232		// Also the linker introduces implicit dependencies reported by LinkerDeps.
   233		stk.Push("testmain")
   234		deps := TestMainDeps // cap==len, so safe for append
   235		for _, d := range LinkerDeps(p) {
   236			deps = append(deps, d)
   237		}
   238		for _, dep := range deps {
   239			if dep == ptest.ImportPath {
   240				pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
   241			} else {
   242				p1 := loadImport(pre, dep, "", nil, &stk, nil, 0)
   243				pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
   244			}
   245		}
   246		stk.Pop()
   247	
   248		if cover != nil && cover.Pkgs != nil {
   249			// Add imports, but avoid duplicates.
   250			seen := map[*Package]bool{p: true, ptest: true}
   251			for _, p1 := range pmain.Internal.Imports {
   252				seen[p1] = true
   253			}
   254			for _, p1 := range cover.Pkgs {
   255				if !seen[p1] {
   256					seen[p1] = true
   257					pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
   258				}
   259			}
   260		}
   261	
   262		allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports))
   263		allTestImports = append(allTestImports, pmain.Internal.Imports...)
   264		allTestImports = append(allTestImports, imports...)
   265		allTestImports = append(allTestImports, ximports...)
   266		setToolFlags(allTestImports...)
   267	
   268		// Do initial scan for metadata needed for writing _testmain.go
   269		// Use that metadata to update the list of imports for package main.
   270		// The list of imports is used by recompileForTest and by the loop
   271		// afterward that gathers t.Cover information.
   272		t, err := loadTestFuncs(ptest)
   273		if err != nil && pmain.Error == nil {
   274			pmain.Error = &PackageError{Err: err.Error()}
   275		}
   276		t.Cover = cover
   277		if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
   278			pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
   279			pmain.Imports = append(pmain.Imports, ptest.ImportPath)
   280			t.ImportTest = true
   281		}
   282		if pxtest != nil {
   283			pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
   284			pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
   285			t.ImportXtest = true
   286		}
   287		pmain.collectDeps()
   288	
   289		// Sort and dedup pmain.Imports.
   290		// Only matters for go list -test output.
   291		sort.Strings(pmain.Imports)
   292		w := 0
   293		for _, path := range pmain.Imports {
   294			if w == 0 || path != pmain.Imports[w-1] {
   295				pmain.Imports[w] = path
   296				w++
   297			}
   298		}
   299		pmain.Imports = pmain.Imports[:w]
   300		pmain.Internal.RawImports = str.StringList(pmain.Imports)
   301	
   302		// Replace pmain's transitive dependencies with test copies, as necessary.
   303		recompileForTest(pmain, p, ptest, pxtest)
   304	
   305		// Should we apply coverage analysis locally,
   306		// only for this package and only for this test?
   307		// Yes, if -cover is on but -coverpkg has not specified
   308		// a list of packages for global coverage.
   309		if cover != nil && cover.Local {
   310			ptest.Internal.CoverMode = cover.Mode
   311			var coverFiles []string
   312			coverFiles = append(coverFiles, ptest.GoFiles...)
   313			coverFiles = append(coverFiles, ptest.CgoFiles...)
   314			ptest.Internal.CoverVars = cover.DeclVars(ptest, coverFiles...)
   315		}
   316	
   317		for _, cp := range pmain.Internal.Imports {
   318			if len(cp.Internal.CoverVars) > 0 {
   319				t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars})
   320			}
   321		}
   322	
   323		data, err := formatTestmain(t)
   324		if err != nil && pmain.Error == nil {
   325			pmain.Error = &PackageError{Err: err.Error()}
   326		}
   327		if data != nil {
   328			pmain.Internal.TestmainGo = &data
   329		}
   330	
   331		return pmain, ptest, pxtest
   332	}
   333	
   334	func testImportStack(top string, p *Package, target string) []string {
   335		stk := []string{top, p.ImportPath}
   336	Search:
   337		for p.ImportPath != target {
   338			for _, p1 := range p.Internal.Imports {
   339				if p1.ImportPath == target || str.Contains(p1.Deps, target) {
   340					stk = append(stk, p1.ImportPath)
   341					p = p1
   342					continue Search
   343				}
   344			}
   345			// Can't happen, but in case it does...
   346			stk = append(stk, "<lost path to cycle>")
   347			break
   348		}
   349		return stk
   350	}
   351	
   352	// recompileForTest copies and replaces certain packages in pmain's dependency
   353	// graph. This is necessary for two reasons. First, if ptest is different than
   354	// preal, packages that import the package under test should get ptest instead
   355	// of preal. This is particularly important if pxtest depends on functionality
   356	// exposed in test sources in ptest. Second, if there is a main package
   357	// (other than pmain) anywhere, we need to set p.Internal.ForceLibrary and
   358	// clear p.Internal.BuildInfo in the test copy to prevent link conflicts.
   359	// This may happen if both -coverpkg and the command line patterns include
   360	// multiple main packages.
   361	func recompileForTest(pmain, preal, ptest, pxtest *Package) {
   362		// The "test copy" of preal is ptest.
   363		// For each package that depends on preal, make a "test copy"
   364		// that depends on ptest. And so on, up the dependency tree.
   365		testCopy := map[*Package]*Package{preal: ptest}
   366		for _, p := range PackageList([]*Package{pmain}) {
   367			if p == preal {
   368				continue
   369			}
   370			// Copy on write.
   371			didSplit := p == pmain || p == pxtest
   372			split := func() {
   373				if didSplit {
   374					return
   375				}
   376				didSplit = true
   377				if testCopy[p] != nil {
   378					panic("recompileForTest loop")
   379				}
   380				p1 := new(Package)
   381				testCopy[p] = p1
   382				*p1 = *p
   383				p1.ForTest = preal.ImportPath
   384				p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
   385				copy(p1.Internal.Imports, p.Internal.Imports)
   386				p1.Imports = make([]string, len(p.Imports))
   387				copy(p1.Imports, p.Imports)
   388				p = p1
   389				p.Target = ""
   390				p.Internal.BuildInfo = ""
   391				p.Internal.ForceLibrary = true
   392			}
   393	
   394			// Update p.Internal.Imports to use test copies.
   395			for i, imp := range p.Internal.Imports {
   396				if p1 := testCopy[imp]; p1 != nil && p1 != imp {
   397					split()
   398					p.Internal.Imports[i] = p1
   399				}
   400			}
   401	
   402			// Force main packages the test imports to be built as libraries.
   403			// Normal imports of main packages are forbidden by the package loader,
   404			// but this can still happen if -coverpkg patterns include main packages:
   405			// covered packages are imported by pmain. Linking multiple packages
   406			// compiled with '-p main' causes duplicate symbol errors.
   407			// See golang.org/issue/30907, golang.org/issue/34114.
   408			if p.Name == "main" && p != pmain && p != ptest {
   409				split()
   410			}
   411		}
   412	}
   413	
   414	// isTestFunc tells whether fn has the type of a testing function. arg
   415	// specifies the parameter type we look for: B, M or T.
   416	func isTestFunc(fn *ast.FuncDecl, arg string) bool {
   417		if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
   418			fn.Type.Params.List == nil ||
   419			len(fn.Type.Params.List) != 1 ||
   420			len(fn.Type.Params.List[0].Names) > 1 {
   421			return false
   422		}
   423		ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
   424		if !ok {
   425			return false
   426		}
   427		// We can't easily check that the type is *testing.M
   428		// because we don't know how testing has been imported,
   429		// but at least check that it's *M or *something.M.
   430		// Same applies for B and T.
   431		if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
   432			return true
   433		}
   434		if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
   435			return true
   436		}
   437		return false
   438	}
   439	
   440	// isTest tells whether name looks like a test (or benchmark, according to prefix).
   441	// It is a Test (say) if there is a character after Test that is not a lower-case letter.
   442	// We don't want TesticularCancer.
   443	func isTest(name, prefix string) bool {
   444		if !strings.HasPrefix(name, prefix) {
   445			return false
   446		}
   447		if len(name) == len(prefix) { // "Test" is ok
   448			return true
   449		}
   450		rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
   451		return !unicode.IsLower(rune)
   452	}
   453	
   454	type coverInfo struct {
   455		Package *Package
   456		Vars    map[string]*CoverVar
   457	}
   458	
   459	// loadTestFuncs returns the testFuncs describing the tests that will be run.
   460	// The returned testFuncs is always non-nil, even if an error occurred while
   461	// processing test files.
   462	func loadTestFuncs(ptest *Package) (*testFuncs, error) {
   463		t := &testFuncs{
   464			Package: ptest,
   465		}
   466		var err error
   467		for _, file := range ptest.TestGoFiles {
   468			if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
   469				err = lerr
   470			}
   471		}
   472		for _, file := range ptest.XTestGoFiles {
   473			if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
   474				err = lerr
   475			}
   476		}
   477		return t, err
   478	}
   479	
   480	// formatTestmain returns the content of the _testmain.go file for t.
   481	func formatTestmain(t *testFuncs) ([]byte, error) {
   482		var buf bytes.Buffer
   483		if err := testmainTmpl.Execute(&buf, t); err != nil {
   484			return nil, err
   485		}
   486		return buf.Bytes(), nil
   487	}
   488	
   489	type testFuncs struct {
   490		Tests       []testFunc
   491		Benchmarks  []testFunc
   492		Examples    []testFunc
   493		TestMain    *testFunc
   494		Package     *Package
   495		ImportTest  bool
   496		NeedTest    bool
   497		ImportXtest bool
   498		NeedXtest   bool
   499		Cover       *TestCover
   500	}
   501	
   502	// ImportPath returns the import path of the package being tested, if it is within GOPATH.
   503	// This is printed by the testing package when running benchmarks.
   504	func (t *testFuncs) ImportPath() string {
   505		pkg := t.Package.ImportPath
   506		if strings.HasPrefix(pkg, "_/") {
   507			return ""
   508		}
   509		if pkg == "command-line-arguments" {
   510			return ""
   511		}
   512		return pkg
   513	}
   514	
   515	// Covered returns a string describing which packages are being tested for coverage.
   516	// If the covered package is the same as the tested package, it returns the empty string.
   517	// Otherwise it is a comma-separated human-readable list of packages beginning with
   518	// " in", ready for use in the coverage message.
   519	func (t *testFuncs) Covered() string {
   520		if t.Cover == nil || t.Cover.Paths == nil {
   521			return ""
   522		}
   523		return " in " + strings.Join(t.Cover.Paths, ", ")
   524	}
   525	
   526	// Tested returns the name of the package being tested.
   527	func (t *testFuncs) Tested() string {
   528		return t.Package.Name
   529	}
   530	
   531	type testFunc struct {
   532		Package   string // imported package name (_test or _xtest)
   533		Name      string // function name
   534		Output    string // output, for examples
   535		Unordered bool   // output is allowed to be unordered.
   536	}
   537	
   538	var testFileSet = token.NewFileSet()
   539	
   540	func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
   541		f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
   542		if err != nil {
   543			return base.ExpandScanner(err)
   544		}
   545		for _, d := range f.Decls {
   546			n, ok := d.(*ast.FuncDecl)
   547			if !ok {
   548				continue
   549			}
   550			if n.Recv != nil {
   551				continue
   552			}
   553			name := n.Name.String()
   554			switch {
   555			case name == "TestMain":
   556				if isTestFunc(n, "T") {
   557					t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
   558					*doImport, *seen = true, true
   559					continue
   560				}
   561				err := checkTestFunc(n, "M")
   562				if err != nil {
   563					return err
   564				}
   565				if t.TestMain != nil {
   566					return errors.New("multiple definitions of TestMain")
   567				}
   568				t.TestMain = &testFunc{pkg, name, "", false}
   569				*doImport, *seen = true, true
   570			case isTest(name, "Test"):
   571				err := checkTestFunc(n, "T")
   572				if err != nil {
   573					return err
   574				}
   575				t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
   576				*doImport, *seen = true, true
   577			case isTest(name, "Benchmark"):
   578				err := checkTestFunc(n, "B")
   579				if err != nil {
   580					return err
   581				}
   582				t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
   583				*doImport, *seen = true, true
   584			}
   585		}
   586		ex := doc.Examples(f)
   587		sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
   588		for _, e := range ex {
   589			*doImport = true // import test file whether executed or not
   590			if e.Output == "" && !e.EmptyOutput {
   591				// Don't run examples with no output.
   592				continue
   593			}
   594			t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered})
   595			*seen = true
   596		}
   597		return nil
   598	}
   599	
   600	func checkTestFunc(fn *ast.FuncDecl, arg string) error {
   601		if !isTestFunc(fn, arg) {
   602			name := fn.Name.String()
   603			pos := testFileSet.Position(fn.Pos())
   604			return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg)
   605		}
   606		return nil
   607	}
   608	
   609	var testmainTmpl = lazytemplate.New("main", `
   610	// Code generated by 'go test'. DO NOT EDIT.
   611	
   612	package main
   613	
   614	import (
   615	{{if not .TestMain}}
   616		"os"
   617	{{end}}
   618		"testing"
   619		"testing/internal/testdeps"
   620	
   621	{{if .ImportTest}}
   622		{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
   623	{{end}}
   624	{{if .ImportXtest}}
   625		{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
   626	{{end}}
   627	{{if .Cover}}
   628	{{range $i, $p := .Cover.Vars}}
   629		_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
   630	{{end}}
   631	{{end}}
   632	)
   633	
   634	var tests = []testing.InternalTest{
   635	{{range .Tests}}
   636		{"{{.Name}}", {{.Package}}.{{.Name}}},
   637	{{end}}
   638	}
   639	
   640	var benchmarks = []testing.InternalBenchmark{
   641	{{range .Benchmarks}}
   642		{"{{.Name}}", {{.Package}}.{{.Name}}},
   643	{{end}}
   644	}
   645	
   646	var examples = []testing.InternalExample{
   647	{{range .Examples}}
   648		{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}},
   649	{{end}}
   650	}
   651	
   652	func init() {
   653		testdeps.ImportPath = {{.ImportPath | printf "%q"}}
   654	}
   655	
   656	{{if .Cover}}
   657	
   658	// Only updated by init functions, so no need for atomicity.
   659	var (
   660		coverCounters = make(map[string][]uint32)
   661		coverBlocks = make(map[string][]testing.CoverBlock)
   662	)
   663	
   664	func init() {
   665		{{range $i, $p := .Cover.Vars}}
   666		{{range $file, $cover := $p.Vars}}
   667		coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
   668		{{end}}
   669		{{end}}
   670	}
   671	
   672	func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
   673		if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
   674			panic("coverage: mismatched sizes")
   675		}
   676		if coverCounters[fileName] != nil {
   677			// Already registered.
   678			return
   679		}
   680		coverCounters[fileName] = counter
   681		block := make([]testing.CoverBlock, len(counter))
   682		for i := range counter {
   683			block[i] = testing.CoverBlock{
   684				Line0: pos[3*i+0],
   685				Col0: uint16(pos[3*i+2]),
   686				Line1: pos[3*i+1],
   687				Col1: uint16(pos[3*i+2]>>16),
   688				Stmts: numStmts[i],
   689			}
   690		}
   691		coverBlocks[fileName] = block
   692	}
   693	{{end}}
   694	
   695	func main() {
   696	{{if .Cover}}
   697		testing.RegisterCover(testing.Cover{
   698			Mode: {{printf "%q" .Cover.Mode}},
   699			Counters: coverCounters,
   700			Blocks: coverBlocks,
   701			CoveredPackages: {{printf "%q" .Covered}},
   702		})
   703	{{end}}
   704		m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples)
   705	{{with .TestMain}}
   706		{{.Package}}.{{.Name}}(m)
   707	{{else}}
   708		os.Exit(m.Run())
   709	{{end}}
   710	}
   711	
   712	`)
   713	

View as plain text