Skip to content

Commit 85bdd05

Browse files
committed
cmd/go: rebuild as needed for tests of packages that add methods
If A's external test package imports B, which imports A, and A's (internal) test code also adds something to A that invalidates anything in the export data from a build of A without its test code, then strictly speaking we need to rebuild B against the test-augmented version of A before using it to build A's external test package. We've been skating by without doing this for a very long time, but I knew we'd need to handle it better eventually, I planned for it in the new build cache simplifications, and the code was ready. Now that we have a real-world test case that needs it, turn on the "proper rebuilding" code. It doesn't really matter how much things slow down, since a real-world test cases that caused an internal compiler error before is now handled correctly, but it appears to be small: I wasn't able to measure an effect on "go test -a -c fmt". And of course most builds won't use -a and will be cached well. Fixes #6204. Fixes #23701. Change-Id: I2cd60cf400d1928428979ab05831f48ff7cee6ca Reviewed-on: https://go-review.googlesource.com/92215 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent fd7331a commit 85bdd05

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

src/cmd/go/go_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,6 +5439,44 @@ func TestTestVet(t *testing.T) {
54395439
tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
54405440
}
54415441

5442+
func TestTestRebuild(t *testing.T) {
5443+
tg := testgo(t)
5444+
defer tg.cleanup()
5445+
tg.parallel()
5446+
5447+
// golang.org/issue/23701.
5448+
// b_test imports b with augmented method from export_test.go.
5449+
// b_test also imports a, which imports b.
5450+
// Must not accidentally see un-augmented b propagate through a to b_test.
5451+
tg.tempFile("src/a/a.go", `package a
5452+
import "b"
5453+
type Type struct{}
5454+
func (*Type) M() b.T {return 0}
5455+
`)
5456+
tg.tempFile("src/b/b.go", `package b
5457+
type T int
5458+
type I interface {M() T}
5459+
`)
5460+
tg.tempFile("src/b/export_test.go", `package b
5461+
func (*T) Method() *T { return nil }
5462+
`)
5463+
tg.tempFile("src/b/b_test.go", `package b_test
5464+
import (
5465+
"testing"
5466+
"a"
5467+
. "b"
5468+
)
5469+
func TestBroken(t *testing.T) {
5470+
x := new(T)
5471+
x.Method()
5472+
_ = new(a.Type)
5473+
}
5474+
`)
5475+
5476+
tg.setenv("GOPATH", tg.path("."))
5477+
tg.run("test", "b")
5478+
}
5479+
54425480
func TestInstallDeps(t *testing.T) {
54435481
tooSlow(t)
54445482
tg := testgo(t)

src/cmd/go/internal/test/test.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
897897
t.ImportXtest = true
898898
}
899899

900-
if ptest != p && localCover {
900+
if ptest != p {
901901
// We have made modifications to the package p being tested
902902
// and are rebuilding p (as ptest).
903903
// Arrange to rebuild all packages q such that
@@ -906,13 +906,6 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
906906
// Strictly speaking, the rebuild is only necessary if the
907907
// modifications to p change its export metadata, but
908908
// determining that is a bit tricky, so we rebuild always.
909-
// TODO(rsc): Once we get export metadata changes
910-
// handled properly, look into the expense of dropping
911-
// "&& localCover" above.
912-
//
913-
// This will cause extra compilation, so for now we only do it
914-
// when testCover is set. The conditions are more general, though,
915-
// and we may find that we need to do it always in the future.
916909
recompileForTest(pmain, p, ptest, pxtest)
917910
}
918911

0 commit comments

Comments
 (0)