internal/lsp/regtest: allow for unsent diagnostics in TestResolveImportCycle

Gopls doesn't send empty diagnostics for open files in some cases
(likely a race to context cancellation). This is probably a bug itself,
but for now don't let this cause TestResolveImportCycle to fail.

Added a TODO to investigate further.

Fixes golang/go#46773

Change-Id: I197d9b09885951b47b3f90a0480ae75679d2a1a0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/333289
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go
index 1aff66e..9ee102c 100644
--- a/gopls/internal/regtest/diagnostics/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go
@@ -1618,7 +1618,6 @@
 // Tests golang/go#46667: deleting a problematic import path should resolve
 // import cycle errors.
 func TestResolveImportCycle(t *testing.T) {
-	t.Skip("flaky test: see golang/go#46773")
 	const mod = `
 -- go.mod --
 module mod.test
@@ -1646,8 +1645,8 @@
 		env.RegexpReplace("b/b.go", `const B = a\.B`, "")
 		env.SaveBuffer("b/b.go")
 		env.Await(
-			EmptyDiagnostics("a/a.go"),
-			EmptyDiagnostics("b/b.go"),
+			EmptyOrNoDiagnostics("a/a.go"),
+			EmptyOrNoDiagnostics("b/b.go"),
 		)
 	})
 }
diff --git a/internal/lsp/regtest/expectation.go b/internal/lsp/regtest/expectation.go
index f80d8f5..eb24955 100644
--- a/internal/lsp/regtest/expectation.go
+++ b/internal/lsp/regtest/expectation.go
@@ -533,6 +533,23 @@
 	}
 }
 
+// EmptyOrNoDiagnostics asserts that either no diagnostics are sent for the
+// workspace-relative path name, or empty diagnostics are sent.
+// TODO(rFindley): this subtlety shouldn't be necessary. Gopls should always
+// send at least one diagnostic set for open files.
+func EmptyOrNoDiagnostics(name string) Expectation {
+	check := func(s State) Verdict {
+		if diags := s.diagnostics[name]; len(diags.Diagnostics) == 0 {
+			return Met
+		}
+		return Unmet
+	}
+	return SimpleExpectation{
+		check:       check,
+		description: fmt.Sprintf("empty or no diagnostics for %q", name),
+	}
+}
+
 // NoDiagnostics asserts that no diagnostics are sent for the
 // workspace-relative path name. It should be used primarily in conjunction
 // with a OnceMet, as it has to check that all outstanding diagnostics have