gopls/internal/regtest: convert circular import tests to regtests

These tests require special cases and are difficult to understand in the
marker format. They are much simpler as regression tests.

Fixes golang/go#40332

Change-Id: I791b9092d0f3d08aa5415eced427850626f8eb2a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/272207
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/gopls/internal/regtest/diagnostics_test.go b/gopls/internal/regtest/diagnostics_test.go
index 90d0938..8a7008a 100644
--- a/gopls/internal/regtest/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics_test.go
@@ -1515,3 +1515,45 @@
 		)
 	})
 }
+
+// Confirms that circular imports are tested and reported.
+func TestCircularImports(t *testing.T) {
+	const mod = `
+-- go.mod --
+module mod.com
+
+go 1.12
+-- self/self.go --
+package self
+
+import _ "mod.com/self"
+func Hello() {}
+-- double/a/a.go --
+package a
+
+import _ "mod.com/double/b"
+-- double/b/b.go --
+package b
+
+import _ "mod.com/double/a"
+-- triple/a/a.go --
+package a
+
+import _ "mod.com/triple/b"
+-- triple/b/b.go --
+package b
+
+import _ "mod.com/triple/c"
+-- triple/c/c.go --
+package c
+
+import _ "mod.com/triple/a"
+`
+	run(t, mod, func(t *testing.T, env *Env) {
+		env.Await(
+			env.DiagnosticAtRegexpWithMessage("self/self.go", `_ "mod.com/self"`, "import cycle not allowed"),
+			env.DiagnosticAtRegexpWithMessage("double/a/a.go", `_ "mod.com/double/b"`, "import cycle not allowed"),
+			env.DiagnosticAtRegexpWithMessage("triple/a/a.go", `_ "mod.com/triple/b"`, "import cycle not allowed"),
+		)
+	})
+}
diff --git a/gopls/internal/regtest/expectation.go b/gopls/internal/regtest/expectation.go
index f895e8c..b518984 100644
--- a/gopls/internal/regtest/expectation.go
+++ b/gopls/internal/regtest/expectation.go
@@ -504,6 +504,14 @@
 	return DiagnosticExpectation{path: name, pos: &pos, re: re, present: true}
 }
 
+// DiagnosticAtRegexpWithMessage is like DiagnosticAtRegexp, but it also
+// checks for the content of the diagnostic message,
+func (e *Env) DiagnosticAtRegexpWithMessage(name, re, msg string) DiagnosticExpectation {
+	e.T.Helper()
+	pos := e.RegexpSearch(name, re)
+	return DiagnosticExpectation{path: name, pos: &pos, re: re, present: true, message: msg}
+}
+
 // DiagnosticAt asserts that there is a diagnostic entry at the position
 // specified by line and col, for the workdir-relative path name.
 func DiagnosticAt(name string, line, col int) DiagnosticExpectation {
diff --git a/internal/lsp/cmd/test/check.go b/internal/lsp/cmd/test/check.go
index 24e916f..1e07df3 100644
--- a/internal/lsp/cmd/test/check.go
+++ b/internal/lsp/cmd/test/check.go
@@ -18,9 +18,6 @@
 	if len(want) == 1 && want[0].Message == "" {
 		return
 	}
-	if strings.Contains(uri.Filename(), "circular") {
-		t.Skip("skipping circular diagnostics tests due to golang/go#36265")
-	}
 	fname := uri.Filename()
 	out, _ := r.runGoplsCmd(t, "check", fname)
 	// parse got into a collection of reports
@@ -53,8 +50,8 @@
 			expect = fmt.Sprintf("%v:%v: %v", uri.Filename(), diag.Range.Start.Line+1, diag.Message)
 		}
 		expect = r.NormalizePrefix(expect)
-		// Skip the badimport and import cycle not allowed test for now, until we do a better job with diagnostic ranges.
-		if strings.Contains(uri.Filename(), "badimport") || strings.Contains(expect, "import cycle") {
+		// Skip the badimport test for now, until we do a better job with diagnostic ranges.
+		if strings.Contains(uri.Filename(), "badimport") {
 			continue
 		}
 		_, found := got[expect]
@@ -65,8 +62,8 @@
 		}
 	}
 	for extra := range got {
-		// Skip the badimport and import cycle not allowed test for now, until we do a better job with diagnostic ranges.
-		if strings.Contains(extra, "badimport") || strings.Contains(extra, "import cycle") {
+		// Skip the badimport test for now, until we do a better job with diagnostic ranges.
+		if strings.Contains(extra, "badimport") {
 			continue
 		}
 		t.Errorf("extra diagnostic %q", extra)
diff --git a/internal/lsp/testdata/circular/double/b/b.go b/internal/lsp/testdata/circular/double/b/b.go
deleted file mode 100644
index 1372522..0000000
--- a/internal/lsp/testdata/circular/double/b/b.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package b
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular/double/one" //@diag("_ \"golang.org/x/tools/internal/lsp/circular/double/one\"", "compiler", "import cycle not allowed", "error"),diag("\"golang.org/x/tools/internal/lsp/circular/double/one\"", "compiler", "could not import golang.org/x/tools/internal/lsp/circular/double/one (no package for import golang.org/x/tools/internal/lsp/circular/double/one)", "error")
-)
diff --git a/internal/lsp/testdata/circular/double/one/one.go b/internal/lsp/testdata/circular/double/one/one.go
deleted file mode 100644
index 7a5f674..0000000
--- a/internal/lsp/testdata/circular/double/one/one.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package one
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular/double/b"
-)
\ No newline at end of file
diff --git a/internal/lsp/testdata/circular/self.go b/internal/lsp/testdata/circular/self.go
deleted file mode 100644
index 5ec8b41..0000000
--- a/internal/lsp/testdata/circular/self.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package circular
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular" //@diag("_ \"golang.org/x/tools/internal/lsp/circular\"", "compiler", "import cycle not allowed", "error"),diag("\"golang.org/x/tools/internal/lsp/circular\"", "compiler", "could not import golang.org/x/tools/internal/lsp/circular (no package for import golang.org/x/tools/internal/lsp/circular)", "error")
-)
diff --git a/internal/lsp/testdata/circular/triple/a/a.go b/internal/lsp/testdata/circular/triple/a/a.go
deleted file mode 100644
index 64b6c74..0000000
--- a/internal/lsp/testdata/circular/triple/a/a.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package a
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular/triple/b" //@diag("_ \"golang.org/x/tools/internal/lsp/circular/triple/b\"", "compiler", "import cycle not allowed", "error")
-)
diff --git a/internal/lsp/testdata/circular/triple/b/b.go b/internal/lsp/testdata/circular/triple/b/b.go
deleted file mode 100644
index 955a9c8..0000000
--- a/internal/lsp/testdata/circular/triple/b/b.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package b
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular/triple/c"
-)
diff --git a/internal/lsp/testdata/circular/triple/c/c.go b/internal/lsp/testdata/circular/triple/c/c.go
deleted file mode 100644
index fccd2e4..0000000
--- a/internal/lsp/testdata/circular/triple/c/c.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package c
-
-import (
-	_ "golang.org/x/tools/internal/lsp/circular/triple/a"
-)
diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden
index a8a3799..e7af0bd 100644
--- a/internal/lsp/testdata/summary.txt.golden
+++ b/internal/lsp/testdata/summary.txt.golden
@@ -8,7 +8,7 @@
 FuzzyCompletionsCount = 8
 RankedCompletionsCount = 158
 CaseSensitiveCompletionsCount = 4
-DiagnosticsCount = 43
+DiagnosticsCount = 38
 FoldingRangesCount = 2
 FormatCount = 6
 ImportCount = 8