From 95e4181b0c7c7f9e6db672067847b1152eafa58c Mon Sep 17 00:00:00 2001
From: Russ Cox <rsc@golang.org>
Date: Tue, 13 May 2014 01:38:10 -0400
Subject: [PATCH] cmd/go: fix go test again

Fixes subrepo builds.

LGTM=iant, mikioh.mikioh
R=golang-codereviews, iant, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/96310043
---
 src/cmd/go/test.bash                        | 10 ++++
 src/cmd/go/test.go                          | 62 ++++++++++++---------
 src/cmd/go/testdata/src/xtestonly/f.go      |  3 +
 src/cmd/go/testdata/src/xtestonly/f_test.go | 12 ++++
 4 files changed, 60 insertions(+), 27 deletions(-)
 create mode 100644 src/cmd/go/testdata/src/xtestonly/f.go
 create mode 100644 src/cmd/go/testdata/src/xtestonly/f_test.go

diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index 92b6cf5962..9a4fc1fa66 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -789,6 +789,16 @@ if ! ./testgo test testdata/standalone_test.go; then
 	ok=false
 fi
 
+TEST 'go test xtestonly works'
+export GOPATH=$(pwd)/testdata
+./testgo clean -i xtestonly
+if ! ./testgo test xtestonly >/dev/null; then
+	echo "go test xtestonly failed"
+	ok=false
+fi
+unset GOPATH
+
+
 # clean up
 if $started; then stop; fi
 rm -rf testdata/bin testdata/bin1
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index e309501f82..b30182791e 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -559,8 +559,10 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 	}
 	stk.pop()
 	stk.push(p.ImportPath + "_test")
+	pxtestNeedsPtest := false
 	for _, path := range p.XTestImports {
 		if path == p.ImportPath {
+			pxtestNeedsPtest = true
 			continue
 		}
 		p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path])
@@ -666,7 +668,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 			fake:    true,
 			Stale:   true,
 		}
-		if ptest != p {
+		if pxtestNeedsPtest {
 			pxtest.imports = append(pxtest.imports, ptest)
 		}
 	}
@@ -684,17 +686,13 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 		Stale:      true,
 		omitDWARF:  !testC && !testNeedBinary,
 	}
-	if ptest != p {
-		pmain.imports = append(pmain.imports, ptest)
-	}
-	if pxtest != nil {
-		pmain.imports = append(pmain.imports, pxtest)
-	}
 
 	// The generated main also imports testing and regexp.
 	stk.push("testmain")
 	for dep := range testMainDeps {
-		if ptest.ImportPath != dep {
+		if dep == ptest.ImportPath {
+			pmain.imports = append(pmain.imports, ptest)
+		} else {
 			p1 := loadImport(dep, "", &stk, nil)
 			if p1.Error != nil {
 				return nil, nil, nil, p1.Error
@@ -717,6 +715,14 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 		}
 	}
 
+	// writeTestmain writes _testmain.go but also updates
+	// pmain.imports to reflect the import statements written
+	// to _testmain.go. This metadata is needed for recompileForTest
+	// and the builds below.
+	if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), pmain, ptest, pxtest); err != nil {
+		return nil, nil, nil, err
+	}
+
 	if ptest != p && localCover {
 		// We have made modifications to the package p being tested
 		// and are rebuilding p (as ptest), writing it to the testDir tree.
@@ -733,10 +739,6 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 		recompileForTest(pmain, p, ptest, testDir)
 	}
 
-	if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), pmain, ptest); err != nil {
-		return nil, nil, nil, err
-	}
-
 	computeStale(pmain)
 
 	if ptest != p {
@@ -1056,30 +1058,36 @@ type coverInfo struct {
 }
 
 // writeTestmain writes the _testmain.go file for package p to
-// the file named out.
-func writeTestmain(out string, pmain, p *Package) error {
-	var cover []coverInfo
-	for _, cp := range pmain.imports {
-		if len(cp.coverVars) > 0 {
-			cover = append(cover, coverInfo{cp, cp.coverVars})
-		}
-	}
-
+// the file named out. It also updates pmain.imports to include
+// ptest and/or pxtest, depending on what it writes to _testmain.go.
+func writeTestmain(out string, pmain, ptest, pxtest *Package) error {
 	t := &testFuncs{
-		Package: p,
-		Cover:   cover,
+		Package: ptest,
 	}
-	for _, file := range p.TestGoFiles {
-		if err := t.load(filepath.Join(p.Dir, file), "_test", &t.NeedTest); err != nil {
+	for _, file := range ptest.TestGoFiles {
+		if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.NeedTest); err != nil {
 			return err
 		}
 	}
-	for _, file := range p.XTestGoFiles {
-		if err := t.load(filepath.Join(p.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+	for _, file := range ptest.XTestGoFiles {
+		if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.NeedXtest); err != nil {
 			return err
 		}
 	}
 
+	if t.NeedTest {
+		pmain.imports = append(pmain.imports, ptest)
+	}
+	if t.NeedXtest {
+		pmain.imports = append(pmain.imports, pxtest)
+	}
+
+	for _, cp := range pmain.imports {
+		if len(cp.coverVars) > 0 {
+			t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
+		}
+	}
+
 	f, err := os.Create(out)
 	if err != nil {
 		return err
diff --git a/src/cmd/go/testdata/src/xtestonly/f.go b/src/cmd/go/testdata/src/xtestonly/f.go
new file mode 100644
index 0000000000..dac039e1ad
--- /dev/null
+++ b/src/cmd/go/testdata/src/xtestonly/f.go
@@ -0,0 +1,3 @@
+package xtestonly
+
+func F() int { return 42 }
diff --git a/src/cmd/go/testdata/src/xtestonly/f_test.go b/src/cmd/go/testdata/src/xtestonly/f_test.go
new file mode 100644
index 0000000000..01f6e83730
--- /dev/null
+++ b/src/cmd/go/testdata/src/xtestonly/f_test.go
@@ -0,0 +1,12 @@
+package xtestonly_test
+
+import (
+	"testing"
+	"xtestonly"
+)
+
+func TestF(t *testing.T) {
+	if x := xtestonly.F(); x != 42 {
+		t.Errorf("f.F() = %d, want 42", x)
+	}
+}
-- 
2.30.9