mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 01:27:16 +08:00
dap: remote attach must not use terminateDebuggee in single-client launch mode (#2995)
This commit is contained in:
@ -77,6 +77,9 @@ func startDAPServerWithClient(t *testing.T, serverStopped chan struct{}) *daptes
|
||||
return client
|
||||
}
|
||||
|
||||
// Starts an empty server and a stripped down config just to establish a client connection.
|
||||
// To mock a server created by dap.NewServer(config) or serving dap.NewSession(conn, config, debugger)
|
||||
// set those arg fields manually after the server creation.
|
||||
func startDAPServer(t *testing.T, serverStopped chan struct{}) (server *Server, forceStop chan struct{}) {
|
||||
// Start the DAP server.
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
@ -6516,6 +6519,18 @@ func launchDebuggerWithTargetHalted(t *testing.T, fixture string) (*protest.Fixt
|
||||
return &fixbin, dbg
|
||||
}
|
||||
|
||||
func attachDebuggerWithTargetHalted(t *testing.T, fixture string) (*exec.Cmd, *debugger.Debugger) {
|
||||
t.Helper()
|
||||
fixbin := protest.BuildFixture(fixture, protest.AllNonOptimized)
|
||||
cmd := execFixture(t, fixbin)
|
||||
cfg := service.Config{Debugger: debugger.Config{Backend: "default", AttachPid: cmd.Process.Pid}}
|
||||
dbg, err := debugger.New(&cfg.Debugger, nil) // debugger halts process on entry
|
||||
if err != nil {
|
||||
t.Fatal("failed to start debugger:", err)
|
||||
}
|
||||
return cmd, dbg
|
||||
}
|
||||
|
||||
// runTestWithDebugger starts the server and sets its debugger, initializes a debug session,
|
||||
// runs test, then disconnects. Expects no running async handler at the end of test() (either
|
||||
// process is halted or debug session never launched.)
|
||||
@ -6528,6 +6543,10 @@ func runTestWithDebugger(t *testing.T, dbg *debugger.Debugger, test func(c *dapt
|
||||
if server.session == nil {
|
||||
t.Fatal("DAP session is not ready")
|
||||
}
|
||||
// Mock dap.NewSession arguments, so
|
||||
// this dap.Server can be used as a proxy for
|
||||
// rpccommon.Server running dap.Session.
|
||||
server.session.config.Debugger.AttachPid = dbg.AttachPid()
|
||||
server.session.debugger = dbg
|
||||
server.sessionMu.Unlock()
|
||||
defer client.Close()
|
||||
@ -6537,7 +6556,7 @@ func runTestWithDebugger(t *testing.T, dbg *debugger.Debugger, test func(c *dapt
|
||||
test(client)
|
||||
|
||||
client.DisconnectRequest()
|
||||
if server.config.Debugger.AttachPid == 0 { // launched target
|
||||
if dbg.AttachPid() == 0 { // launched target
|
||||
client.ExpectOutputEventDetachingKill(t)
|
||||
} else { // attached to target
|
||||
client.ExpectOutputEventDetachingNoKill(t)
|
||||
@ -6548,9 +6567,24 @@ func runTestWithDebugger(t *testing.T, dbg *debugger.Debugger, test func(c *dapt
|
||||
<-serverStopped
|
||||
}
|
||||
|
||||
func TestAttachRemoteToHaltedTargetStopOnEntry(t *testing.T) {
|
||||
func TestAttachRemoteToDlvLaunchHaltedStopOnEntry(t *testing.T) {
|
||||
// Halted + stop on entry
|
||||
_, dbg := launchDebuggerWithTargetHalted(t, "increment")
|
||||
runTestWithDebugger(t, dbg, func(client *daptest.Client) {
|
||||
client.AttachRequest(map[string]interface{}{"mode": "remote", "stopOnEntry": true})
|
||||
client.ExpectInitializedEvent(t)
|
||||
client.ExpectAttachResponse(t)
|
||||
client.ConfigurationDoneRequest()
|
||||
client.ExpectStoppedEvent(t)
|
||||
client.ExpectConfigurationDoneResponse(t)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAttachRemoteToDlvAttachHaltedStopOnEntry(t *testing.T) {
|
||||
if runtime.GOOS == "freebsd" || runtime.GOOS == "windows" {
|
||||
t.SkipNow()
|
||||
}
|
||||
cmd, dbg := attachDebuggerWithTargetHalted(t, "http_server")
|
||||
runTestWithDebugger(t, dbg, func(client *daptest.Client) {
|
||||
client.AttachRequest(map[string]interface{}{"mode": "remote", "stopOnEntry": true})
|
||||
client.ExpectCapabilitiesEventSupportTerminateDebuggee(t)
|
||||
@ -6560,6 +6594,7 @@ func TestAttachRemoteToHaltedTargetStopOnEntry(t *testing.T) {
|
||||
client.ExpectStoppedEvent(t)
|
||||
client.ExpectConfigurationDoneResponse(t)
|
||||
})
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
|
||||
func TestAttachRemoteToHaltedTargetContinueOnEntry(t *testing.T) {
|
||||
@ -6567,7 +6602,6 @@ func TestAttachRemoteToHaltedTargetContinueOnEntry(t *testing.T) {
|
||||
_, dbg := launchDebuggerWithTargetHalted(t, "http_server")
|
||||
runTestWithDebugger(t, dbg, func(client *daptest.Client) {
|
||||
client.AttachRequest(map[string]interface{}{"mode": "remote", "stopOnEntry": false})
|
||||
client.ExpectCapabilitiesEventSupportTerminateDebuggee(t)
|
||||
client.ExpectInitializedEvent(t)
|
||||
client.ExpectAttachResponse(t)
|
||||
client.ConfigurationDoneRequest()
|
||||
@ -6584,7 +6618,6 @@ func TestAttachRemoteToRunningTargetStopOnEntry(t *testing.T) {
|
||||
fixture, dbg := launchDebuggerWithTargetRunning(t, "loopprog")
|
||||
runTestWithDebugger(t, dbg, func(client *daptest.Client) {
|
||||
client.AttachRequest(map[string]interface{}{"mode": "remote", "stopOnEntry": true})
|
||||
client.ExpectCapabilitiesEventSupportTerminateDebuggee(t)
|
||||
client.ExpectInitializedEvent(t)
|
||||
client.ExpectAttachResponse(t)
|
||||
// Target is halted here
|
||||
@ -6604,7 +6637,6 @@ func TestAttachRemoteToRunningTargetContinueOnEntry(t *testing.T) {
|
||||
fixture, dbg := launchDebuggerWithTargetRunning(t, "loopprog")
|
||||
runTestWithDebugger(t, dbg, func(client *daptest.Client) {
|
||||
client.AttachRequest(map[string]interface{}{"mode": "remote", "stopOnEntry": false})
|
||||
client.ExpectCapabilitiesEventSupportTerminateDebuggee(t)
|
||||
client.ExpectInitializedEvent(t)
|
||||
client.ExpectAttachResponse(t)
|
||||
// Target is halted here
|
||||
@ -6643,8 +6675,8 @@ func TestAttachRemoteMultiClientDisconnect(t *testing.T) {
|
||||
if server.session == nil {
|
||||
t.Fatal("dap session is not ready")
|
||||
}
|
||||
// DAP server doesn't support accept-multiclient, but we can use this
|
||||
// hack to test the inner connection logic that can be used by a server that does.
|
||||
// A dap.Server doesn't support accept-multiclient, but we can use this
|
||||
// hack to test the inner connection logic that is used by a server that does.
|
||||
server.session.config.AcceptMulti = true
|
||||
_, server.session.debugger = launchDebuggerWithTargetHalted(t, "increment")
|
||||
server.sessionMu.Unlock()
|
||||
@ -6672,7 +6704,7 @@ func TestAttachRemoteMultiClientDisconnect(t *testing.T) {
|
||||
if tc.expect == closingClientSessionOnly {
|
||||
// At this point a multi-client server is still running.
|
||||
verifySessionStopped(t, server.session)
|
||||
// Since it is a dap server, it cannot accept another client, so the only
|
||||
// Since it is a dap.Server, it cannot accept another client, so the only
|
||||
// way to take down the server is to force-kill it.
|
||||
close(forceStop)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user