cmd/guru: fix tests now that go1.9 go/types returns fake packages

The go1.9 type checker now returns fake packages in addition to an
error if the package was not found at all.  This changes the behavior
of guru in a release-specific way, requiring the test to be split into
a common part and a go1.9-specific part.

In hindsight, perhaps it would have been better to place the
expectation in a comment alongside the query so that they can be
easily enabled or disabled together.  (The downside of that design is
that you can't batch-update all the expectations to match the actual
behavior.)

Change-Id: I58054adec428fbab7fe3c57097aefc827f89a46e
Reviewed-on: https://go-review.googlesource.com/37865
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/cmd/guru/guru_test.go b/cmd/guru/guru_test.go
index ac185fd..4026136 100644
--- a/cmd/guru/guru_test.go
+++ b/cmd/guru/guru_test.go
@@ -221,6 +221,7 @@
 		"testdata/src/alias/alias.go", // iff guru.HasAlias (go1.9)
 		"testdata/src/calls/main.go",
 		"testdata/src/describe/main.go",
+		"testdata/src/describe/main19.go", // iff go1.9
 		"testdata/src/freevars/main.go",
 		"testdata/src/implements/main.go",
 		"testdata/src/implements-methods/main.go",
@@ -237,6 +238,7 @@
 		"testdata/src/calls-json/main.go",
 		"testdata/src/peers-json/main.go",
 		"testdata/src/definition-json/main.go",
+		"testdata/src/definition-json/main19.go",
 		"testdata/src/describe-json/main.go",
 		"testdata/src/implements-json/main.go",
 		"testdata/src/implements-methods-json/main.go",
@@ -252,6 +254,11 @@
 		if filename == "testdata/src/alias/alias.go" && !guru.HasAlias {
 			continue
 		}
+		if strings.HasSuffix(filename, "19.go") && !contains(build.Default.ReleaseTags, "go1.9") {
+			// TODO(adonovan): recombine the 'describe' and 'definition'
+			// tests once we drop support for go1.8.
+			continue
+		}
 
 		json := strings.Contains(filename, "-json/")
 		queries := parseQueries(t, filename)
@@ -296,6 +303,15 @@
 	}
 }
 
+func contains(haystack []string, needle string) bool {
+	for _, x := range haystack {
+		if needle == x {
+			return true
+		}
+	}
+	return false
+}
+
 func TestIssue14684(t *testing.T) {
 	var buildContext = build.Default
 	buildContext.GOPATH = "testdata"
diff --git a/cmd/guru/testdata/src/definition-json/main.go b/cmd/guru/testdata/src/definition-json/main.go
index 1674519..6408404 100644
--- a/cmd/guru/testdata/src/definition-json/main.go
+++ b/cmd/guru/testdata/src/definition-json/main.go
@@ -9,7 +9,6 @@
 import (
 	"lib"
 	lib2 "lib"
-	"nosuchpkg"
 )
 
 func main() {
@@ -28,7 +27,6 @@
 	var _ lib.Const    // @definition qualified-const "Const"
 	var _ lib2.Type    // @definition qualified-type-renaming "Type"
 	var _ lib.Nonesuch // @definition qualified-nomember "Nonesuch"
-	var _ nosuchpkg.T  // @definition qualified-nopkg "nosuchpkg"
 
 	var u U
 	print(u.field) // @definition select-field "field"
diff --git a/cmd/guru/testdata/src/definition-json/main.golden b/cmd/guru/testdata/src/definition-json/main.golden
index e93903d..af0a687 100644
--- a/cmd/guru/testdata/src/definition-json/main.golden
+++ b/cmd/guru/testdata/src/definition-json/main.golden
@@ -11,17 +11,17 @@
 }
 -------- @definition lexical-func --------
 {
-	"objpos": "$GOPATH/src/definition-json/main.go:38:6",
+	"objpos": "$GOPATH/src/definition-json/main.go:36:6",
 	"desc": "func f"
 }
 -------- @definition lexical-var --------
 {
-	"objpos": "$GOPATH/src/definition-json/main.go:19:6",
+	"objpos": "$GOPATH/src/definition-json/main.go:18:6",
 	"desc": "var x"
 }
 -------- @definition lexical-shadowing --------
 {
-	"objpos": "$GOPATH/src/definition-json/main.go:22:5",
+	"objpos": "$GOPATH/src/definition-json/main.go:21:5",
 	"desc": "var x"
 }
 -------- @definition qualified-type --------
@@ -52,17 +52,14 @@
 -------- @definition qualified-nomember --------
 
 Error: couldn't find declaration of Nonesuch in "lib"
--------- @definition qualified-nopkg --------
-
-Error: no object for identifier
 -------- @definition select-field --------
 {
-	"objpos": "testdata/src/definition-json/main.go:40:16",
+	"objpos": "testdata/src/definition-json/main.go:38:16",
 	"desc": "field field int"
 }
 -------- @definition select-method --------
 {
-	"objpos": "testdata/src/definition-json/main.go:42:10",
+	"objpos": "testdata/src/definition-json/main.go:40:10",
 	"desc": "func (T).method()"
 }
 -------- @definition embedded-other-file --------
@@ -88,6 +85,6 @@
 }
 -------- @definition embedded-same-file --------
 {
-	"objpos": "$GOPATH/src/definition-json/main.go:40:6",
+	"objpos": "$GOPATH/src/definition-json/main.go:38:6",
 	"desc": "type T"
 }
diff --git a/cmd/guru/testdata/src/definition-json/main19.go b/cmd/guru/testdata/src/definition-json/main19.go
new file mode 100644
index 0000000..9f047c3
--- /dev/null
+++ b/cmd/guru/testdata/src/definition-json/main19.go
@@ -0,0 +1,5 @@
+package definition
+
+import "nosuchpkg"
+
+var _ nosuchpkg.T // @definition qualified-nopkg "nosuchpkg"
diff --git a/cmd/guru/testdata/src/definition-json/main19.golden b/cmd/guru/testdata/src/definition-json/main19.golden
new file mode 100644
index 0000000..3281aa5
--- /dev/null
+++ b/cmd/guru/testdata/src/definition-json/main19.golden
@@ -0,0 +1,5 @@
+-------- @definition qualified-nopkg --------
+{
+	"objpos": "testdata/src/definition-json/main19.go:3:8",
+	"desc": "package nosuchpkg"
+}
diff --git a/cmd/guru/testdata/src/describe/main.go b/cmd/guru/testdata/src/describe/main.go
index 8e56aca..c6c5349 100644
--- a/cmd/guru/testdata/src/describe/main.go
+++ b/cmd/guru/testdata/src/describe/main.go
@@ -8,14 +8,9 @@
 
 import (
 	"lib"
-	"nosuchpkg"            // @describe badimport1 "nosuchpkg"
-	nosuchpkg2 "nosuchpkg" // @describe badimport2 "nosuchpkg2"
-	_ "unsafe"             // @describe unsafe "unsafe"
+	_ "unsafe" // @describe unsafe "unsafe"
 )
 
-var _ nosuchpkg.T
-var _ nosuchpkg2.T
-
 type cake float64 // @describe type-ref-builtin "float64"
 
 const c = iota // @describe const-ref-iota "iota"
diff --git a/cmd/guru/testdata/src/describe/main.golden b/cmd/guru/testdata/src/describe/main.golden
index 940ef57..724643d 100644
--- a/cmd/guru/testdata/src/describe/main.golden
+++ b/cmd/guru/testdata/src/describe/main.golden
@@ -13,12 +13,6 @@
 	const pi     untyped float = 3.141
 	const pie    cake = 3.141
 
--------- @describe badimport1 --------
-
-Error: can't import package "nosuchpkg"
--------- @describe badimport2 --------
-
-Error: can't import package "nosuchpkg"
 -------- @describe unsafe --------
 import of package "unsafe"
 	builtin Alignof 
diff --git a/cmd/guru/testdata/src/describe/main19.go b/cmd/guru/testdata/src/describe/main19.go
new file mode 100644
index 0000000..2068f8c
--- /dev/null
+++ b/cmd/guru/testdata/src/describe/main19.go
@@ -0,0 +1,13 @@
+package describe
+
+// The behavior of "describe" on a non-existent import changed
+// when go/types started returning fake packages, so this test
+// is executed only under go1.9.
+
+import (
+	"nosuchpkg"            // @describe badimport1 "nosuchpkg"
+	nosuchpkg2 "nosuchpkg" // @describe badimport2 "nosuchpkg2"
+)
+
+var _ nosuchpkg.T
+var _ nosuchpkg2.T
diff --git a/cmd/guru/testdata/src/describe/main19.golden b/cmd/guru/testdata/src/describe/main19.golden
new file mode 100644
index 0000000..005e30b
--- /dev/null
+++ b/cmd/guru/testdata/src/describe/main19.golden
@@ -0,0 +1,6 @@
+-------- @describe badimport1 --------
+import of package "nosuchpkg"
+
+-------- @describe badimport2 --------
+reference to package "nosuchpkg"
+
diff --git a/cmd/guru/testdata/src/referrers-json/main.golden b/cmd/guru/testdata/src/referrers-json/main.golden
index bc44ab2..7bda141 100644
--- a/cmd/guru/testdata/src/referrers-json/main.golden
+++ b/cmd/guru/testdata/src/referrers-json/main.golden
@@ -6,35 +6,35 @@
 	"package": "definition-json",
 	"refs": [
 		{
-			"pos": "testdata/src/definition-json/main.go:19:8",
+			"pos": "testdata/src/definition-json/main.go:18:8",
 			"text": "\tvar x lib.T           // @definition lexical-pkgname \"lib\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:25:8",
+			"pos": "testdata/src/definition-json/main.go:24:8",
 			"text": "\tvar _ lib.Type     // @definition qualified-type \"Type\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:26:8",
+			"pos": "testdata/src/definition-json/main.go:25:8",
 			"text": "\tvar _ lib.Func     // @definition qualified-func \"Func\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:27:8",
+			"pos": "testdata/src/definition-json/main.go:26:8",
 			"text": "\tvar _ lib.Var      // @definition qualified-var \"Var\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:28:8",
+			"pos": "testdata/src/definition-json/main.go:27:8",
 			"text": "\tvar _ lib.Const    // @definition qualified-const \"Const\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:29:8",
+			"pos": "testdata/src/definition-json/main.go:28:8",
 			"text": "\tvar _ lib2.Type    // @definition qualified-type-renaming \"Type\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:30:8",
+			"pos": "testdata/src/definition-json/main.go:29:8",
 			"text": "\tvar _ lib.Nonesuch // @definition qualified-nomember \"Nonesuch\""
 		},
 		{
-			"pos": "testdata/src/definition-json/main.go:63:2",
+			"pos": "testdata/src/definition-json/main.go:61:2",
 			"text": "\tlib.Type // @definition embedded-other-pkg \"Type\""
 		}
 	]
@@ -43,7 +43,7 @@
 	"package": "describe",
 	"refs": [
 		{
-			"pos": "testdata/src/describe/main.go:91:8",
+			"pos": "testdata/src/describe/main.go:86:8",
 			"text": "\tvar _ lib.Outer // @describe lib-outer \"Outer\""
 		}
 	]