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