diff --git a/src/cmd/compile/internal/test/inl_test.go b/src/cmd/compile/internal/test/inl_test.go index 9a1a8bb105..f1f6c34bfc 100644 --- a/src/cmd/compile/internal/test/inl_test.go +++ b/src/cmd/compile/internal/test/inl_test.go @@ -375,10 +375,6 @@ func TestIssue56044(t *testing.T) { if testing.Short() { t.Skipf("skipping test: too long for short mode") } - if !goexperiment.CoverageRedesign { - t.Skipf("skipping new coverage tests (experiment not enabled)") - } - testenv.MustHaveGoBuild(t) modes := []string{"-covermode=set", "-covermode=atomic"} diff --git a/src/cmd/covdata/tool_test.go b/src/cmd/covdata/tool_test.go index 757a245047..730adf4c8e 100644 --- a/src/cmd/covdata/tool_test.go +++ b/src/cmd/covdata/tool_test.go @@ -9,7 +9,6 @@ import ( "flag" "fmt" "internal/coverage/pods" - "internal/goexperiment" "internal/testenv" "log" "os" @@ -150,9 +149,6 @@ const debugWorkDir = false func TestCovTool(t *testing.T) { testenv.MustHaveGoBuild(t) - if !goexperiment.CoverageRedesign { - t.Skipf("stubbed out due to goexperiment.CoverageRedesign=false") - } dir := tempDir(t) if testing.Short() { t.Skip() diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 2220863b8e..b9cf7202c2 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2484,7 +2484,6 @@ // GOCOVERDIR // Directory into which to write code coverage data files // generated by running a "go build -cover" binary. -// Requires that GOEXPERIMENT=coverageredesign is enabled. // // Special-purpose environment variables: // diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index ccc04c25d2..d2f0fd173b 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -657,7 +657,6 @@ Environment variables for use with code coverage: GOCOVERDIR Directory into which to write code coverage data files generated by running a "go build -cover" binary. - Requires that GOEXPERIMENT=coverageredesign is enabled. Special-purpose environment variables: diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 04fdadef3f..d6cba5a4e0 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -347,9 +347,7 @@ func init() { CmdList.Run = runList // break init cycle // Omit build -json because list has its own -json work.AddBuildFlags(CmdList, work.OmitJSONFlag) - if cfg.Experiment != nil && cfg.Experiment.CoverageRedesign { - work.AddCoverFlags(CmdList, nil) - } + work.AddCoverFlags(CmdList, nil) CmdList.Flag.Var(&listJsonFields, "json", "") } @@ -728,7 +726,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { b.IsCmdList = true b.NeedExport = *listExport b.NeedCompiledGoFiles = *listCompiled - if cfg.Experiment.CoverageRedesign && cfg.BuildCover { + if cfg.BuildCover { load.PrepareForCoverageBuild(pkgs) } a := &work.Action{} diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 15f6b2e87b..0c4639ce82 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -8,7 +8,6 @@ package load import ( "bytes" "context" - "crypto/sha256" "encoding/json" "errors" "fmt" @@ -218,27 +217,26 @@ func (p *Package) IsTestOnly() bool { type PackageInternal struct { // Unexported fields are not part of the public API. Build *build.Package - Imports []*Package // this package's direct imports - CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports - RawImports []string // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports - ForceLibrary bool // this package is a library (even if named "main") - CmdlineFiles bool // package built from files listed on command line - CmdlinePkg bool // package listed on command line - CmdlinePkgLiteral bool // package listed as literal on command line (not via wildcard) - Local bool // imported via local path (./ or ../) - LocalPrefix string // interpret ./ and ../ imports relative to this prefix - ExeName string // desired name for temporary executable - FuzzInstrument bool // package should be instrumented for fuzzing - Cover CoverSetup // coverage mode and other setup info of -cover is being applied to this package - CoverVars map[string]*CoverVar // variables created by coverage analysis - OmitDebug bool // tell linker not to write debug information - GobinSubdir bool // install target would be subdir of GOBIN - BuildInfo *debug.BuildInfo // add this info to package main - TestmainGo *[]byte // content for _testmain.go - Embed map[string][]string // //go:embed comment mapping - OrigImportPath string // original import path before adding '_test' suffix - PGOProfile string // path to PGO profile - ForMain string // the main package if this package is built specifically for it + Imports []*Package // this package's direct imports + CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports + RawImports []string // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports + ForceLibrary bool // this package is a library (even if named "main") + CmdlineFiles bool // package built from files listed on command line + CmdlinePkg bool // package listed on command line + CmdlinePkgLiteral bool // package listed as literal on command line (not via wildcard) + Local bool // imported via local path (./ or ../) + LocalPrefix string // interpret ./ and ../ imports relative to this prefix + ExeName string // desired name for temporary executable + FuzzInstrument bool // package should be instrumented for fuzzing + Cover CoverSetup // coverage mode and other setup info of -cover is being applied to this package + OmitDebug bool // tell linker not to write debug information + GobinSubdir bool // install target would be subdir of GOBIN + BuildInfo *debug.BuildInfo // add this info to package main + TestmainGo *[]byte // content for _testmain.go + Embed map[string][]string // //go:embed comment mapping + OrigImportPath string // original import path before adding '_test' suffix + PGOProfile string // path to PGO profile + ForMain string // the main package if this package is built specifically for it Asmflags []string // -asmflags for this package Gcflags []string // -gcflags for this package @@ -372,12 +370,6 @@ func (p *Package) Resolve(imports []string) []string { return all } -// CoverVar holds the name of the generated coverage variables targeting the named file. -type CoverVar struct { - File string // local file name - Var string // name of count struct -} - // CoverSetup holds parameters related to coverage setup for a given package (covermode, etc). type CoverSetup struct { Mode string // coverage mode for this package @@ -2627,7 +2619,7 @@ func LinkerDeps(p *Package) ([]string, error) { deps = append(deps, "runtime/asan") } // Building for coverage forces an import of runtime/coverage. - if cfg.BuildCover && cfg.Experiment.CoverageRedesign { + if cfg.BuildCover { deps = append(deps, "runtime/coverage") } @@ -3568,14 +3560,6 @@ func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op strin if cfg.BuildCoverMode == "atomic" { EnsureImport(p, "sync/atomic") } - - // Generate covervars if using legacy coverage design. - if !cfg.Experiment.CoverageRedesign { - var coverFiles []string - coverFiles = append(coverFiles, p.GoFiles...) - coverFiles = append(coverFiles, p.CgoFiles...) - p.Internal.CoverVars = DeclareCoverVars(p, coverFiles...) - } } // Warn about -coverpkg arguments that are not actually used. @@ -3587,42 +3571,3 @@ func SelectCoverPackages(roots []*Package, match []func(*Package) bool, op strin return covered } - -// DeclareCoverVars attaches the required cover variables names -// to the files, to be used when annotating the files. This -// function only called when using legacy coverage test/build -// (e.g. GOEXPERIMENT=coverageredesign is off). -func DeclareCoverVars(p *Package, files ...string) map[string]*CoverVar { - coverVars := make(map[string]*CoverVar) - coverIndex := 0 - // We create the cover counters as new top-level variables in the package. - // We need to avoid collisions with user variables (GoCover_0 is unlikely but still) - // and more importantly with dot imports of other covered packages, - // so we append 12 hex digits from the SHA-256 of the import path. - // The point is only to avoid accidents, not to defeat users determined to - // break things. - sum := sha256.Sum256([]byte(p.ImportPath)) - h := fmt.Sprintf("%x", sum[:6]) - for _, file := range files { - if base.IsTestFile(file) { - continue - } - // For a package that is "local" (imported via ./ import or command line, outside GOPATH), - // we record the full path to the file name. - // Otherwise we record the import path, then a forward slash, then the file name. - // This makes profiles within GOPATH file system-independent. - // These names appear in the cmd/cover HTML interface. - var longFile string - if p.Internal.Local { - longFile = filepath.Join(p.Dir, file) - } else { - longFile = pathpkg.Join(p.ImportPath, file) - } - coverVars[file] = &CoverVar{ - File: longFile, - Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h), - } - coverIndex++ - } - return coverVars -} diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go index ddd14a0304..f895e3a246 100644 --- a/src/cmd/go/internal/load/test.go +++ b/src/cmd/go/internal/load/test.go @@ -23,7 +23,6 @@ import ( "unicode" "unicode/utf8" - "cmd/go/internal/cfg" "cmd/go/internal/fsys" "cmd/go/internal/str" "cmd/go/internal/trace" @@ -42,7 +41,6 @@ type TestCover struct { Local bool Pkgs []*Package Paths []string - Vars []coverInfo } // TestPackagesFor is like TestPackagesAndErrors but it returns @@ -309,7 +307,7 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p // Also the linker introduces implicit dependencies reported by LinkerDeps. stk.Push(ImportInfo{Pkg: "testmain"}) deps := TestMainDeps // cap==len, so safe for append - if cover != nil && cfg.Experiment.CoverageRedesign { + if cover != nil { deps = append(deps, "internal/coverage/cfile") } ldDeps, err := LinkerDeps(p) @@ -334,22 +332,6 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p stk.Pop() parallelizablePart := func() { - if cover != nil && cover.Pkgs != nil && !cfg.Experiment.CoverageRedesign { - // Add imports, but avoid duplicates. - seen := map[*Package]bool{p: true, ptest: true} - for _, p1 := range pmain.Internal.Imports { - seen[p1] = true - } - for _, p1 := range cover.Pkgs { - if seen[p1] { - // Don't add duplicate imports. - continue - } - seen[p1] = true - pmain.Internal.Imports = append(pmain.Internal.Imports, p1) - } - } - allTestImports := make([]*Package, 0, len(pmain.Internal.Imports)+len(imports)+len(ximports)) allTestImports = append(allTestImports, pmain.Internal.Imports...) allTestImports = append(allTestImports, imports...) @@ -397,35 +379,19 @@ func TestPackagesAndErrors(ctx context.Context, done func(), opts PackageOpts, p } if cover != nil { - if cfg.Experiment.CoverageRedesign { - // Here ptest needs to inherit the proper coverage mode (since - // it contains p's Go files), whereas pmain contains only - // test harness code (don't want to instrument it, and - // we don't want coverage hooks in the pkg init). - ptest.Internal.Cover.Mode = p.Internal.Cover.Mode - pmain.Internal.Cover.Mode = "testmain" - } + // Here ptest needs to inherit the proper coverage mode (since + // it contains p's Go files), whereas pmain contains only + // test harness code (don't want to instrument it, and + // we don't want coverage hooks in the pkg init). + ptest.Internal.Cover.Mode = p.Internal.Cover.Mode + pmain.Internal.Cover.Mode = "testmain" + // Should we apply coverage analysis locally, only for this // package and only for this test? Yes, if -cover is on but // -coverpkg has not specified a list of packages for global // coverage. if cover.Local { ptest.Internal.Cover.Mode = cover.Mode - - if !cfg.Experiment.CoverageRedesign { - var coverFiles []string - coverFiles = append(coverFiles, ptest.GoFiles...) - coverFiles = append(coverFiles, ptest.CgoFiles...) - ptest.Internal.CoverVars = DeclareCoverVars(ptest, coverFiles...) - } - } - - if !cfg.Experiment.CoverageRedesign { - for _, cp := range pmain.Internal.Imports { - if len(cp.Internal.CoverVars) > 0 { - t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars}) - } - } } } @@ -625,11 +591,6 @@ func isTest(name, prefix string) bool { return !unicode.IsLower(rune) } -type coverInfo struct { - Package *Package - Vars map[string]*CoverVar -} - // loadTestFuncs returns the testFuncs describing the tests that will be run. // The returned testFuncs is always non-nil, even if an error occurred while // processing test files. @@ -655,9 +616,6 @@ func loadTestFuncs(ptest *Package) (*testFuncs, error) { func formatTestmain(t *testFuncs) ([]byte, error) { var buf bytes.Buffer tmpl := testmainTmpl - if cfg.Experiment.CoverageRedesign { - tmpl = testmainTmplNewCoverage - } if err := tmpl.Execute(&buf, t); err != nil { return nil, err } @@ -825,119 +783,6 @@ var testmainTmpl = lazytemplate.New("main", ` package main -import ( - "os" -{{if .TestMain}} - "reflect" -{{end}} - "testing" - "testing/internal/testdeps" - -{{if .ImportTest}} - {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} -{{end}} -{{if .ImportXtest}} - {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} -{{end}} -{{if .Cover}} -{{range $i, $p := .Cover.Vars}} - _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} -{{end}} -{{end}} -) - -var tests = []testing.InternalTest{ -{{range .Tests}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var benchmarks = []testing.InternalBenchmark{ -{{range .Benchmarks}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var fuzzTargets = []testing.InternalFuzzTarget{ -{{range .FuzzTargets}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var examples = []testing.InternalExample{ -{{range .Examples}} - {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, -{{end}} -} - -func init() { - testdeps.ImportPath = {{.ImportPath | printf "%q"}} -} - -{{if .Cover}} - -// Only updated by init functions, so no need for atomicity. -var ( - coverCounters = make(map[string][]uint32) - coverBlocks = make(map[string][]testing.CoverBlock) -) - -func init() { - {{range $i, $p := .Cover.Vars}} - {{range $file, $cover := $p.Vars}} - coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:]) - {{end}} - {{end}} -} - -func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) { - if 3*len(counter) != len(pos) || len(counter) != len(numStmts) { - panic("coverage: mismatched sizes") - } - if coverCounters[fileName] != nil { - // Already registered. - return - } - coverCounters[fileName] = counter - block := make([]testing.CoverBlock, len(counter)) - for i := range counter { - block[i] = testing.CoverBlock{ - Line0: pos[3*i+0], - Col0: uint16(pos[3*i+2]), - Line1: pos[3*i+1], - Col1: uint16(pos[3*i+2]>>16), - Stmts: numStmts[i], - } - } - coverBlocks[fileName] = block -} -{{end}} - -func main() { -{{if .Cover}} - testing.RegisterCover(testing.Cover{ - Mode: {{printf "%q" .Cover.Mode}}, - Counters: coverCounters, - Blocks: coverBlocks, - CoveredPackages: {{printf "%q" .Covered}}, - }) -{{end}} - m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples) -{{with .TestMain}} - {{.Package}}.{{.Name}}(m) - os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int())) -{{else}} - os.Exit(m.Run()) -{{end}} -} - -`) - -var testmainTmplNewCoverage = lazytemplate.New("main", ` -// Code generated by 'go test'. DO NOT EDIT. - -package main - import ( "os" {{if .TestMain}} diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 5067cb2835..b81b1a007b 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -66,9 +66,7 @@ func init() { CmdRun.Run = runRun // break init loop work.AddBuildFlags(CmdRun, work.DefaultBuildFlags) - if cfg.Experiment != nil && cfg.Experiment.CoverageRedesign { - work.AddCoverFlags(CmdRun, nil) - } + work.AddCoverFlags(CmdRun, nil) CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "") } @@ -141,7 +139,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { cmdArgs := args[i:] load.CheckPackageErrors([]*load.Package{p}) - if cfg.Experiment.CoverageRedesign && cfg.BuildCover { + if cfg.BuildCover { load.PrepareForCoverageBuild([]*load.Package{p}) } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 90f2d88d6b..e3cd50d59c 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -867,7 +867,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // patterns. plist := load.TestPackageList(ctx, pkgOpts, pkgs) testCoverPkgs = load.SelectCoverPackages(plist, match, "test") - if cfg.Experiment.CoverageRedesign && len(testCoverPkgs) > 0 { + if len(testCoverPkgs) > 0 { // create a new singleton action that will collect up the // meta-data files from all of the packages mentioned in // "-coverpkg" and write them to a summary file. This new @@ -984,9 +984,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // later package. Note that if -coverpkg is in effect // p.Internal.Cover.GenMeta will wind up being set for // all matching packages. - if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 && - cfg.BuildCoverPkg == nil && - cfg.Experiment.CoverageRedesign { + if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 && cfg.BuildCoverPkg == nil { p.Internal.Cover.GenMeta = true } } @@ -1092,7 +1090,7 @@ var windowsBadWords = []string{ func builderTest(b *work.Builder, ctx context.Context, pkgOpts load.PackageOpts, p *load.Package, imported bool, writeCoverMetaAct *work.Action) (buildAction, runAction, printAction *work.Action, perr *load.Package, err error) { if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { - if cfg.BuildCover && cfg.Experiment.CoverageRedesign { + if cfg.BuildCover { if p.Internal.Cover.GenMeta { p.Internal.Cover.Mode = cfg.BuildCoverMode } @@ -1487,7 +1485,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) if p := a.Package; len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { reportNoTestFiles := true - if cfg.BuildCover && cfg.Experiment.CoverageRedesign && p.Internal.Cover.GenMeta { + if cfg.BuildCover && p.Internal.Cover.GenMeta { if err := sh.Mkdir(a.Objdir); err != nil { return err } diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 3508d51fbb..873feb8a26 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -247,10 +247,8 @@ func init() { AddBuildFlags(CmdBuild, DefaultBuildFlags) AddBuildFlags(CmdInstall, DefaultBuildFlags) - if cfg.Experiment != nil && cfg.Experiment.CoverageRedesign { - AddCoverFlags(CmdBuild, nil) - AddCoverFlags(CmdInstall, nil) - } + AddCoverFlags(CmdBuild, nil) + AddCoverFlags(CmdInstall, nil) } // Note that flags consulted by other parts of the code @@ -361,26 +359,13 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) { cmd.Flag.StringVar(&cfg.DebugTrace, "debug-trace", "", "") } -// AddCoverFlags adds coverage-related flags to "cmd". If the -// CoverageRedesign experiment is enabled, we add -cover{mode,pkg} to -// the build command and only -coverprofile to the test command. If -// the CoverageRedesign experiment is disabled, -cover* flags are -// added only to the test command. +// AddCoverFlags adds coverage-related flags to "cmd". +// We add -cover{mode,pkg} to the build command and only +// -coverprofile to the test command. func AddCoverFlags(cmd *base.Command, coverProfileFlag *string) { - addCover := false - if cfg.Experiment != nil && cfg.Experiment.CoverageRedesign { - // New coverage enabled: both build and test commands get - // coverage flags. - addCover = true - } else { - // New coverage disabled: only test command gets cover flags. - addCover = coverProfileFlag != nil - } - if addCover { - cmd.Flag.BoolVar(&cfg.BuildCover, "cover", false, "") - cmd.Flag.Var(coverFlag{(*coverModeFlag)(&cfg.BuildCoverMode)}, "covermode", "") - cmd.Flag.Var(coverFlag{commaListFlag{&cfg.BuildCoverPkg}}, "coverpkg", "") - } + cmd.Flag.BoolVar(&cfg.BuildCover, "cover", false, "") + cmd.Flag.Var(coverFlag{(*coverModeFlag)(&cfg.BuildCoverMode)}, "covermode", "") + cmd.Flag.Var(coverFlag{commaListFlag{&cfg.BuildCoverPkg}}, "coverpkg", "") if coverProfileFlag != nil { cmd.Flag.Var(coverFlag{V: stringFlag{coverProfileFlag}}, "coverprofile", "") } @@ -515,7 +500,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { cfg.BuildO = "" } - if cfg.Experiment.CoverageRedesign && cfg.BuildCover { + if cfg.BuildCover { load.PrepareForCoverageBuild(pkgs) } @@ -732,7 +717,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { } load.CheckPackageErrors(pkgs) - if cfg.Experiment.CoverageRedesign && cfg.BuildCover { + if cfg.BuildCover { load.PrepareForCoverageBuild(pkgs) } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 7b073165d5..c79d6f73ef 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -647,31 +647,18 @@ OverlayLoop: var sourceFile string var coverFile string - var key string if base, found := strings.CutSuffix(file, ".cgo1.go"); found { // cgo files have absolute paths base = filepath.Base(base) sourceFile = file coverFile = objdir + base + ".cgo1.go" - key = base + ".go" } else { sourceFile = filepath.Join(p.Dir, file) coverFile = objdir + file - key = file } coverFile = strings.TrimSuffix(coverFile, ".go") + ".cover.go" - if cfg.Experiment.CoverageRedesign { - infiles = append(infiles, sourceFile) - outfiles = append(outfiles, coverFile) - } else { - cover := p.Internal.CoverVars[key] - if cover == nil { - continue // Not covering this file. - } - if err := b.cover(a, coverFile, sourceFile, cover.Var); err != nil { - return err - } - } + infiles = append(infiles, sourceFile) + outfiles = append(outfiles, coverFile) if i < len(gofiles) { gofiles[i] = coverFile } else { @@ -679,36 +666,27 @@ OverlayLoop: } } - if cfg.Experiment.CoverageRedesign { - if len(infiles) != 0 { - // Coverage instrumentation creates new top level - // variables in the target package for things like - // meta-data containers, counter vars, etc. To avoid - // collisions with user variables, suffix the var name - // with 12 hex digits from the SHA-256 hash of the - // import path. Choice of 12 digits is historical/arbitrary, - // we just need enough of the hash to avoid accidents, - // as opposed to precluding determined attempts by - // users to break things. - sum := sha256.Sum256([]byte(a.Package.ImportPath)) - coverVar := fmt.Sprintf("goCover_%x_", sum[:6]) - mode := a.Package.Internal.Cover.Mode - if mode == "" { - panic("covermode should be set at this point") - } - if newoutfiles, err := b.cover2(a, infiles, outfiles, coverVar, mode); err != nil { - return err - } else { - outfiles = newoutfiles - gofiles = append([]string{newoutfiles[0]}, gofiles...) - } + if len(infiles) != 0 { + // Coverage instrumentation creates new top level + // variables in the target package for things like + // meta-data containers, counter vars, etc. To avoid + // collisions with user variables, suffix the var name + // with 12 hex digits from the SHA-256 hash of the + // import path. Choice of 12 digits is historical/arbitrary, + // we just need enough of the hash to avoid accidents, + // as opposed to precluding determined attempts by + // users to break things. + sum := sha256.Sum256([]byte(a.Package.ImportPath)) + coverVar := fmt.Sprintf("goCover_%x_", sum[:6]) + mode := a.Package.Internal.Cover.Mode + if mode == "" { + panic("covermode should be set at this point") + } + if newoutfiles, err := b.cover(a, infiles, outfiles, coverVar, mode); err != nil { + return err } else { - // If there are no input files passed to cmd/cover, - // then we don't want to pass -covercfg when building - // the package with the compiler, so set covermode to - // the empty string so as to signal that we need to do - // that. - p.Internal.Cover.Mode = "" + outfiles = newoutfiles + gofiles = append([]string{newoutfiles[0]}, gofiles...) } if ba, ok := a.Actor.(*buildActor); ok && ba.covMetaFileName != "" { b.cacheObjdirFile(a, cache.Default(), ba.covMetaFileName) @@ -1909,26 +1887,13 @@ func (b *Builder) installHeader(ctx context.Context, a *Action) error { // cover runs, in effect, // -// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go -func (b *Builder) cover(a *Action, dst, src string, varName string) error { - return b.Shell(a).run(a.Objdir, "", nil, - cfg.BuildToolexec, - base.Tool("cover"), - "-mode", a.Package.Internal.Cover.Mode, - "-var", varName, - "-o", dst, - src) -} - -// cover2 runs, in effect, -// // go tool cover -pkgcfg= -mode=b.coverMode -var="varName" -o // // Return value is an updated output files list; in addition to the // regular outputs (instrumented source files) the cover tool also // writes a separate file (appearing first in the list of outputs) // that will contain coverage counters and meta-data. -func (b *Builder) cover2(a *Action, infiles, outfiles []string, varName string, mode string) ([]string, error) { +func (b *Builder) cover(a *Action, infiles, outfiles []string, varName string, mode string) ([]string, error) { pkgcfg := a.Objdir + "pkgcfg.txt" covoutputs := a.Objdir + "coveroutfiles.txt" odir := filepath.Dir(outfiles[0]) diff --git a/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt b/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt index e14a0784f2..ba382639e9 100644 --- a/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt +++ b/src/cmd/go/testdata/script/cover_build_cmdline_pkgs.txt @@ -5,7 +5,6 @@ # inside and outside the standard library. [short] skip -[!GOEXPERIMENT:coverageredesign] skip # Compile an object. go tool compile -p tiny tiny/tiny.go tiny/tiny2.go diff --git a/src/cmd/go/testdata/script/cover_build_pkg_select.txt b/src/cmd/go/testdata/script/cover_build_pkg_select.txt index 447ca7788c..3a59e72e88 100644 --- a/src/cmd/go/testdata/script/cover_build_pkg_select.txt +++ b/src/cmd/go/testdata/script/cover_build_pkg_select.txt @@ -3,9 +3,6 @@ [short] skip -# Skip if new coverage is not enabled. -[!GOEXPERIMENT:coverageredesign] skip - #------------------------------------------- # Build for coverage. diff --git a/src/cmd/go/testdata/script/cover_build_simple.txt b/src/cmd/go/testdata/script/cover_build_simple.txt index b61e631abd..ee451a68ab 100644 --- a/src/cmd/go/testdata/script/cover_build_simple.txt +++ b/src/cmd/go/testdata/script/cover_build_simple.txt @@ -2,9 +2,6 @@ [short] skip -# Hard-wire new coverage for this test. -env GOEXPERIMENT=coverageredesign - # Build for coverage. go build -gcflags=-m -o example.exe -cover example/main & [race] go build -o examplewithrace.exe -race -cover example/main & diff --git a/src/cmd/go/testdata/script/cover_coverpkg_partial.txt b/src/cmd/go/testdata/script/cover_coverpkg_partial.txt index ef7a4dd2aa..efdfe2f27d 100644 --- a/src/cmd/go/testdata/script/cover_coverpkg_partial.txt +++ b/src/cmd/go/testdata/script/cover_coverpkg_partial.txt @@ -16,7 +16,6 @@ # [short] skip -[!GOEXPERIMENT:coverageredesign] skip # Test all packages with -coverpkg=./... go test -coverprofile=cov.p -coverpkg=./... ./... diff --git a/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt b/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt index 7a89102547..bb5bcfa823 100644 --- a/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt +++ b/src/cmd/go/testdata/script/cover_coverpkg_with_init.txt @@ -5,7 +5,6 @@ # do not, some have tests and some do not. [short] skip -[!GOEXPERIMENT:coverageredesign] skip # Verify correct statements percentages. We have a total of 10 # statements in the packages matched by "./..."; package "a" (for diff --git a/src/cmd/go/testdata/script/cover_list.txt b/src/cmd/go/testdata/script/cover_list.txt index 1b1f326662..7ecc5c05eb 100644 --- a/src/cmd/go/testdata/script/cover_list.txt +++ b/src/cmd/go/testdata/script/cover_list.txt @@ -3,7 +3,6 @@ # build arguments (such as -cover, -covermode). See issue #57785. [short] skip -[!GOEXPERIMENT:coverageredesign] skip env GOBIN=$WORK/bin diff --git a/src/cmd/go/testdata/script/cover_main_import_path.txt b/src/cmd/go/testdata/script/cover_main_import_path.txt index e8696e27e2..3a2f3c3ee2 100644 --- a/src/cmd/go/testdata/script/cover_main_import_path.txt +++ b/src/cmd/go/testdata/script/cover_main_import_path.txt @@ -4,7 +4,6 @@ # the "main" package is handled. See issue 57169 for details. [short] skip -[!GOEXPERIMENT:coverageredesign] skip # Build this program with -cover and run to collect a profile. diff --git a/src/cmd/go/testdata/script/cover_statements.txt b/src/cmd/go/testdata/script/cover_statements.txt index 030177cb8b..f0391ede22 100644 --- a/src/cmd/go/testdata/script/cover_statements.txt +++ b/src/cmd/go/testdata/script/cover_statements.txt @@ -10,35 +10,32 @@ env GOCACHE=$WORK/cache # Initial run with simple coverage. go test -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4 -[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]' -[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements' +stdout 'pkg1 coverage: 0.0% of statements' stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]' stdout 'pkg3 \S+ coverage: 100.0% of statements' stdout 'pkg4 \S+ coverage: \[no statements\]' # Second run to make sure that caching works properly. go test -x -cover ./pkg1 ./pkg2 ./pkg3 ./pkg4 -[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]' -[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements' +stdout 'pkg1 coverage: 0.0% of statements' stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]' stdout 'pkg3 \S+ coverage: 100.0% of statements' stdout 'pkg4 \S+ coverage: \[no statements\]' -[GOEXPERIMENT:coverageredesign] ! stderr 'link(\.exe"?)? -' +! stderr 'link(\.exe"?)? -' ! stderr 'compile(\.exe"?)? -' ! stderr 'cover(\.exe"?)? -' -[GOEXPERIMENT:coverageredesign] stderr 'covdata(\.exe"?)? percent' +stderr 'covdata(\.exe"?)? percent' # Now add in -coverprofile. go test -cover -coverprofile=cov.dat ./pkg1 ./pkg2 ./pkg3 ./pkg4 -[!GOEXPERIMENT:coverageredesign] stdout 'pkg1 \[no test files\]' -[GOEXPERIMENT:coverageredesign] stdout 'pkg1 coverage: 0.0% of statements' +stdout 'pkg1 coverage: 0.0% of statements' stdout 'pkg2 \S+ coverage: 0.0% of statements \[no tests to run\]' stdout 'pkg3 \S+ coverage: 100.0% of statements' stdout 'pkg4 \S+ coverage: \[no statements\]' # Validate go tool cover -func=cov.dat -[GOEXPERIMENT:coverageredesign] stdout 'pkg1/a.go:5:\s+F\s+0.0%' +stdout 'pkg1/a.go:5:\s+F\s+0.0%' -- go.mod -- module m diff --git a/src/cmd/go/testdata/script/cover_sync_atomic_import.txt b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt index a098979797..7beea137e2 100644 --- a/src/cmd/go/testdata/script/cover_sync_atomic_import.txt +++ b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt @@ -1,6 +1,5 @@ [short] skip [compiler:gccgo] skip # gccgo has no cover tool -[!GOEXPERIMENT:coverageredesign] skip go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep diff --git a/src/cmd/go/testdata/script/cover_test_pkgselect.txt b/src/cmd/go/testdata/script/cover_test_pkgselect.txt index 97a1d2cbbb..8e47d142d4 100644 --- a/src/cmd/go/testdata/script/cover_test_pkgselect.txt +++ b/src/cmd/go/testdata/script/cover_test_pkgselect.txt @@ -1,9 +1,6 @@ [short] skip -# Hard-wire new coverage for this test. -env GOEXPERIMENT=coverageredesign - # Baseline run. go test -cover example/foo stdout 'coverage: 50.0% of statements$' diff --git a/src/cmd/go/testdata/script/cover_var_init_order.txt b/src/cmd/go/testdata/script/cover_var_init_order.txt index 37e07b71f6..a9ee63c78c 100644 --- a/src/cmd/go/testdata/script/cover_var_init_order.txt +++ b/src/cmd/go/testdata/script/cover_var_init_order.txt @@ -4,9 +4,6 @@ [short] skip -# Skip if new coverage is turned off. -[!GOEXPERIMENT:coverageredesign] skip - go test -cover example -- go.mod -- diff --git a/src/cmd/go/testdata/script/testing_coverage.txt b/src/cmd/go/testdata/script/testing_coverage.txt index 6cf6adbbd7..bf4dc83107 100644 --- a/src/cmd/go/testdata/script/testing_coverage.txt +++ b/src/cmd/go/testdata/script/testing_coverage.txt @@ -2,7 +2,6 @@ # Rudimentary test of testing.Coverage(). [short] skip -[!GOEXPERIMENT:coverageredesign] skip # Simple test. go test -v -cover -count=1 diff --git a/src/cmd/internal/cov/read_test.go b/src/cmd/internal/cov/read_test.go index fa2151a09e..cef03fa323 100644 --- a/src/cmd/internal/cov/read_test.go +++ b/src/cmd/internal/cov/read_test.go @@ -11,7 +11,6 @@ import ( "internal/coverage/decodecounter" "internal/coverage/decodemeta" "internal/coverage/pods" - "internal/goexperiment" "internal/testenv" "os" "path/filepath" @@ -45,9 +44,6 @@ func (v *visitor) Finish() func TestIssue58411(t *testing.T) { testenv.MustHaveGoBuild(t) - if !goexperiment.CoverageRedesign { - t.Skipf("skipping since this test requires 'go build -cover'") - } // Build a tiny test program with -cover. Smallness is important; // it is one of the factors that triggers issue 58411. diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go index 332c9afa57..9c9ec2c711 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -74,13 +74,12 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { } baseline := goexperiment.Flags{ - RegabiWrappers: regabiSupported, - RegabiArgs: regabiSupported, - CoverageRedesign: true, - AliasTypeParams: true, - SwissMap: true, - SpinbitMutex: haveXchg8, - SyncHashTrieMap: true, + RegabiWrappers: regabiSupported, + RegabiArgs: regabiSupported, + AliasTypeParams: true, + SwissMap: true, + SpinbitMutex: haveXchg8, + SyncHashTrieMap: true, } // Start with the statically enabled set of experiments. diff --git a/src/internal/coverage/cfile/emitdata_test.go b/src/internal/coverage/cfile/emitdata_test.go index c522048173..d127c6b2a9 100644 --- a/src/internal/coverage/cfile/emitdata_test.go +++ b/src/internal/coverage/cfile/emitdata_test.go @@ -7,7 +7,6 @@ package cfile import ( "fmt" "internal/coverage" - "internal/goexperiment" "internal/platform" "internal/testenv" "os" @@ -25,9 +24,6 @@ func TestCoverageApis(t *testing.T) { if testing.Short() { t.Skipf("skipping test: too long for short mode") } - if !goexperiment.CoverageRedesign { - t.Skipf("skipping new coverage tests (experiment not enabled)") - } testenv.MustHaveGoBuild(t) dir := t.TempDir() if fixedTestDir { @@ -465,9 +461,6 @@ func TestIssue56006EmitDataRaceCoverRunningGoroutine(t *testing.T) { if testing.Short() { t.Skipf("skipping test: too long for short mode") } - if !goexperiment.CoverageRedesign { - t.Skipf("skipping new coverage tests (experiment not enabled)") - } // This test requires "go test -race -cover", meaning that we need // go build, go run, and "-race" support. diff --git a/src/internal/coverage/cfile/ts_test.go b/src/internal/coverage/cfile/ts_test.go index d3441821a4..d106d3b132 100644 --- a/src/internal/coverage/cfile/ts_test.go +++ b/src/internal/coverage/cfile/ts_test.go @@ -8,7 +8,6 @@ import ( "encoding/json" "flag" "internal/coverage" - "internal/goexperiment" "internal/testenv" "os" "os/exec" @@ -32,9 +31,6 @@ func testGoCoverDir(t *testing.T) string { // relying on other test paths will provide a better signal when // running "go test -cover" for this package). func TestTestSupport(t *testing.T) { - if !goexperiment.CoverageRedesign { - return - } if testing.CoverMode() == "" { return } @@ -128,9 +124,6 @@ func genAuxMeta(t *testing.T, dstdir string) (string, string) { } func TestAuxMetaDataFiles(t *testing.T) { - if !goexperiment.CoverageRedesign { - return - } if testing.CoverMode() == "" { return } diff --git a/src/internal/goexperiment/exp_coverageredesign_off.go b/src/internal/goexperiment/exp_coverageredesign_off.go deleted file mode 100644 index 2c33177322..0000000000 --- a/src/internal/goexperiment/exp_coverageredesign_off.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build !goexperiment.coverageredesign - -package goexperiment - -const CoverageRedesign = false -const CoverageRedesignInt = 0 diff --git a/src/internal/goexperiment/exp_coverageredesign_on.go b/src/internal/goexperiment/exp_coverageredesign_on.go deleted file mode 100644 index 3fc6c2f70a..0000000000 --- a/src/internal/goexperiment/exp_coverageredesign_on.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by mkconsts.go. DO NOT EDIT. - -//go:build goexperiment.coverageredesign - -package goexperiment - -const CoverageRedesign = true -const CoverageRedesignInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 948ed5c802..dff5255e00 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -83,10 +83,6 @@ type Flags struct { // by default. HeapMinimum512KiB bool - // CoverageRedesign enables the new compiler-based code coverage - // tooling. - CoverageRedesign bool - // Arenas causes the "arena" standard library package to be visible // to the outside world. Arenas bool diff --git a/src/testing/cover.go b/src/testing/cover.go index 6ad43ab9ff..74c97d471e 100644 --- a/src/testing/cover.go +++ b/src/testing/cover.go @@ -6,13 +6,6 @@ package testing -import ( - "fmt" - "internal/goexperiment" - "os" - "sync/atomic" -) - // CoverBlock records the coverage data for a single basic block. // The fields are 1-indexed, as in an editor: The opening line of // the file is number 1, for example. Columns are measured @@ -27,8 +20,6 @@ type CoverBlock struct { Stmts uint16 // Number of statements included in this block. } -var cover Cover - // Cover records information about test coverage checking. // NOTE: This struct is internal to the testing infrastructure and may change. // It is not covered (yet) by the Go 1 compatibility guidelines. @@ -39,86 +30,8 @@ type Cover struct { CoveredPackages string } -// Coverage reports the current code coverage as a fraction in the range [0, 1]. -// If coverage is not enabled, Coverage returns 0. -// -// When running a large set of sequential test cases, checking Coverage after each one -// can be useful for identifying which test cases exercise new code paths. -// It is not a replacement for the reports generated by 'go test -cover' and -// 'go tool cover'. -func Coverage() float64 { - if goexperiment.CoverageRedesign { - return coverage2() - } - var n, d int64 - for _, counters := range cover.Counters { - for i := range counters { - if atomic.LoadUint32(&counters[i]) > 0 { - n++ - } - d++ - } - } - if d == 0 { - return 0 - } - return float64(n) / float64(d) -} - // RegisterCover records the coverage data accumulators for the tests. // NOTE: This function is internal to the testing infrastructure and may change. // It is not covered (yet) by the Go 1 compatibility guidelines. func RegisterCover(c Cover) { - cover = c -} - -// mustBeNil checks the error and, if present, reports it and exits. -func mustBeNil(err error) { - if err != nil { - fmt.Fprintf(os.Stderr, "testing: %s\n", err) - os.Exit(2) - } -} - -// coverReport reports the coverage percentage and writes a coverage profile if requested. -func coverReport() { - if goexperiment.CoverageRedesign { - coverReport2() - return - } - var f *os.File - var err error - if *coverProfile != "" { - f, err = os.Create(toOutputDir(*coverProfile)) - mustBeNil(err) - fmt.Fprintf(f, "mode: %s\n", cover.Mode) - defer func() { mustBeNil(f.Close()) }() - } - - var active, total int64 - var count uint32 - for name, counts := range cover.Counters { - blocks := cover.Blocks[name] - for i := range counts { - stmts := int64(blocks[i].Stmts) - total += stmts - count = atomic.LoadUint32(&counts[i]) // For -mode=atomic. - if count > 0 { - active += stmts - } - if f != nil { - _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name, - blocks[i].Line0, blocks[i].Col0, - blocks[i].Line1, blocks[i].Col1, - stmts, - count) - mustBeNil(err) - } - } - } - if total == 0 { - fmt.Println("coverage: [no statements]") - return - } - fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages) } diff --git a/src/testing/newcover.go b/src/testing/newcover.go index ad2f622640..5a8d728831 100644 --- a/src/testing/newcover.go +++ b/src/testing/newcover.go @@ -8,49 +8,52 @@ package testing import ( "fmt" - "internal/goexperiment" "os" _ "unsafe" // for linkname ) -// cover2 variable stores the current coverage mode and a +// cover variable stores the current coverage mode and a // tear-down function to be called at the end of the testing run. -var cover2 struct { +var cover struct { mode string tearDown func(coverprofile string, gocoverdir string) (string, error) snapshotcov func() float64 } -// registerCover2 is invoked during "go test -cover" runs. +// registerCover is invoked during "go test -cover" runs. // It is used to record a 'tear down' function // (to be called when the test is complete) and the coverage mode. -func registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error), snapcov func() float64) { +func registerCover(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error), snapcov func() float64) { if mode == "" { return } - cover2.mode = mode - cover2.tearDown = tearDown - cover2.snapshotcov = snapcov + cover.mode = mode + cover.tearDown = tearDown + cover.snapshotcov = snapcov } -// coverReport2 invokes a callback in _testmain.go that will +// coverReport reports the coverage percentage and +// writes a coverage profile if requested. +// This invokes a callback in _testmain.go that will // emit coverage data at the point where test execution is complete, // for "go test -cover" runs. -func coverReport2() { - if !goexperiment.CoverageRedesign { - panic("unexpected") - } - if errmsg, err := cover2.tearDown(*coverProfile, *gocoverdir); err != nil { +func coverReport() { + if errmsg, err := cover.tearDown(*coverProfile, *gocoverdir); err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", errmsg, err) os.Exit(2) } } -// coverage2 returns a rough "coverage percentage so far" -// number to support the testing.Coverage() function. -func coverage2() float64 { - if cover2.mode == "" { +// Coverage reports the current code coverage as a fraction in the range [0, 1]. +// If coverage is not enabled, Coverage returns 0. +// +// When running a large set of sequential test cases, checking Coverage after each one +// can be useful for identifying which test cases exercise new code paths. +// It is not a replacement for the reports generated by 'go test -cover' and +// 'go tool cover'. +func Coverage() float64 { + if cover.mode == "" { return 0.0 } - return cover2.snapshotcov() + return cover.snapshotcov() } diff --git a/src/testing/testing.go b/src/testing/testing.go index 3833bfc84b..2bfa4b6db0 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -403,7 +403,6 @@ import ( "errors" "flag" "fmt" - "internal/goexperiment" "internal/race" "io" "math/rand" @@ -700,10 +699,7 @@ func Testing() bool { // values are "set", "count", or "atomic". The return value will be // empty if test coverage is not enabled. func CoverMode() string { - if goexperiment.CoverageRedesign { - return cover2.mode - } - return cover.Mode + return cover.mode } // Verbose reports whether the -test.v flag is set. @@ -2021,7 +2017,7 @@ type testDeps interface { // It is not meant to be called directly and is not subject to the Go 1 compatibility document. // It may change signature from release to release. func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M { - registerCover2(deps.InitRuntimeCoverage()) + registerCover(deps.InitRuntimeCoverage()) Init() return &M{ deps: deps,