service/dap: fix TestNextParked (#2784)
Co-authored-by: Polina Sokolova <polinasok@users.noreply.github.com>
This commit is contained in:
parent
f34a1e6a5e
commit
88dca53e5c
@ -153,6 +153,11 @@ func (c *Client) ExpectOutputEventProcessExited(t *testing.T, status int) *dap.O
|
|||||||
return c.ExpectOutputEventRegex(t, fmt.Sprintf(ProcessExited, fmt.Sprintf("%d", status)))
|
return c.ExpectOutputEventRegex(t, fmt.Sprintf(ProcessExited, fmt.Sprintf("%d", status)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) ExpectOutputEventProcessExitedAnyStatus(t *testing.T) *dap.OutputEvent {
|
||||||
|
t.Helper()
|
||||||
|
return c.ExpectOutputEventRegex(t, fmt.Sprintf(ProcessExited, `-?\d+`))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) ExpectOutputEventDetaching(t *testing.T) *dap.OutputEvent {
|
func (c *Client) ExpectOutputEventDetaching(t *testing.T) *dap.OutputEvent {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return c.ExpectOutputEventRegex(t, `Detaching\n`)
|
return c.ExpectOutputEventRegex(t, `Detaching\n`)
|
||||||
|
@ -4426,6 +4426,8 @@ func getPC(t *testing.T, client *daptest.Client, threadId int) (uint64, error) {
|
|||||||
return strconv.ParseUint(st.Body.StackFrames[0].InstructionPointerReference, 0, 64)
|
return strconv.ParseUint(st.Body.StackFrames[0].InstructionPointerReference, 0, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestNextParked tests that we can switched selected goroutine to a parked one
|
||||||
|
// and perform next operation on it.
|
||||||
func TestNextParked(t *testing.T) {
|
func TestNextParked(t *testing.T) {
|
||||||
if runtime.GOOS == "freebsd" {
|
if runtime.GOOS == "freebsd" {
|
||||||
t.SkipNow()
|
t.SkipNow()
|
||||||
@ -4440,40 +4442,48 @@ func TestNextParked(t *testing.T) {
|
|||||||
fixture.Source, []int{15},
|
fixture.Source, []int{15},
|
||||||
[]onBreakpoint{{ // Stop at line 15
|
[]onBreakpoint{{ // Stop at line 15
|
||||||
execute: func() {
|
execute: func() {
|
||||||
if goroutineId := testStepParkedHelper(t, client, fixture); goroutineId >= 0 {
|
if parkedGoid := testNextParkedHelper(t, client, fixture); parkedGoid >= 0 {
|
||||||
|
client.NextRequest(parkedGoid)
|
||||||
client.NextRequest(goroutineId)
|
|
||||||
client.ExpectNextResponse(t)
|
client.ExpectNextResponse(t)
|
||||||
|
|
||||||
se := client.ExpectStoppedEvent(t)
|
se := client.ExpectStoppedEvent(t)
|
||||||
if se.Body.ThreadId != goroutineId {
|
if se.Body.ThreadId != parkedGoid {
|
||||||
t.Fatalf("Next did not continue on the selected goroutine, expected %d got %d", goroutineId, se.Body.ThreadId)
|
t.Fatalf("Next did not continue on the newly selected goroutine, expected %d got %d", parkedGoid, se.Body.ThreadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Let the test harness continue to process termination
|
||||||
|
// if it hasn't gotten there already.
|
||||||
disconnect: false,
|
disconnect: false,
|
||||||
}})
|
}})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testStepParkedHelper(t *testing.T, client *daptest.Client, fixture protest.Fixture) int {
|
// Finds a goroutine other than the selected one that is parked inside of main.sayhi and therefore
|
||||||
|
// still has a line to execute if resumed with next.
|
||||||
|
func testNextParkedHelper(t *testing.T, client *daptest.Client, fixture protest.Fixture) int {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Set a breakpoint at main.sayHi
|
// Set a breakpoint at main.sayhi
|
||||||
client.SetBreakpointsRequest(fixture.Source, []int{8})
|
client.SetBreakpointsRequest(fixture.Source, []int{8})
|
||||||
client.ExpectSetBreakpointsResponse(t)
|
client.ExpectSetBreakpointsResponse(t)
|
||||||
|
|
||||||
var goroutineId = -1
|
var parkedGoid = -1
|
||||||
for goroutineId < 0 {
|
for parkedGoid < 0 {
|
||||||
client.ContinueRequest(1)
|
client.ContinueRequest(1)
|
||||||
contResp := client.ExpectMessage(t)
|
client.ExpectContinueResponse(t)
|
||||||
switch contResp.(type) {
|
event := client.ExpectMessage(t)
|
||||||
case *dap.ContinueResponse:
|
switch event.(type) {
|
||||||
|
case *dap.StoppedEvent:
|
||||||
// ok
|
// ok
|
||||||
case *dap.TerminatedEvent:
|
case *dap.TerminatedEvent:
|
||||||
|
// This is very unlikely to happen. But in theory if all sayhi
|
||||||
|
// gouritines are run serially, there will never be a second parked
|
||||||
|
// sayhi goroutine when another breaks and we will keep trying
|
||||||
|
// until process termination.
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
se := client.ExpectStoppedEvent(t)
|
se := event.(*dap.StoppedEvent)
|
||||||
|
|
||||||
client.ThreadsRequest()
|
client.ThreadsRequest()
|
||||||
threads := client.ExpectThreadsResponse(t)
|
threads := client.ExpectThreadsResponse(t)
|
||||||
@ -4484,9 +4494,7 @@ func testStepParkedHelper(t *testing.T, client *daptest.Client, fixture protest.
|
|||||||
// 2. hasn't called wg.Done yet
|
// 2. hasn't called wg.Done yet
|
||||||
// 3. is not the currently selected goroutine
|
// 3. is not the currently selected goroutine
|
||||||
for _, g := range threads.Body.Threads {
|
for _, g := range threads.Body.Threads {
|
||||||
// We do not need to check the thread that the program
|
if g.Id == se.Body.ThreadId { // Skip selected goroutine
|
||||||
// is currently stopped on.
|
|
||||||
if g.Id == se.Body.ThreadId {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
client.StackTraceRequest(g.Id, 0, 5)
|
client.StackTraceRequest(g.Id, 0, 5)
|
||||||
@ -4494,11 +4502,11 @@ func testStepParkedHelper(t *testing.T, client *daptest.Client, fixture protest.
|
|||||||
for _, frame := range frames.Body.StackFrames {
|
for _, frame := range frames.Body.StackFrames {
|
||||||
// line 11 is the line where wg.Done is called
|
// line 11 is the line where wg.Done is called
|
||||||
if frame.Name == "main.sayhi" && frame.Line < 11 {
|
if frame.Name == "main.sayhi" && frame.Line < 11 {
|
||||||
goroutineId = g.Id
|
parkedGoid = g.Id
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if goroutineId >= 0 {
|
if parkedGoid >= 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4507,8 +4515,7 @@ func testStepParkedHelper(t *testing.T, client *daptest.Client, fixture protest.
|
|||||||
// Clear all breakpoints.
|
// Clear all breakpoints.
|
||||||
client.SetBreakpointsRequest(fixture.Source, []int{})
|
client.SetBreakpointsRequest(fixture.Source, []int{})
|
||||||
client.ExpectSetBreakpointsResponse(t)
|
client.ExpectSetBreakpointsResponse(t)
|
||||||
|
return parkedGoid
|
||||||
return goroutineId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestStepOutPreservesGoroutine is inspired by proc_test.TestStepOutPreservesGoroutine
|
// TestStepOutPreservesGoroutine is inspired by proc_test.TestStepOutPreservesGoroutine
|
||||||
@ -4989,7 +4996,7 @@ func runDebugSessionWithBPs(t *testing.T, client *daptest.Client, cmd string, cm
|
|||||||
if onBP.disconnect {
|
if onBP.disconnect {
|
||||||
client.DisconnectRequestWithKillOption(true)
|
client.DisconnectRequestWithKillOption(true)
|
||||||
if onBP.terminated {
|
if onBP.terminated {
|
||||||
client.ExpectOutputEventProcessExited(t, 0)
|
client.ExpectOutputEventProcessExitedAnyStatus(t)
|
||||||
client.ExpectOutputEventDetaching(t)
|
client.ExpectOutputEventDetaching(t)
|
||||||
} else {
|
} else {
|
||||||
client.ExpectOutputEventDetachingKill(t)
|
client.ExpectOutputEventDetachingKill(t)
|
||||||
@ -5008,7 +5015,7 @@ func runDebugSessionWithBPs(t *testing.T, client *daptest.Client, cmd string, cm
|
|||||||
}
|
}
|
||||||
client.DisconnectRequestWithKillOption(true)
|
client.DisconnectRequestWithKillOption(true)
|
||||||
if cmd == "launch" {
|
if cmd == "launch" {
|
||||||
client.ExpectOutputEventProcessExited(t, 0)
|
client.ExpectOutputEventProcessExitedAnyStatus(t)
|
||||||
client.ExpectOutputEventDetaching(t)
|
client.ExpectOutputEventDetaching(t)
|
||||||
} else if cmd == "attach" {
|
} else if cmd == "attach" {
|
||||||
client.ExpectOutputEventDetachingKill(t)
|
client.ExpectOutputEventDetachingKill(t)
|
||||||
|
Loading…
Reference in New Issue
Block a user