golang.org/x/tools/gopls@v0.15.3/internal/test/integration/misc/prompt_test.go (about) 1 // Copyright 2023 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 misc 6 7 import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "regexp" 12 "testing" 13 14 "golang.org/x/tools/gopls/internal/protocol" 15 "golang.org/x/tools/gopls/internal/protocol/command" 16 "golang.org/x/tools/gopls/internal/server" 17 . "golang.org/x/tools/gopls/internal/test/integration" 18 ) 19 20 // Test that gopls prompts for telemetry only when it is supposed to. 21 func TestTelemetryPrompt_Conditions(t *testing.T) { 22 const src = ` 23 -- go.mod -- 24 module mod.com 25 26 go 1.12 27 -- main.go -- 28 package main 29 30 func main() { 31 } 32 ` 33 34 for _, enabled := range []bool{true, false} { 35 t.Run(fmt.Sprintf("telemetryPrompt=%v", enabled), func(t *testing.T) { 36 for _, initialMode := range []string{"", "local", "off", "on"} { 37 t.Run(fmt.Sprintf("initial_mode=%s", initialMode), func(t *testing.T) { 38 modeFile := filepath.Join(t.TempDir(), "mode") 39 if initialMode != "" { 40 if err := os.WriteFile(modeFile, []byte(initialMode), 0666); err != nil { 41 t.Fatal(err) 42 } 43 } 44 WithOptions( 45 Modes(Default), // no need to run this in all modes 46 EnvVars{ 47 server.GoplsConfigDirEnvvar: t.TempDir(), 48 server.FakeTelemetryModefileEnvvar: modeFile, 49 }, 50 Settings{ 51 "telemetryPrompt": enabled, 52 }, 53 ).Run(t, src, func(t *testing.T, env *Env) { 54 wantPrompt := enabled && (initialMode == "" || initialMode == "local") 55 expectation := ShownMessageRequest(".*Would you like to enable Go telemetry?") 56 if !wantPrompt { 57 expectation = Not(expectation) 58 } 59 env.OnceMet( 60 CompletedWork(server.TelemetryPromptWorkTitle, 1, true), 61 expectation, 62 ) 63 }) 64 }) 65 } 66 }) 67 } 68 } 69 70 // Test that responding to the telemetry prompt results in the expected state. 71 func TestTelemetryPrompt_Response(t *testing.T) { 72 const src = ` 73 -- go.mod -- 74 module mod.com 75 76 go 1.12 77 -- main.go -- 78 package main 79 80 func main() { 81 } 82 ` 83 84 tests := []struct { 85 name string // subtest name 86 response string // response to choose for the telemetry dialog 87 wantMode string // resulting telemetry mode 88 wantMsg string // substring contained in the follow-up popup (if empty, no popup is expected) 89 }{ 90 {"yes", server.TelemetryYes, "on", "uploading is now enabled"}, 91 {"no", server.TelemetryNo, "", ""}, 92 {"empty", "", "", ""}, 93 } 94 for _, test := range tests { 95 t.Run(test.name, func(t *testing.T) { 96 modeFile := filepath.Join(t.TempDir(), "mode") 97 msgRE := regexp.MustCompile(".*Would you like to enable Go telemetry?") 98 respond := func(m *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) { 99 if msgRE.MatchString(m.Message) { 100 for _, item := range m.Actions { 101 if item.Title == test.response { 102 return &item, nil 103 } 104 } 105 if test.response != "" { 106 t.Errorf("action item %q not found", test.response) 107 } 108 } 109 return nil, nil 110 } 111 WithOptions( 112 Modes(Default), // no need to run this in all modes 113 EnvVars{ 114 server.GoplsConfigDirEnvvar: t.TempDir(), 115 server.FakeTelemetryModefileEnvvar: modeFile, 116 }, 117 Settings{ 118 "telemetryPrompt": true, 119 }, 120 MessageResponder(respond), 121 ).Run(t, src, func(t *testing.T, env *Env) { 122 var postConditions []Expectation 123 if test.wantMsg != "" { 124 postConditions = append(postConditions, ShownMessage(test.wantMsg)) 125 } 126 env.OnceMet( 127 CompletedWork(server.TelemetryPromptWorkTitle, 1, true), 128 postConditions..., 129 ) 130 gotMode := "" 131 if contents, err := os.ReadFile(modeFile); err == nil { 132 gotMode = string(contents) 133 } else if !os.IsNotExist(err) { 134 t.Fatal(err) 135 } 136 if gotMode != test.wantMode { 137 t.Errorf("after prompt, mode=%s, want %s", gotMode, test.wantMode) 138 } 139 }) 140 }) 141 } 142 } 143 144 // Test that we stop asking about telemetry after the user ignores the question 145 // 5 times. 146 func TestTelemetryPrompt_GivingUp(t *testing.T) { 147 const src = ` 148 -- go.mod -- 149 module mod.com 150 151 go 1.12 152 -- main.go -- 153 package main 154 155 func main() { 156 } 157 ` 158 159 // For this test, we want to share state across gopls sessions. 160 modeFile := filepath.Join(t.TempDir(), "mode") 161 configDir := t.TempDir() 162 163 const maxPrompts = 5 // internal prompt limit defined by gopls 164 165 for i := 0; i < maxPrompts+1; i++ { 166 WithOptions( 167 Modes(Default), // no need to run this in all modes 168 EnvVars{ 169 server.GoplsConfigDirEnvvar: configDir, 170 server.FakeTelemetryModefileEnvvar: modeFile, 171 }, 172 Settings{ 173 "telemetryPrompt": true, 174 }, 175 ).Run(t, src, func(t *testing.T, env *Env) { 176 wantPrompt := i < maxPrompts 177 expectation := ShownMessageRequest(".*Would you like to enable Go telemetry?") 178 if !wantPrompt { 179 expectation = Not(expectation) 180 } 181 env.OnceMet( 182 CompletedWork(server.TelemetryPromptWorkTitle, 1, true), 183 expectation, 184 ) 185 }) 186 } 187 } 188 189 // Test that gopls prompts for telemetry only when it is supposed to. 190 func TestTelemetryPrompt_Conditions2(t *testing.T) { 191 const src = ` 192 -- go.mod -- 193 module mod.com 194 195 go 1.12 196 -- main.go -- 197 package main 198 199 func main() { 200 } 201 ` 202 modeFile := filepath.Join(t.TempDir(), "mode") 203 WithOptions( 204 Modes(Default), // no need to run this in all modes 205 EnvVars{ 206 server.GoplsConfigDirEnvvar: t.TempDir(), 207 server.FakeTelemetryModefileEnvvar: modeFile, 208 }, 209 Settings{ 210 // off because we are testing 211 // if we can trigger the prompt with command. 212 "telemetryPrompt": false, 213 }, 214 ).Run(t, src, func(t *testing.T, env *Env) { 215 cmd, err := command.NewMaybePromptForTelemetryCommand("prompt") 216 if err != nil { 217 t.Fatal(err) 218 } 219 var result error 220 env.ExecuteCommand(&protocol.ExecuteCommandParams{ 221 Command: cmd.Command, 222 }, &result) 223 if result != nil { 224 t.Fatal(err) 225 } 226 expectation := ShownMessageRequest(".*Would you like to enable Go telemetry?") 227 env.OnceMet( 228 CompletedWork(server.TelemetryPromptWorkTitle, 2, true), 229 expectation, 230 ) 231 }) 232 }