1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 . "golang.org/x/tools/gopls/internal/regtest"
14 "golang.org/x/tools/internal/lsp/protocol"
15 "golang.org/x/tools/internal/lsp/tests"
16 "golang.org/x/tools/internal/testenv"
19 func TestMain(m *testing.M) {
23 const workspaceProxy = `
24 -- example.com@v1.2.3/go.mod --
28 -- example.com@v1.2.3/blah/blah.go --
32 fmt.Println("something")
34 -- random.org@v1.2.3/go.mod --
38 -- random.org@v1.2.3/bye/bye.go --
47 -- example.com@v1.2.3/go.mod --
51 -- example.com@v1.2.3/blah/blah.go --
55 -- random.org@v1.2.3/go.mod --
59 -- random.org@v1.2.3/blah/blah.go --
65 func TestModFileModification(t *testing.T) {
66 testenv.NeedsGo1Point(t, 14)
68 const untidyModule = `
75 import "example.com/blah"
82 runner := RunMultiple{
83 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
84 {"nested", WithOptions(ProxyFiles(proxy))},
87 t.Run("basic", func(t *testing.T) {
88 runner.Run(t, untidyModule, func(t *testing.T, env *Env) {
89 // Open the file and make sure that the initial workspace load does not
90 // modify the go.mod file.
91 goModContent := env.ReadWorkspaceFile("a/go.mod")
92 env.OpenFile("a/main.go")
94 env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
96 if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
97 t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
99 // Save the buffer, which will format and organize imports.
100 // Confirm that the go.mod file still does not change.
101 env.SaveBuffer("a/main.go")
103 env.DiagnosticAtRegexp("a/main.go", "\"example.com/blah\""),
105 if got := env.ReadWorkspaceFile("a/go.mod"); got != goModContent {
106 t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
111 // Reproduce golang/go#40269 by deleting and recreating main.go.
112 t.Run("delete main.go", func(t *testing.T) {
113 t.Skip("This test will be flaky until golang/go#40269 is resolved.")
115 runner.Run(t, untidyModule, func(t *testing.T, env *Env) {
116 goModContent := env.ReadWorkspaceFile("a/go.mod")
117 mainContent := env.ReadWorkspaceFile("a/main.go")
118 env.OpenFile("a/main.go")
119 env.SaveBuffer("a/main.go")
121 env.RemoveWorkspaceFile("a/main.go")
125 env.DoneWithChangeWatchedFiles(),
128 env.WriteWorkspaceFile("main.go", mainContent)
130 env.DiagnosticAtRegexp("main.go", "\"example.com/blah\""),
132 if got := env.ReadWorkspaceFile("go.mod"); got != goModContent {
133 t.Fatalf("go.mod changed on disk:\n%s", tests.Diff(t, goModContent, got))
139 func TestGoGetFix(t *testing.T) {
140 testenv.NeedsGo1Point(t, 14)
150 import "example.com/blah"
155 const want = `module mod.com
159 require example.com v1.2.3
163 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
164 {"nested", WithOptions(ProxyFiles(proxy))},
165 }.Run(t, mod, func(t *testing.T, env *Env) {
166 if strings.Contains(t.Name(), "workspace_module") {
167 t.Skip("workspace module mode doesn't set -mod=readonly")
169 env.OpenFile("a/main.go")
170 var d protocol.PublishDiagnosticsParams
173 env.DiagnosticAtRegexp("a/main.go", `"example.com/blah"`),
174 ReadDiagnostics("a/main.go", &d),
177 var goGetDiag protocol.Diagnostic
178 for _, diag := range d.Diagnostics {
179 if strings.Contains(diag.Message, "could not import") {
183 env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{goGetDiag})
184 if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
185 t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
190 // Tests that multiple missing dependencies gives good single fixes.
191 func TestMissingDependencyFixes(t *testing.T) {
192 testenv.NeedsGo1Point(t, 14)
202 import "example.com/blah"
203 import "random.org/blah"
205 var _, _ = blah.Name, hello.Name
208 const want = `module mod.com
212 require random.org v1.2.3
216 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
217 {"nested", WithOptions(ProxyFiles(proxy))},
218 }.Run(t, mod, func(t *testing.T, env *Env) {
219 env.OpenFile("a/main.go")
220 var d protocol.PublishDiagnosticsParams
223 env.DiagnosticAtRegexp("a/main.go", `"random.org/blah"`),
224 ReadDiagnostics("a/main.go", &d),
227 var randomDiag protocol.Diagnostic
228 for _, diag := range d.Diagnostics {
229 if strings.Contains(diag.Message, "random.org") {
233 env.ApplyQuickFixes("a/main.go", []protocol.Diagnostic{randomDiag})
234 if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
235 t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
240 func TestIndirectDependencyFix(t *testing.T) {
241 testenv.NeedsGo1Point(t, 14)
249 require example.com v1.2.3 // indirect
251 example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
252 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
256 import "example.com/blah"
259 fmt.Println(blah.Name)
261 const want = `module mod.com
265 require example.com v1.2.3
269 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
270 {"nested", WithOptions(ProxyFiles(proxy))},
271 }.Run(t, mod, func(t *testing.T, env *Env) {
272 env.OpenFile("a/go.mod")
273 var d protocol.PublishDiagnosticsParams
276 env.DiagnosticAtRegexp("a/go.mod", "// indirect"),
277 ReadDiagnostics("a/go.mod", &d),
280 env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
281 if got := env.Editor.BufferText("a/go.mod"); got != want {
282 t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
287 func TestUnusedDiag(t *testing.T) {
288 testenv.NeedsGo1Point(t, 14)
291 -- example.com@v1.0.0/x.go --
299 require example.com v1.0.0
301 example.com v1.0.0 h1:38O7j5rEBajXk+Q5wzLbRN7KqMkSgEiN9NqcM1O2bBM=
302 example.com v1.0.0/go.mod h1:vUsPMGpx9ZXXzECCOsOmYCW7npJTwuA16yl89n3Mgls=
308 const want = `module mod.com
314 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
315 {"nested", WithOptions(ProxyFiles(proxy))},
316 }.Run(t, files, func(t *testing.T, env *Env) {
317 env.OpenFile("a/go.mod")
318 var d protocol.PublishDiagnosticsParams
321 env.DiagnosticAtRegexp("a/go.mod", `require example.com`),
322 ReadDiagnostics("a/go.mod", &d),
325 env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
326 if got := env.Editor.BufferText("a/go.mod"); got != want {
327 t.Fatalf("unexpected go.mod content:\n%s", tests.Diff(t, want, got))
332 // Test to reproduce golang/go#39041. It adds a new require to a go.mod file
333 // that already has an unused require.
334 func TestNewDepWithUnusedDep(t *testing.T) {
335 testenv.NeedsGo1Point(t, 14)
338 -- github.com/esimov/caire@v1.2.5/go.mod --
339 module github.com/esimov/caire
342 -- github.com/esimov/caire@v1.2.5/caire.go --
345 func RemoveTempImage() {}
346 -- google.golang.org/protobuf@v1.20.0/go.mod --
347 module google.golang.org/protobuf
350 -- google.golang.org/protobuf@v1.20.0/hello/hello.go --
359 require google.golang.org/protobuf v1.20.0
361 github.com/esimov/caire v1.2.5 h1:OcqDII/BYxcBYj3DuwDKjd+ANhRxRqLa2n69EGje7qw=
362 github.com/esimov/caire v1.2.5/go.mod h1:mXnjRjg3+WUtuhfSC1rKRmdZU9vJZyS1ZWU0qSvJhK8=
363 google.golang.org/protobuf v1.20.0 h1:y9T1vAtFKQg0faFNMOxJU7WuEqPWolVkjIkU6aI8qCY=
364 google.golang.org/protobuf v1.20.0/go.mod h1:FcqsytGClbtLv1ot8NvsJHjBi0h22StKVP+K/j2liKA=
369 "github.com/esimov/caire"
373 caire.RemoveTempImage()
377 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
378 {"nested", WithOptions(ProxyFiles(proxy))},
379 }.Run(t, repro, func(t *testing.T, env *Env) {
380 env.OpenFile("a/main.go")
381 var d protocol.PublishDiagnosticsParams
384 env.DiagnosticAtRegexp("a/main.go", `"github.com/esimov/caire"`),
385 ReadDiagnostics("a/main.go", &d),
388 env.ApplyQuickFixes("a/main.go", d.Diagnostics)
389 want := `module mod.com
394 github.com/esimov/caire v1.2.5
395 google.golang.org/protobuf v1.20.0
398 if got := env.ReadWorkspaceFile("a/go.mod"); got != want {
399 t.Fatalf("TestNewDepWithUnusedDep failed:\n%s", tests.Diff(t, want, got))
404 // TODO: For this test to be effective, the sandbox's file watcher must respect
405 // the file watching GlobPattern in the capability registration. See
407 func TestModuleChangesOnDisk(t *testing.T) {
408 testenv.NeedsGo1Point(t, 14)
416 require example.com v1.2.3
418 example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
419 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
424 fmt.Println(blah.Name)
427 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
428 {"nested", WithOptions(ProxyFiles(proxy))},
429 }.Run(t, mod, func(t *testing.T, env *Env) {
430 env.Await(env.DiagnosticAtRegexp("a/go.mod", "require"))
431 env.RunGoCommandInDir("a", "mod", "tidy")
433 EmptyDiagnostics("a/go.mod"),
438 // Tests golang/go#39784: a missing indirect dependency, necessary
439 // due to blah@v2.0.0's incomplete go.mod file.
440 func TestBadlyVersionedModule(t *testing.T) {
441 testenv.NeedsGo1Point(t, 14)
444 -- example.com/blah/@v/v1.0.0.mod --
448 -- example.com/blah@v1.0.0/blah.go --
452 -- example.com/blah/v2/@v/v2.0.0.mod --
456 -- example.com/blah/v2@v2.0.0/blah.go --
459 import "example.com/blah"
461 var V1Name = blah.Name
470 require example.com/blah/v2 v2.0.0
472 example.com/blah v1.0.0 h1:kGPlWJbMsn1P31H9xp/q2mYI32cxLnCvauHN0AVaHnc=
473 example.com/blah v1.0.0/go.mod h1:PZUQaGFeVjyDmAE8ywmLbmDn3fj4Ws8epg4oLuDzW3M=
474 example.com/blah/v2 v2.0.0 h1:DNPsFPkKtTdxclRheaMCiYAoYizp6PuBzO0OmLOO0pY=
475 example.com/blah/v2 v2.0.0/go.mod h1:UZiKbTwobERo/hrqFLvIQlJwQZQGxWMVY4xere8mj7w=
479 import "example.com/blah/v2"
484 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
485 {"nested", WithOptions(ProxyFiles(proxy))},
486 }.Run(t, files, func(t *testing.T, env *Env) {
487 env.OpenFile("a/main.go")
488 env.OpenFile("a/go.mod")
490 // We would like for the error to appear in the v2 module, but
491 // as of writing non-workspace packages are not diagnosed.
492 env.DiagnosticAtRegexpWithMessage("a/main.go", `"example.com/blah/v2"`, "cannot find module providing"),
493 env.DiagnosticAtRegexpWithMessage("a/go.mod", `require example.com/blah/v2`, "cannot find module providing"),
495 env.ApplyQuickFixes("a/go.mod", env.DiagnosticsFor("a/go.mod").Diagnostics)
496 const want = `module mod.com
501 example.com/blah v1.0.0 // indirect
502 example.com/blah/v2 v2.0.0
505 env.SaveBuffer("a/go.mod")
506 env.Await(EmptyDiagnostics("a/main.go"))
507 if got := env.Editor.BufferText("a/go.mod"); got != want {
508 t.Fatalf("suggested fixes failed:\n%s", tests.Diff(t, want, got))
513 // Reproduces golang/go#38232.
514 func TestUnknownRevision(t *testing.T) {
515 testenv.NeedsGo1Point(t, 14)
527 import "example.com/blah"
534 runner := RunMultiple{
535 {"default", WithOptions(ProxyFiles(proxy), WorkspaceFolders("a"))},
536 {"nested", WithOptions(ProxyFiles(proxy))},
538 // Start from a bad state/bad IWL, and confirm that we recover.
539 t.Run("bad", func(t *testing.T) {
540 runner.Run(t, unknown, func(t *testing.T, env *Env) {
541 env.OpenFile("a/go.mod")
543 env.DiagnosticAtRegexp("a/go.mod", "example.com v1.2.2"),
545 env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3")
546 env.SaveBuffer("a/go.mod") // Save to trigger diagnostics.
548 d := protocol.PublishDiagnosticsParams{}
551 // Make sure the diagnostic mentions the new version -- the old diagnostic is in the same place.
552 env.DiagnosticAtRegexpWithMessage("a/go.mod", "example.com v1.2.3", "example.com@v1.2.3"),
553 ReadDiagnostics("a/go.mod", &d),
556 env.ApplyQuickFixes("a/go.mod", d.Diagnostics)
557 env.SaveBuffer("a/go.mod") // Save to trigger diagnostics.
559 EmptyDiagnostics("a/go.mod"),
560 env.DiagnosticAtRegexp("a/main.go", "x = "),
573 example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
574 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
578 import "example.com/blah"
584 // Start from a good state, transform to a bad state, and confirm that we
586 t.Run("good", func(t *testing.T) {
587 runner.Run(t, known, func(t *testing.T, env *Env) {
588 env.OpenFile("a/go.mod")
590 env.DiagnosticAtRegexp("a/main.go", "x = "),
592 env.RegexpReplace("a/go.mod", "v1.2.3", "v1.2.2")
593 env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk
595 env.DiagnosticAtRegexp("a/go.mod", "example.com v1.2.2"),
597 env.RegexpReplace("a/go.mod", "v1.2.2", "v1.2.3")
598 env.Editor.SaveBuffer(env.Ctx, "a/go.mod") // go.mod changes must be on disk
600 env.DiagnosticAtRegexp("a/main.go", "x = "),
606 // Confirm that an error in an indirect dependency of a requirement is surfaced
607 // as a diagnostic in the go.mod file.
608 func TestErrorInIndirectDependency(t *testing.T) {
609 testenv.NeedsGo1Point(t, 14)
612 -- example.com@v1.2.3/go.mod --
617 require random.org v1.2.3 // indirect
618 -- example.com@v1.2.3/blah/blah.go --
622 -- random.org@v1.2.3/go.mod --
626 -- random.org@v1.2.3/blah/blah.go --
637 require example.com v1.2.3
641 import "example.com/blah"
648 {"default", WithOptions(ProxyFiles(badProxy), WorkspaceFolders("a"))},
649 {"nested", WithOptions(ProxyFiles(badProxy))},
650 }.Run(t, module, func(t *testing.T, env *Env) {
651 env.OpenFile("a/go.mod")
653 env.DiagnosticAtRegexp("a/go.mod", "require example.com v1.2.3"),
658 // A copy of govim's config_set_env_goflags_mod_readonly test.
659 func TestGovimModReadonly(t *testing.T) {
668 import "example.com/blah"
676 Env: map[string]string{
677 "GOFLAGS": "-mod=readonly",
682 ).Run(t, mod, func(t *testing.T, env *Env) {
683 env.OpenFile("main.go")
684 original := env.ReadWorkspaceFile("go.mod")
686 env.DiagnosticAtRegexp("main.go", `"example.com/blah"`),
688 got := env.ReadWorkspaceFile("go.mod")
690 t.Fatalf("go.mod file modified:\n%s", tests.Diff(t, original, got))
692 env.RunGoCommand("get", "example.com/blah@v1.2.3")
693 env.RunGoCommand("mod", "tidy")
695 EmptyDiagnostics("main.go"),
700 func TestMultiModuleModDiagnostics(t *testing.T) {
701 testenv.NeedsGo1Point(t, 14)
713 example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
714 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
722 require example.com v1.2.3
728 import "example.com/blah"
735 ProxyFiles(workspaceProxy),
737 ).Run(t, mod, func(t *testing.T, env *Env) {
739 env.DiagnosticAtRegexpWithMessage("a/go.mod", "example.com v1.2.3", "is not used"),
744 func TestModTidyWithBuildTags(t *testing.T) {
745 testenv.NeedsGo1Point(t, 14)
757 import "example.com/blah"
764 ProxyFiles(workspaceProxy),
766 BuildFlags: []string{"-tags", "bob"},
768 ).Run(t, mod, func(t *testing.T, env *Env) {
770 env.DiagnosticAtRegexp("main.go", `"example.com/blah"`),
775 func TestModTypoDiagnostic(t *testing.T) {
786 Run(t, mod, func(t *testing.T, env *Env) {
787 env.OpenFile("go.mod")
788 env.RegexpReplace("go.mod", "module", "modul")
790 env.DiagnosticAtRegexp("go.mod", "modul"),
795 func TestSumUpdateFixesDiagnostics(t *testing.T) {
796 testenv.NeedsGo1Point(t, 14)
820 ProxyFiles(workspaceProxy),
821 ).Run(t, mod, func(t *testing.T, env *Env) {
822 d := &protocol.PublishDiagnosticsParams{}
823 env.OpenFile("go.mod")
826 env.GoSumDiagnostic("go.mod", `example.com v1.2.3`),
827 ReadDiagnostics("go.mod", d),
830 env.ApplyQuickFixes("go.mod", d.Diagnostics)
831 env.SaveBuffer("go.mod") // Save to trigger diagnostics.
833 EmptyDiagnostics("go.mod"),
838 // This test confirms that editing a go.mod file only causes metadata
839 // to be invalidated when it's saved.
840 func TestGoModInvalidatesOnSave(t *testing.T) {
858 // TODO(rFindley) this doesn't work in multi-module workspace mode, because
859 // it keeps around the last parsing modfile. Update this test to also
860 // exercise the workspace module.
862 ).Run(t, mod, func(t *testing.T, env *Env) {
863 env.OpenFile("go.mod")
864 env.Await(env.DoneWithOpen())
865 env.RegexpReplace("go.mod", "module", "modul")
866 // Confirm that we still have metadata with only on-disk edits.
867 env.OpenFile("main.go")
868 file, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", "hello"))
869 if filepath.Base(file) != "hello.go" {
870 t.Fatalf("expected definition in hello.go, got %s", file)
872 // Confirm that we no longer have metadata when the file is saved.
873 env.SaveBufferWithoutActions("go.mod")
874 _, _, err := env.Editor.GoToDefinition(env.Ctx, "main.go", env.RegexpSearch("main.go", "hello"))
876 t.Fatalf("expected error, got none")
881 func TestRemoveUnusedDependency(t *testing.T) {
882 testenv.NeedsGo1Point(t, 14)
885 -- hasdep.com@v1.2.3/go.mod --
890 require example.com v1.2.3
891 -- hasdep.com@v1.2.3/a/a.go --
893 -- example.com@v1.2.3/go.mod --
897 -- example.com@v1.2.3/blah/blah.go --
901 -- random.com@v1.2.3/go.mod --
905 -- random.com@v1.2.3/blah/blah.go --
910 t.Run("almost tidied", func(t *testing.T) {
917 require hasdep.com v1.2.3
919 example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
920 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
921 hasdep.com v1.2.3 h1:00y+N5oD+SpKoqV1zP2VOPawcW65Zb9NebANY3GSzGI=
922 hasdep.com v1.2.3/go.mod h1:ePVZOlez+KZEOejfLPGL2n4i8qiAjrkhQZ4wcImqAes=
930 ).Run(t, mod, func(t *testing.T, env *Env) {
931 env.OpenFile("go.mod")
932 d := &protocol.PublishDiagnosticsParams{}
935 env.DiagnosticAtRegexp("go.mod", "require hasdep.com v1.2.3"),
936 ReadDiagnostics("go.mod", d),
939 const want = `module mod.com
943 env.ApplyQuickFixes("go.mod", d.Diagnostics)
944 if got := env.Editor.BufferText("go.mod"); got != want {
945 t.Fatalf("unexpected content in go.mod:\n%s", tests.Diff(t, want, got))
950 t.Run("not tidied", func(t *testing.T) {
957 require hasdep.com v1.2.3
958 require random.com v1.2.3
960 example.com v1.2.3 h1:ihBTGWGjTU3V4ZJ9OmHITkU9WQ4lGdQkMjgyLFk0FaY=
961 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
962 hasdep.com v1.2.3 h1:00y+N5oD+SpKoqV1zP2VOPawcW65Zb9NebANY3GSzGI=
963 hasdep.com v1.2.3/go.mod h1:ePVZOlez+KZEOejfLPGL2n4i8qiAjrkhQZ4wcImqAes=
964 random.com v1.2.3 h1:PzYTykzqqH6+qU0dIgh9iPFbfb4Mm8zNBjWWreRKtx0=
965 random.com v1.2.3/go.mod h1:8EGj+8a4Hw1clAp8vbaeHAsKE4sbm536FP7nKyXO+qQ=
973 ).Run(t, mod, func(t *testing.T, env *Env) {
974 d := &protocol.PublishDiagnosticsParams{}
975 env.OpenFile("go.mod")
976 pos := env.RegexpSearch("go.mod", "require hasdep.com v1.2.3")
979 DiagnosticAt("go.mod", pos.Line, pos.Column),
980 ReadDiagnostics("go.mod", d),
983 const want = `module mod.com
987 require random.com v1.2.3
989 var diagnostics []protocol.Diagnostic
990 for _, d := range d.Diagnostics {
991 if d.Range.Start.Line != uint32(pos.Line) {
994 diagnostics = append(diagnostics, d)
996 env.ApplyQuickFixes("go.mod", diagnostics)
997 if got := env.Editor.BufferText("go.mod"); got != want {
998 t.Fatalf("unexpected content in go.mod:\n%s", tests.Diff(t, want, got))
1004 func TestSumUpdateQuickFix(t *testing.T) {
1005 testenv.NeedsGo1Point(t, 14)
1028 ProxyFiles(workspaceProxy),
1030 ).Run(t, mod, func(t *testing.T, env *Env) {
1031 env.OpenFile("go.mod")
1032 params := &protocol.PublishDiagnosticsParams{}
1035 env.GoSumDiagnostic("go.mod", "example.com"),
1036 ReadDiagnostics("go.mod", params),
1039 env.ApplyQuickFixes("go.mod", params.Diagnostics)
1040 const want = `example.com v1.2.3 h1:Yryq11hF02fEf2JlOS2eph+ICE2/ceevGV3C9dl5V/c=
1041 example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
1043 if got := env.ReadWorkspaceFile("go.sum"); got != want {
1044 t.Fatalf("unexpected go.sum contents:\n%s", tests.Diff(t, want, got))
1049 func TestDownloadDeps(t *testing.T) {
1050 testenv.NeedsGo1Point(t, 14)
1053 -- example.com@v1.2.3/go.mod --
1058 require random.org v1.2.3
1059 -- example.com@v1.2.3/blah/blah.go --
1062 import "random.org/bye"
1064 func SaySomething() {
1067 -- random.org@v1.2.3/go.mod --
1071 -- random.org@v1.2.3/bye/bye.go --
1099 ).Run(t, mod, func(t *testing.T, env *Env) {
1100 env.OpenFile("main.go")
1101 d := &protocol.PublishDiagnosticsParams{}
1103 env.DiagnosticAtRegexpWithMessage("main.go", `"example.com/blah"`, `could not import example.com/blah (no required module provides package "example.com/blah")`),
1104 ReadDiagnostics("main.go", d),
1106 env.ApplyQuickFixes("main.go", d.Diagnostics)
1108 EmptyDiagnostics("main.go"),
1109 NoDiagnostics("go.mod"),