service/dap: send 'continued' event on next/step/stepout requests (#2480)

* service/dap: send 'continued' event on next/step/stepout requests

Next/step/stepout requests assume that execution is only resumed
on the thread that was specified. We cannot resume execution on
only a single thread, so we need to send a continued event to let
the client know that all threads have resumed.

* update set breakpoints test with continued event
This commit is contained in:
Suzy Mueller 2021-05-17 23:34:27 -04:00 committed by GitHub
parent c10b222bad
commit 4e582fa553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 0 deletions

@ -1254,6 +1254,15 @@ func stoppedGoroutineID(state *api.DebuggerState) (id int) {
// due to an error, so the server is ready to receive new requests. // due to an error, so the server is ready to receive new requests.
func (s *Server) doStepCommand(command string, threadId int, asyncSetupDone chan struct{}) { func (s *Server) doStepCommand(command string, threadId int, asyncSetupDone chan struct{}) {
defer s.asyncCommandDone(asyncSetupDone) defer s.asyncCommandDone(asyncSetupDone)
// All of the threads will be continued by this request, so we need to send
// a continued event so the UI can properly reflect the current state.
s.send(&dap.ContinuedEvent{
Event: *newEvent("continued"),
Body: dap.ContinuedEventBody{
ThreadId: threadId,
AllThreadsContinued: true,
},
})
_, err := s.debugger.Command(&api.DebuggerCommand{Name: api.SwitchGoroutine, GoroutineID: threadId}, nil) _, err := s.debugger.Command(&api.DebuggerCommand{Name: api.SwitchGoroutine, GoroutineID: threadId}, nil)
if err != nil { if err != nil {
s.log.Errorf("Error switching goroutines while stepping: %v", err) s.log.Errorf("Error switching goroutines while stepping: %v", err)

@ -1701,6 +1701,7 @@ func TestVariablesLoading(t *testing.T) {
// step into another function // step into another function
client.StepInRequest(1) client.StepInRequest(1)
client.ExpectStepInResponse(t) client.ExpectStepInResponse(t)
client.ExpectContinuedEvent(t)
client.ExpectStoppedEvent(t) client.ExpectStoppedEvent(t)
handleStop(t, client, 1, "main.barfoo", 24) handleStop(t, client, 1, "main.barfoo", 24)
loadvars(1001 /*second frame here is same as topmost above*/) loadvars(1001 /*second frame here is same as topmost above*/)
@ -1748,6 +1749,7 @@ func TestGlobalScopeAndVariables(t *testing.T) {
// Step into pkg.AnotherMethod() // Step into pkg.AnotherMethod()
client.StepInRequest(1) client.StepInRequest(1)
client.ExpectStepInResponse(t) client.ExpectStepInResponse(t)
client.ExpectContinuedEvent(t)
client.ExpectStoppedEvent(t) client.ExpectStoppedEvent(t)
client.StackTraceRequest(1, 0, 20) client.StackTraceRequest(1, 0, 20)
@ -1981,6 +1983,7 @@ func TestSetBreakpointWhileRunning(t *testing.T) {
// We can set breakpoints while nexting // We can set breakpoints while nexting
client.NextRequest(1) client.NextRequest(1)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
client.SetBreakpointsRequest(fixture.Source, []int{15}) // [16,] => [15,] client.SetBreakpointsRequest(fixture.Source, []int{15}) // [16,] => [15,]
se, br := expectSetBreakpointsResponseAndStoppedEvent(t, client) se, br := expectSetBreakpointsResponseAndStoppedEvent(t, client)
if se.Body.Reason != "pause" || !se.Body.AllThreadsStopped || se.Body.ThreadId != 0 && se.Body.ThreadId != 1 { if se.Body.Reason != "pause" || !se.Body.AllThreadsStopped || se.Body.ThreadId != 0 && se.Body.ThreadId != 1 {
@ -2479,18 +2482,22 @@ func TestNextAndStep(t *testing.T) {
client.StepOutRequest(1) client.StepOutRequest(1)
client.ExpectStepOutResponse(t) client.ExpectStepOutResponse(t)
client.ExpectContinuedEvent(t)
expectStop("main.main", 18) expectStop("main.main", 18)
client.NextRequest(1) client.NextRequest(1)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
expectStop("main.main", 19) expectStop("main.main", 19)
client.StepInRequest(1) client.StepInRequest(1)
client.ExpectStepInResponse(t) client.ExpectStepInResponse(t)
client.ExpectContinuedEvent(t)
expectStop("main.inlineThis", 5) expectStop("main.inlineThis", 5)
client.NextRequest(-1000) client.NextRequest(-1000)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
if se := client.ExpectStoppedEvent(t); se.Body.Reason != "error" || se.Body.Text != "unknown goroutine -1000" { if se := client.ExpectStoppedEvent(t); se.Body.Reason != "error" || se.Body.Text != "unknown goroutine -1000" {
t.Errorf("got %#v, want Reaspon=\"error\", Text=\"unknown goroutine -1000\"", se) t.Errorf("got %#v, want Reaspon=\"error\", Text=\"unknown goroutine -1000\"", se)
} }
@ -2519,6 +2526,7 @@ func TestNextParked(t *testing.T) {
client.NextRequest(goroutineId) client.NextRequest(goroutineId)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
se := client.ExpectStoppedEvent(t) se := client.ExpectStoppedEvent(t)
if se.Body.ThreadId != goroutineId { if se.Body.ThreadId != goroutineId {
@ -2548,6 +2556,7 @@ func TestStepInParked(t *testing.T) {
client.StepInRequest(goroutineId) client.StepInRequest(goroutineId)
client.ExpectStepInResponse(t) client.ExpectStepInResponse(t)
client.ExpectContinuedEvent(t)
se := client.ExpectStoppedEvent(t) se := client.ExpectStoppedEvent(t)
if se.Body.ThreadId != goroutineId { if se.Body.ThreadId != goroutineId {
@ -2667,6 +2676,7 @@ func TestStepOutPreservesGoroutine(t *testing.T) {
} }
client.StepOutRequest(goroutineId) client.StepOutRequest(goroutineId)
client.ExpectStepOutResponse(t) client.ExpectStepOutResponse(t)
client.ExpectContinuedEvent(t)
switch e := client.ExpectMessage(t).(type) { switch e := client.ExpectMessage(t).(type) {
case *dap.StoppedEvent: case *dap.StoppedEvent:
@ -2720,18 +2730,22 @@ func TestBadAccess(t *testing.T) {
client.NextRequest(1) client.NextRequest(1)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
expectStoppedOnError("invalid memory address or nil pointer dereference") expectStoppedOnError("invalid memory address or nil pointer dereference")
client.NextRequest(1) client.NextRequest(1)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
expectStoppedOnError("next while nexting") expectStoppedOnError("next while nexting")
client.StepInRequest(1) client.StepInRequest(1)
client.ExpectStepInResponse(t) client.ExpectStepInResponse(t)
client.ExpectContinuedEvent(t)
expectStoppedOnError("next while nexting") expectStoppedOnError("next while nexting")
client.StepOutRequest(1) client.StepOutRequest(1)
client.ExpectStepOutResponse(t) client.ExpectStepOutResponse(t)
client.ExpectContinuedEvent(t)
expectStoppedOnError("next while nexting") expectStoppedOnError("next while nexting")
}, },
disconnect: true, disconnect: true,
@ -2792,6 +2806,7 @@ func TestPanicBreakpointOnNext(t *testing.T) {
client.NextRequest(1) client.NextRequest(1)
client.ExpectNextResponse(t) client.ExpectNextResponse(t)
client.ExpectContinuedEvent(t)
se := client.ExpectStoppedEvent(t) se := client.ExpectStoppedEvent(t)
if se.Body.ThreadId != 1 || se.Body.Reason != "exception" || se.Body.Description != "Paused on panic" { if se.Body.ThreadId != 1 || se.Body.Reason != "exception" || se.Body.Description != "Paused on panic" {