gopls: add a test that mirrors govim's -mod=readonly test

This isn't strictly necessary, but we've broken it a number of times,
and it's easier to have a regtest for it. When golang/go#41437 is resolved, we
might consider making this a -mod=mod test or something.

Also, added a wrapper for RunGoCommand.

Change-Id: I75db585549d84dacde9d3efbc6e02a7ba4e005aa
Reviewed-on: https://go-review.googlesource.com/c/tools/+/258803
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
diff --git a/gopls/internal/regtest/diagnostics_test.go b/gopls/internal/regtest/diagnostics_test.go
index 0ddf6cb..2d70f40 100644
--- a/gopls/internal/regtest/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics_test.go
@@ -273,9 +273,7 @@
 			env.Await(
 				env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
 			)
-			if err := env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"init", "mod.com"}); err != nil {
-				t.Fatal(err)
-			}
+			env.RunGoCommand("mod", "init", "mod.com")
 			env.Await(
 				EmptyDiagnostics("main.go"),
 				env.DiagnosticAtRegexp("bob/bob.go", "x"),
diff --git a/gopls/internal/regtest/modfile_test.go b/gopls/internal/regtest/modfile_test.go
index 11fe302..f1c84ab 100644
--- a/gopls/internal/regtest/modfile_test.go
+++ b/gopls/internal/regtest/modfile_test.go
@@ -314,7 +314,7 @@
 `
 	runner.Run(t, mod, func(t *testing.T, env *Env) {
 		env.Await(env.DiagnosticAtRegexp("go.mod", "require"))
-		env.Sandbox.RunGoCommand(env.Ctx, "", "mod", []string{"tidy"})
+		env.RunGoCommand("mod", "tidy")
 		env.Await(
 			EmptyDiagnostics("go.mod"),
 		)
@@ -565,3 +565,45 @@
 		)
 	})
 }
+
+// A copy of govim's config_set_env_goflags_mod_readonly test.
+func TestGovimModReadonly(t *testing.T) {
+	const mod = `
+-- go.mod --
+module mod.com
+
+go 1.13
+-- main.go --
+package main
+
+import "example.com/blah"
+
+func main() {
+	println(blah.Name)
+}
+`
+	withOptions(
+		EditorConfig{
+			Env: map[string]string{
+				"GOFLAGS": "-mod=readonly",
+			},
+			WithoutExperimentalWorkspaceModule: true,
+		},
+		WithProxyFiles(proxy),
+	).run(t, mod, func(t *testing.T, env *Env) {
+		env.OpenFile("main.go")
+		original := env.ReadWorkspaceFile("go.mod")
+		env.Await(
+			env.DiagnosticAtRegexp("main.go", `"example.com/blah"`),
+		)
+		got := env.ReadWorkspaceFile("go.mod")
+		if got != original {
+			t.Fatalf("go.mod file modified:\n%s", tests.Diff(original, got))
+		}
+		env.RunGoCommand("get", "example.com/blah@v1.2.3")
+		env.RunGoCommand("mod", "tidy")
+		env.Await(
+			EmptyDiagnostics("main.go"),
+		)
+	})
+}
diff --git a/gopls/internal/regtest/wrappers.go b/gopls/internal/regtest/wrappers.go
index 294d303..dce92ca 100644
--- a/gopls/internal/regtest/wrappers.go
+++ b/gopls/internal/regtest/wrappers.go
@@ -239,6 +239,14 @@
 	e.CheckForFileChanges()
 }
 
+// RunGoCommand runs the given command in the sandbox's default working
+// directory.
+func (e *Env) RunGoCommand(verb string, args ...string) {
+	if err := e.Sandbox.RunGoCommand(e.Ctx, "", verb, args); err != nil {
+		e.T.Fatal(err)
+	}
+}
+
 // CheckForFileChanges triggers a manual poll of the workspace for any file
 // changes since creation, or since last polling. It is a workaround for the
 // lack of true file watching support in the fake workspace.