cmd/go: include test deps in buildinfo
Fixes #76926
diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go
index f9bdd5e1..d1ec05f 100644
--- a/src/cmd/go/internal/load/test.go
+++ b/src/cmd/go/internal/load/test.go
@@ -294,15 +294,6 @@
pb := p.Internal.Build
pmain.DefaultGODEBUG = defaultGODEBUG(loaderstate, pmain, pb.Directives, pb.TestDirectives, pb.XTestDirectives)
- if !opts.SuppressBuildInfo && (pmain.Internal.BuildInfo == nil || pmain.DefaultGODEBUG != p.DefaultGODEBUG) {
- // Either we didn't generate build info for the package under test (because it wasn't package main), or
- // the DefaultGODEBUG used to build the test main package is different from the DefaultGODEBUG
- // used to build the package under test. If we didn't set build info for the package under test
- // pmain won't have buildinfo set (since we copy it from the package under test). If the default GODEBUG
- // used for the package under test is different from that of the test main, the BuildInfo assigned above from the package
- // under test incorrect for the test main package. Either set or correct pmain's build info.
- pmain.setBuildInfo(ctx, loaderstate.Fetcher(), opts.AutoVCS)
- }
// The generated main also imports testing, regexp, and os.
// Also the linker introduces implicit dependencies reported by LinkerDeps.
@@ -379,6 +370,12 @@
ptest.Incomplete = true
}
+ if !opts.SuppressBuildInfo {
+ // Now that pmain.Internal.Imports includes the test dependencies,
+ // regenerate build info for the test binary.
+ pmain.setBuildInfo(ctx, loaderstate.Fetcher(), opts.AutoVCS)
+ }
+
if cover != nil {
// Here ptest needs to inherit the proper coverage mode (since
// it contains p's Go files), whereas pmain contains only
diff --git a/src/cmd/go/testdata/script/test_buildinfo.txt b/src/cmd/go/testdata/script/test_buildinfo.txt
index fbf097c..e8884e2 100644
--- a/src/cmd/go/testdata/script/test_buildinfo.txt
+++ b/src/cmd/go/testdata/script/test_buildinfo.txt
@@ -3,7 +3,10 @@
[short] skip 'invokes go test'
-go mod init foo
+go mod init example.com/foo
+go mod edit -require=example.com/d...@v0.0.0
+go mod edit -replace=example.com/dep=./dep
+
go test -v
stdout '(devel)'
@@ -13,12 +16,39 @@
import (
"runtime/debug"
"testing"
+
+ "example.com/dep"
)
func TestBuildInfo(t *testing.T) {
+ if dep.Version() == "" {
+ t.Fatal("empty dep version")
+ }
+
info, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("no debug info")
}
t.Log(info.Main.Version)
-}
\ No newline at end of file
+
+ found := false
+ for _, d := range info.Deps {
+ if d.Path == "example.com/dep" {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Fatalf("expected dep example.com/dep in build info, got %v", info.Deps)
+ }
+}
+
+-- dep/go.mod --
+module example.com/dep
+
+-- dep/dep.go --
+package dep
+
+func Version() string {
+ return "v0"
+}
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Congratulations on opening your first change. Thank you for your contribution!
Next steps:
A maintainer will review your change and provide feedback. See
https://go.dev/doc/contribute#review for more info and tips to get your
patch through code review.
Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.
During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11 or adds a tag like "wait-release", it means that this CL will be
reviewed as part of the next development cycle. See https://go.dev/s/release
for more details.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +2 |
if !opts.SuppressBuildInfo {
// Now that pmain.Internal.Imports includes the test dependencies,
// regenerate build info for the test binary.
pmain.setBuildInfo(ctx, loaderstate.Fetcher(), opts.AutoVCS)
}We should also say here that we can't reuse p's build info in general because the the test variants of the packages can add packages from modules that don't already have transitive imports from `p`.
# Ensure buildinfo is populated on test binaries even if they
# are not tests for package main. See issue #33976.
[short] skip 'invokes go test'
go mod init example.com/foo
go mod edit -require=example.com/d...@v0.0.0
go mod edit -replace=example.com/dep=./dep
go test -v
stdout '(devel)'
-- foo_test.go --
package foo_test
import (
"runtime/debug"
"testing"
"example.com/dep"
)
func TestBuildInfo(t *testing.T) {
if dep.Version() == "" {
t.Fatal("empty dep version")
}
info, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("no debug info")
}
t.Log(info.Main.Version)
found := false
for _, d := range info.Deps {
if d.Path == "example.com/dep" {
found = true
break
}
}
if !found {
t.Fatalf("expected dep example.com/dep in build info, got %v", info.Deps)
}
}
-- dep/go.mod --
module example.com/dep
-- dep/dep.go --
package dep
func Version() string {
return "v0"
}
It's a little easier to parse test failures when they are caused by assertions in the script test. Also we can use the local fake module proxy we start for the go command tests. How's this?
```suggestion
# Ensure buildinfo is populated on test binaries even if they
# are not tests for package main. See issue #33976.
[short] skip 'invokes go test'
go mod init foo
go get example.com/ver...@v1.0.0
go test -v
stdout '(devel)'
stdout 'example.com/version v1.0.0'
-- foo_test.go --
package foo
import (
"runtime/debug"
"testing"
_ "example.com/version"
)
func TestBuildInfo(t *testing.T) {
info, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("no debug info")
}
t.Log(info.Main.Version)
for _, d := range info.Deps {
t.Log(d.Path, d.Version)
}
}
```| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |