blob: 8a781bd424a2c7fe46a27845103206cea173e9db [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package misc
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
. "golang.org/x/tools/gopls/internal/lsp/regtest"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/internal/testenv"
)
// Tests golang/go#38815.
func TestIssue38815(t *testing.T) {
const needs = `
-- go.mod --
module foo
go 1.12
-- a.go --
package main
func f() {}
`
const ntest = `package main
func TestZ(t *testing.T) {
f()
}
`
const want = `package main
import "testing"
func TestZ(t *testing.T) {
f()
}
`
// it was returning
// "package main\nimport \"testing\"\npackage main..."
Run(t, needs, func(t *testing.T, env *Env) {
env.CreateBuffer("a_test.go", ntest)
env.SaveBuffer("a_test.go")
got := env.Editor.BufferText("a_test.go")
if want != got {
t.Errorf("got\n%q, wanted\n%q", got, want)
}
})
}
func TestVim1(t *testing.T) {
const vim1 = `package main
import "fmt"
var foo = 1
var bar = 2
func main() {
fmt.Printf("This is a test %v\n", foo)
fmt.Printf("This is another test %v\n", foo)
fmt.Printf("This is also a test %v\n", foo)
}
`
// The file remains unchanged, but if there are any CodeActions returned, they confuse vim.
// Therefore check for no CodeActions
Run(t, "", func(t *testing.T, env *Env) {
env.CreateBuffer("main.go", vim1)
env.OrganizeImports("main.go")
actions := env.CodeAction("main.go", nil)
if len(actions) > 0 {
got := env.Editor.BufferText("main.go")
t.Errorf("unexpected actions %#v", actions)
if got == vim1 {
t.Errorf("no changes")
} else {
t.Errorf("got\n%q", got)
t.Errorf("was\n%q", vim1)
}
}
})
}
func TestVim2(t *testing.T) {
const vim2 = `package main
import (
"fmt"
"example.com/blah"
"rubbish.com/useless"
)
func main() {
fmt.Println(blah.Name, useless.Name)
}
`
Run(t, "", func(t *testing.T, env *Env) {
env.CreateBuffer("main.go", vim2)
env.OrganizeImports("main.go")
actions := env.CodeAction("main.go", nil)
if len(actions) > 0 {
t.Errorf("unexpected actions %#v", actions)
}
})
}
func TestGOMODCACHE(t *testing.T) {
const proxy = `
-- example.com@v1.2.3/go.mod --
module example.com
go 1.12
-- example.com@v1.2.3/x/x.go --
package x
const X = 1
-- example.com@v1.2.3/y/y.go --
package y
const Y = 2
`
const files = `
-- go.mod --
module mod.com
go 1.12
require example.com v1.2.3
-- go.sum --
example.com v1.2.3 h1:6vTQqzX+pnwngZF1+5gcO3ZEWmix1jJ/h+pWS8wUxK0=
example.com v1.2.3/go.mod h1:Y2Rc5rVWjWur0h3pd9aEvK5Pof8YKDANh9gHA2Maujo=
-- main.go --
package main
import "example.com/x"
var _, _ = x.X, y.Y
`
testenv.NeedsGo1Point(t, 15)
modcache, err := ioutil.TempDir("", "TestGOMODCACHE-modcache")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(modcache)
WithOptions(
EnvVars{"GOMODCACHE": modcache},
ProxyFiles(proxy),
).Run(t, files, func(t *testing.T, env *Env) {
env.OpenFile("main.go")
env.Await(env.DiagnosticAtRegexp("main.go", `y.Y`))
env.SaveBuffer("main.go")
env.Await(EmptyDiagnostics("main.go"))
path, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `y.(Y)`))
if !strings.HasPrefix(path, filepath.ToSlash(modcache)) {
t.Errorf("found module dependency outside of GOMODCACHE: got %v, wanted subdir of %v", path, filepath.ToSlash(modcache))
}
})
}
// Tests golang/go#40685.
func TestAcceptImportsQuickFixTestVariant(t *testing.T) {
const pkg = `
-- go.mod --
module mod.com
go 1.12
-- a/a.go --
package a
import (
"fmt"
)
func _() {
fmt.Println("")
os.Stat("")
}
-- a/a_test.go --
package a
import (
"os"
"testing"
)
func TestA(t *testing.T) {
os.Stat("")
}
`
Run(t, pkg, func(t *testing.T, env *Env) {
env.OpenFile("a/a.go")
var d protocol.PublishDiagnosticsParams
env.Await(
OnceMet(
env.DiagnosticAtRegexp("a/a.go", "os.Stat"),
ReadDiagnostics("a/a.go", &d),
),
)
env.ApplyQuickFixes("a/a.go", d.Diagnostics)
env.Await(
EmptyDiagnostics("a/a.go"),
)
})
}
// Test for golang/go#52784
func TestGoWorkImports(t *testing.T) {
testenv.NeedsGo1Point(t, 18)
const pkg = `
-- go.work --
go 1.19
use (
./caller
./mod
)
-- caller/go.mod --
module caller.com
go 1.18
require mod.com v0.0.0
replace mod.com => ../mod
-- caller/caller.go --
package main
func main() {
a.Test()
}
-- mod/go.mod --
module mod.com
go 1.18
-- mod/a/a.go --
package a
func Test() {
}
`
Run(t, pkg, func(t *testing.T, env *Env) {
env.OpenFile("caller/caller.go")
env.Await(env.DiagnosticAtRegexp("caller/caller.go", "a.Test"))
// Saving caller.go should trigger goimports, which should find a.Test in
// the mod.com module, thanks to the go.work file.
env.SaveBuffer("caller/caller.go")
env.Await(EmptyDiagnostics("caller/caller.go"))
})
}