1package regtest
2
3import (
4	"io/ioutil"
5	"os"
6	"path/filepath"
7	"strings"
8	"testing"
9
10	"golang.org/x/tools/internal/lsp/fake"
11	"golang.org/x/tools/internal/testenv"
12)
13
14func TestIssue38815(t *testing.T) {
15	const needs = `
16-- go.mod --
17module foo
18
19-- a.go --
20package main
21func f() {}
22`
23	const ntest = `package main
24func TestZ(t *testing.T) {
25	f()
26}
27`
28	const want = `package main
29
30import "testing"
31
32func TestZ(t *testing.T) {
33	f()
34}
35`
36
37	// it was returning
38	// "package main\nimport \"testing\"\npackage main..."
39	runner.Run(t, needs, func(t *testing.T, env *Env) {
40		env.CreateBuffer("a_test.go", ntest)
41		env.SaveBuffer("a_test.go")
42		got := env.Editor.BufferText("a_test.go")
43		if want != got {
44			t.Errorf("got\n%q, wanted\n%q", got, want)
45		}
46	})
47}
48
49func TestVim1(t *testing.T) {
50	const vim1 = `package main
51
52import "fmt"
53
54var foo = 1
55var bar = 2
56
57func main() {
58	fmt.Printf("This is a test %v\n", foo)
59	fmt.Printf("This is another test %v\n", foo)
60	fmt.Printf("This is also a test %v\n", foo)
61}
62`
63
64	// The file remains unchanged, but if there are any CodeActions returned, they confuse vim.
65	// Therefore check for no CodeActions
66	runner.Run(t, "", func(t *testing.T, env *Env) {
67		env.CreateBuffer("main.go", vim1)
68		env.OrganizeImports("main.go")
69		actions := env.CodeAction("main.go")
70		if len(actions) > 0 {
71			got := env.Editor.BufferText("main.go")
72			t.Errorf("unexpected actions %#v", actions)
73			if got == vim1 {
74				t.Errorf("no changes")
75			} else {
76				t.Errorf("got\n%q", got)
77				t.Errorf("was\n%q", vim1)
78			}
79		}
80	})
81}
82
83func TestVim2(t *testing.T) {
84	const vim2 = `package main
85
86import (
87	"fmt"
88
89	"example.com/blah"
90
91	"rubbish.com/useless"
92)
93
94func main() {
95	fmt.Println(blah.Name, useless.Name)
96}
97`
98
99	runner.Run(t, "", func(t *testing.T, env *Env) {
100		env.CreateBuffer("main.go", vim2)
101		env.OrganizeImports("main.go")
102		actions := env.CodeAction("main.go")
103		if len(actions) > 0 {
104			t.Errorf("unexpected actions %#v", actions)
105		}
106	})
107}
108
109func TestGOMODCACHE(t *testing.T) {
110	const proxy = `
111-- example.com@v1.2.3/go.mod --
112module example.com
113
114go 1.12
115-- example.com@v1.2.3/x/x.go --
116package x
117
118const X = 1
119-- example.com@v1.2.3/y/y.go --
120package y
121
122const Y = 2
123`
124	const files = `
125-- go.mod --
126module mod.com
127
128require example.com v1.2.3
129
130-- main.go --
131package main
132
133import "example.com/x"
134
135var _, _ = x.X, y.Y
136`
137	testenv.NeedsGo1Point(t, 15)
138
139	modcache, err := ioutil.TempDir("", "TestGOMODCACHE-modcache")
140	if err != nil {
141		t.Fatal(err)
142	}
143	defer os.RemoveAll(modcache)
144	editorConfig := fake.EditorConfig{Env: map[string]string{"GOMODCACHE": modcache}}
145	withOptions(
146		WithEditorConfig(editorConfig),
147		WithProxyFiles(proxy),
148	).run(t, files, func(t *testing.T, env *Env) {
149		env.OpenFile("main.go")
150		env.Await(env.DiagnosticAtRegexp("main.go", `y.Y`))
151		env.SaveBuffer("main.go")
152		env.Await(EmptyDiagnostics("main.go"))
153		path, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `y.(Y)`))
154		if !strings.HasPrefix(path, filepath.ToSlash(modcache)) {
155			t.Errorf("found module dependency outside of GOMODCACHE: got %v, wanted subdir of %v", path, filepath.ToSlash(modcache))
156		}
157	})
158}
159