Skip to content

Commit 015c0fc

Browse files
adonovangopherbot
authored andcommitted
gopls/internal/test/integration/web: move misc/webserver_test.go
This CL moves and splits the tests of web-based features into their own package. No substantive changes. Change-Id: Iea39256e0549edbaf698d8fd5b4c4cc18f3cc17e Reviewed-on: https://go-review.googlesource.com/c/tools/+/667116 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent d97a910 commit 015c0fc

File tree

5 files changed

+309
-246
lines changed

5 files changed

+309
-246
lines changed

gopls/internal/test/integration/misc/compileropt_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package misc
66

77
import (
8+
"fmt"
89
"runtime"
910
"testing"
1011

@@ -44,6 +45,7 @@ func main() {
4445
if err != nil {
4546
t.Fatal(err)
4647
}
48+
4749
params := &protocol.ExecuteCommandParams{
4850
Command: docAction.Command.Command,
4951
Arguments: docAction.Command.Arguments,
@@ -229,3 +231,13 @@ func cond[T any](cond bool, x, y T) T {
229231
return y
230232
}
231233
}
234+
235+
// codeActionByKind returns the first action of (exactly) the specified kind, or an error.
236+
func codeActionByKind(actions []protocol.CodeAction, kind protocol.CodeActionKind) (*protocol.CodeAction, error) {
237+
for _, act := range actions {
238+
if act.Kind == kind {
239+
return &act, nil
240+
}
241+
}
242+
return nil, fmt.Errorf("can't find action with kind %s, only %#v", kind, actions)
243+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright 2025 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+
5+
package web_test
6+
7+
import (
8+
"runtime"
9+
"testing"
10+
11+
"golang.org/x/tools/gopls/internal/protocol"
12+
"golang.org/x/tools/gopls/internal/protocol/command"
13+
"golang.org/x/tools/gopls/internal/settings"
14+
. "golang.org/x/tools/gopls/internal/test/integration"
15+
"golang.org/x/tools/internal/testenv"
16+
)
17+
18+
// TestAssembly is a basic test of the web-based assembly listing.
19+
func TestAssembly(t *testing.T) {
20+
testenv.NeedsGoCommand1Point(t, 22) // for up-to-date assembly listing
21+
22+
const files = `
23+
-- go.mod --
24+
module example.com
25+
26+
-- a/a.go --
27+
package a
28+
29+
func f(x int) int {
30+
println("hello")
31+
defer println("world")
32+
return x
33+
}
34+
35+
func g() {
36+
println("goodbye")
37+
}
38+
39+
var v = [...]int{
40+
f(123),
41+
f(456),
42+
}
43+
44+
func init() {
45+
f(789)
46+
}
47+
`
48+
Run(t, files, func(t *testing.T, env *Env) {
49+
env.OpenFile("a/a.go")
50+
51+
asmFor := func(pattern string) []byte {
52+
// Invoke the "Browse assembly" code action to start the server.
53+
loc := env.RegexpSearch("a/a.go", pattern)
54+
actions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)
55+
if err != nil {
56+
t.Fatalf("CodeAction: %v", err)
57+
}
58+
action, err := codeActionByKind(actions, settings.GoAssembly)
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
63+
// Execute the command.
64+
// Its side effect should be a single showDocument request.
65+
params := &protocol.ExecuteCommandParams{
66+
Command: action.Command.Command,
67+
Arguments: action.Command.Arguments,
68+
}
69+
var result command.DebuggingResult
70+
collectDocs := env.Awaiter.ListenToShownDocuments()
71+
env.ExecuteCommand(params, &result)
72+
doc := shownDocument(t, collectDocs(), "http:")
73+
if doc == nil {
74+
t.Fatalf("no showDocument call had 'file:' prefix")
75+
}
76+
t.Log("showDocument(package doc) URL:", doc.URI)
77+
78+
return get(t, doc.URI)
79+
}
80+
81+
// Get the report and do some minimal checks for sensible results.
82+
//
83+
// Use only portable instructions below! Remember that
84+
// this is a test of plumbing, not compilation, so
85+
// it's better to skip the tests, rather than refine
86+
// them, on any architecture that gives us trouble
87+
// (e.g. uses JAL for CALL, or BL<cc> for RET).
88+
// We conservatively test only on the two most popular
89+
// architectures.
90+
{
91+
report := asmFor("println")
92+
checkMatch(t, true, report, `TEXT.*example.com/a.f`)
93+
switch runtime.GOARCH {
94+
case "amd64", "arm64":
95+
checkMatch(t, true, report, `CALL runtime.printlock`)
96+
checkMatch(t, true, report, `CALL runtime.printstring`)
97+
checkMatch(t, true, report, `CALL runtime.printunlock`)
98+
checkMatch(t, true, report, `CALL example.com/a.f.deferwrap`)
99+
checkMatch(t, true, report, `RET`)
100+
checkMatch(t, true, report, `CALL runtime.morestack_noctxt`)
101+
}
102+
103+
// Nested functions are also shown.
104+
//
105+
// The condition here was relaxed to unblock go.dev/cl/639515.
106+
checkMatch(t, true, report, `example.com/a.f.deferwrap`)
107+
108+
// But other functions are not.
109+
checkMatch(t, false, report, `TEXT.*example.com/a.g`)
110+
}
111+
112+
// Check that code in a package-level var initializer is found too.
113+
{
114+
report := asmFor(`f\(123\)`)
115+
switch runtime.GOARCH {
116+
case "amd64", "arm64":
117+
checkMatch(t, true, report, `TEXT.*example.com/a.init`)
118+
checkMatch(t, true, report, `MOV.? \$123`)
119+
checkMatch(t, true, report, `MOV.? \$456`)
120+
checkMatch(t, true, report, `CALL example.com/a.f`)
121+
}
122+
}
123+
124+
// And code in a source-level init function.
125+
{
126+
report := asmFor(`f\(789\)`)
127+
switch runtime.GOARCH {
128+
case "amd64", "arm64":
129+
checkMatch(t, true, report, `TEXT.*example.com/a.init`)
130+
checkMatch(t, true, report, `MOV.? \$789`)
131+
checkMatch(t, true, report, `CALL example.com/a.f`)
132+
}
133+
}
134+
})
135+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2025 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+
5+
package web_test
6+
7+
import (
8+
"testing"
9+
10+
"golang.org/x/tools/gopls/internal/protocol"
11+
"golang.org/x/tools/gopls/internal/protocol/command"
12+
"golang.org/x/tools/gopls/internal/settings"
13+
. "golang.org/x/tools/gopls/internal/test/integration"
14+
)
15+
16+
// TestFreeSymbols is a basic test of interaction with the "free symbols" web report.
17+
func TestFreeSymbols(t *testing.T) {
18+
const files = `
19+
-- go.mod --
20+
module example.com
21+
22+
-- a/a.go --
23+
package a
24+
25+
import "fmt"
26+
import "bytes"
27+
28+
func f(buf bytes.Buffer, greeting string) {
29+
/* « */
30+
fmt.Fprintf(&buf, "%s", greeting)
31+
buf.WriteString(fmt.Sprint("foo"))
32+
buf.WriteByte(0)
33+
/* » */
34+
buf.Write(nil)
35+
}
36+
`
37+
Run(t, files, func(t *testing.T, env *Env) {
38+
env.OpenFile("a/a.go")
39+
40+
// Invoke the "Browse free symbols" code
41+
// action to start the server.
42+
loc := env.RegexpSearch("a/a.go", "«((?:.|\n)*)»")
43+
actions, err := env.Editor.CodeAction(env.Ctx, loc, nil, protocol.CodeActionUnknownTrigger)
44+
if err != nil {
45+
t.Fatalf("CodeAction: %v", err)
46+
}
47+
action, err := codeActionByKind(actions, settings.GoFreeSymbols)
48+
if err != nil {
49+
t.Fatal(err)
50+
}
51+
52+
// Execute the command.
53+
// Its side effect should be a single showDocument request.
54+
params := &protocol.ExecuteCommandParams{
55+
Command: action.Command.Command,
56+
Arguments: action.Command.Arguments,
57+
}
58+
var result command.DebuggingResult
59+
collectDocs := env.Awaiter.ListenToShownDocuments()
60+
env.ExecuteCommand(params, &result)
61+
doc := shownDocument(t, collectDocs(), "http:")
62+
if doc == nil {
63+
t.Fatalf("no showDocument call had 'file:' prefix")
64+
}
65+
t.Log("showDocument(package doc) URL:", doc.URI)
66+
67+
// Get the report and do some minimal checks for sensible results.
68+
report := get(t, doc.URI)
69+
checkMatch(t, true, report, `<li>import "<a .*'>fmt</a>" // for Fprintf, Sprint</li>`)
70+
checkMatch(t, true, report, `<li>var <a .*>buf</a> bytes.Buffer</li>`)
71+
checkMatch(t, true, report, `<li>func <a .*>WriteByte</a> func\(c byte\) error</li>`)
72+
checkMatch(t, true, report, `<li>func <a .*>WriteString</a> func\(s string\) \(n int, err error\)</li>`)
73+
checkMatch(t, false, report, `<li>func <a .*>Write</a>`) // not in selection
74+
checkMatch(t, true, report, `<li>var <a .*>greeting</a> string</li>`)
75+
})
76+
}

0 commit comments

Comments
 (0)