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.
4
5package regtest
6
7import (
8	"io/ioutil"
9	"os"
10	"path/filepath"
11	"strings"
12	"testing"
13
14	"golang.org/x/tools/internal/lsp/protocol"
15	"golang.org/x/tools/internal/testenv"
16)
17
18// Tests golang/go#38815.
19func TestIssue38815(t *testing.T) {
20	const needs = `
21-- go.mod --
22module foo
23
24go 1.12
25-- a.go --
26package main
27func f() {}
28`
29	const ntest = `package main
30func TestZ(t *testing.T) {
31	f()
32}
33`
34	const want = `package main
35
36import "testing"
37
38func TestZ(t *testing.T) {
39	f()
40}
41`
42
43	// it was returning
44	// "package main\nimport \"testing\"\npackage main..."
45	runner.Run(t, needs, func(t *testing.T, env *Env) {
46		env.CreateBuffer("a_test.go", ntest)
47		env.SaveBuffer("a_test.go")
48		got := env.Editor.BufferText("a_test.go")
49		if want != got {
50			t.Errorf("got\n%q, wanted\n%q", got, want)
51		}
52	})
53}
54
55func TestVim1(t *testing.T) {
56	const vim1 = `package main
57
58import "fmt"
59
60var foo = 1
61var bar = 2
62
63func main() {
64	fmt.Printf("This is a test %v\n", foo)
65	fmt.Printf("This is another test %v\n", foo)
66	fmt.Printf("This is also a test %v\n", foo)
67}
68`
69
70	// The file remains unchanged, but if there are any CodeActions returned, they confuse vim.
71	// Therefore check for no CodeActions
72	runner.Run(t, "", func(t *testing.T, env *Env) {
73		env.CreateBuffer("main.go", vim1)
74		env.OrganizeImports("main.go")
75		actions := env.CodeAction("main.go")
76		if len(actions) > 0 {
77			got := env.Editor.BufferText("main.go")
78			t.Errorf("unexpected actions %#v", actions)
79			if got == vim1 {
80				t.Errorf("no changes")
81			} else {
82				t.Errorf("got\n%q", got)
83				t.Errorf("was\n%q", vim1)
84			}
85		}
86	})
87}
88
89func TestVim2(t *testing.T) {
90	const vim2 = `package main
91
92import (
93	"fmt"
94
95	"example.com/blah"
96
97	"rubbish.com/useless"
98)
99
100func main() {
101	fmt.Println(blah.Name, useless.Name)
102}
103`
104
105	runner.Run(t, "", func(t *testing.T, env *Env) {
106		env.CreateBuffer("main.go", vim2)
107		env.OrganizeImports("main.go")
108		actions := env.CodeAction("main.go")
109		if len(actions) > 0 {
110			t.Errorf("unexpected actions %#v", actions)
111		}
112	})
113}
114
115func TestGOMODCACHE(t *testing.T) {
116	const proxy = `
117-- example.com@v1.2.3/go.mod --
118module example.com
119
120go 1.12
121-- example.com@v1.2.3/x/x.go --
122package x
123
124const X = 1
125-- example.com@v1.2.3/y/y.go --
126package y
127
128const Y = 2
129`
130	const files = `
131-- go.mod --
132module mod.com
133
134go 1.12
135
136require example.com v1.2.3
137-- go.sum --
138example.com v1.2.3 h1:6vTQqzX+pnwngZF1+5gcO3ZEWmix1jJ/h+pWS8wUxK0=
139example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
140-- main.go --
141package main
142
143import "example.com/x"
144
145var _, _ = x.X, y.Y
146`
147	testenv.NeedsGo1Point(t, 15)
148
149	modcache, err := ioutil.TempDir("", "TestGOMODCACHE-modcache")
150	if err != nil {
151		t.Fatal(err)
152	}
153	defer os.RemoveAll(modcache)
154	editorConfig := EditorConfig{Env: map[string]string{"GOMODCACHE": modcache}}
155	withOptions(
156		editorConfig,
157		ProxyFiles(proxy),
158	).run(t, files, func(t *testing.T, env *Env) {
159		env.OpenFile("main.go")
160		env.Await(env.DiagnosticAtRegexp("main.go", `y.Y`))
161		env.SaveBuffer("main.go")
162		env.Await(EmptyDiagnostics("main.go"))
163		path, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `y.(Y)`))
164		if !strings.HasPrefix(path, filepath.ToSlash(modcache)) {
165			t.Errorf("found module dependency outside of GOMODCACHE: got %v, wanted subdir of %v", path, filepath.ToSlash(modcache))
166		}
167	})
168}
169
170// Tests golang/go#40685.
171func TestAcceptImportsQuickFixTestVariant(t *testing.T) {
172	const pkg = `
173-- go.mod --
174module mod.com
175
176go 1.12
177-- a/a.go --
178package a
179
180import (
181	"fmt"
182)
183
184func _() {
185	fmt.Println("")
186	os.Stat("")
187}
188-- a/a_test.go --
189package a
190
191import (
192	"os"
193	"testing"
194)
195
196func TestA(t *testing.T) {
197	os.Stat("")
198}
199`
200	run(t, pkg, func(t *testing.T, env *Env) {
201		env.OpenFile("a/a.go")
202		var d protocol.PublishDiagnosticsParams
203		env.Await(
204			OnceMet(
205				env.DiagnosticAtRegexp("a/a.go", "os.Stat"),
206				ReadDiagnostics("a/a.go", &d),
207			),
208		)
209		env.ApplyQuickFixes("a/a.go", d.Diagnostics)
210		env.Await(
211			EmptyDiagnostics("a/a.go"),
212		)
213	})
214}
215