Skip to content

Commit

Permalink
Add support for "pause" request
Browse files Browse the repository at this point in the history
Summary: We implement the "pause" request. The request takes a threadId, but we ignore it and just pause every process (similar to what we do with "continue").

Reviewed By: thizanne

Differential Revision: D68790443

fbshipit-source-id: 4e0f613b76ac6859167515812dc6d25ecb200f54
  • Loading branch information
jcpetruzza authored and facebook-github-bot committed Jan 29, 2025
1 parent 066cc0a commit 285c16f
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 14 deletions.
2 changes: 2 additions & 0 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
{ct, "mkdir -p _build/test/lib/edb/test/edb_main_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_main_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_scopes_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_pause_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_pause_SUITE_data"}
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_scopes_SUITE_data"},
{ct, "mkdir -p _build/test/lib/edb/test/edb_dap_session_SUITE_data"},
{ct, "cp _build/default/bin/edb _build/test/lib/edb/test/edb_dap_session_SUITE_data"},
Expand Down
14 changes: 14 additions & 0 deletions src/edb_dap.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
message/0,
next_request_arguments/0,
next_response/0,
pause_request_arguments/0,
pause_response/0,
protocol_message_type/0,
protocol_message/0,
request/0,
Expand Down Expand Up @@ -390,6 +392,18 @@ build_error_response(Id, Format) ->
presentationHint => binary()
}.

%%% Pause
%%% https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Pause
-type pause_request_arguments() :: #{
% Pause execution for this thread.
threadId := thread_id()
}.
-type pause_response() :: #{
success := boolean(),
message => binary(),
body := #{}
}.

%%% Continue
%%% https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Continue
-type continue_request_arguments() :: #{
Expand Down
9 changes: 8 additions & 1 deletion src/edb_dap_events.erl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,14 @@ stopped(_State, {step, Pid}) ->
threadId => edb_dap_id_mappings:pid_to_thread_id(Pid),
allThreadsStopped => true
},
#{actions => [{event, <<"stopped">>, StoppedEventBody}]};
#{actions => [{event, ~"stopped", StoppedEventBody}]};
stopped(_State, pause) ->
StoppedEventBody = #{
reason => ~"pause",
preserveFocusHint => true,
allThreadsStopped => true
},
#{actions => [{event, ~"stopped", StoppedEventBody}]};
stopped(_State, Event) ->
?LOG_WARNING("Skipping stopped event: ~p", [Event]),
#{}.
8 changes: 7 additions & 1 deletion src/edb_dap_requests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
-include_lib("kernel/include/logger.hrl").

-export([initialize/2, launch/2, disconnect/2]).
-export([set_breakpoints/2, continue/2, next/2, step_out/2]).
-export([set_breakpoints/2, pause/2, continue/2, next/2, step_out/2]).
-export([threads/2, stack_trace/2, scopes/2, variables/2]).

-type reaction(T) :: #{
Expand Down Expand Up @@ -387,6 +387,12 @@ stack_frames(State, ThreadId) ->
[]
end.

-spec pause(edb_dap_state:t(), edb_dap:pause_request_arguments()) ->
reaction(edb_dap:pause_response()).
pause(_State, _Args) ->
ok = edb:pause(),
#{response => #{success => true, body => #{}}}.

-spec continue(edb_dap_state:t(), edb_dap:continue_request_arguments()) ->
reaction(edb_dap:continue_response()).
continue(_State, _Args) ->
Expand Down
26 changes: 14 additions & 12 deletions src/edb_dap_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -281,30 +281,32 @@ dispatch_event(Event, _DAPState) ->
%% @doc Explicit mapping to avoid the risk of atom exhaustion
-spec method_to_atom(binary()) -> atom().
% Requests
method_to_atom(<<"initialize">>) ->
method_to_atom(~"initialize") ->
initialize;
method_to_atom(<<"launch">>) ->
method_to_atom(~"launch") ->
launch;
method_to_atom(<<"disconnect">>) ->
method_to_atom(~"disconnect") ->
disconnect;
method_to_atom(<<"setBreakpoints">>) ->
method_to_atom(~"setBreakpoints") ->
set_breakpoints;
method_to_atom(<<"threads">>) ->
method_to_atom(~"threads") ->
threads;
method_to_atom(<<"stackTrace">>) ->
method_to_atom(~"stackTrace") ->
stack_trace;
method_to_atom(<<"continue">>) ->
method_to_atom(~"pause") ->
pause;
method_to_atom(~"continue") ->
continue;
method_to_atom(<<"next">>) ->
method_to_atom(~"next") ->
next;
method_to_atom(<<"stepOut">>) ->
method_to_atom(~"stepOut") ->
step_out;
method_to_atom(<<"scopes">>) ->
method_to_atom(~"scopes") ->
scopes;
method_to_atom(<<"variables">>) ->
method_to_atom(~"variables") ->
variables;
% Reverse requests
method_to_atom(<<"runInTerminal">>) ->
method_to_atom(~"runInTerminal") ->
run_in_terminal;
method_to_atom(Method) ->
?LOG_WARNING("Method not found: ~p", [Method]),
Expand Down
120 changes: 120 additions & 0 deletions test/edb_dap_pause_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
%% Copyright (c) Meta Platforms, Inc. and affiliates.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%% % @format

%% Pause/continue for the EDB DAP adapter

-module(edb_dap_pause_SUITE).

%% erlfmt:ignore
% @fb-only

% @fb-only
-include_lib("stdlib/include/assert.hrl").

%% CT callbacks
-export([
all/0,
init_per_testcase/2,
end_per_testcase/2
]).

%% Test cases
-export([
test_can_pause_and_continue/1
]).

all() ->
[
test_can_pause_and_continue
].

init_per_testcase(_TestCase, Config) ->
Config.

end_per_testcase(_TestCase, _Config) ->
edb_test_support:stop_all_peer_nodes(),
ok.

%%--------------------------------------------------------------------
%% TEST CASES
%%--------------------------------------------------------------------
test_can_pause_and_continue(Config) ->
{ok, Peer, Node, Cookie} = edb_test_support:start_peer_node(Config, "debuggee"),
{ok, Client, _Cwd} = edb_dap_test_support:start_session(Config, Node, Cookie),
ModuleSource = erlang:iolist_to_binary([
~"-module(foo). %L01\n",
~"-export([go/0]). %L02\n",
~"go() -> %L03\n",
~" timer:sleep(infinity), %L04\n",
~" ok. %L05\n"
]),
{ok, ThreadId, ST0} = edb_dap_test_support:ensure_process_in_bp(
Config, Client, Peer, {source, ModuleSource}, go, [], {line, 4}
),

% Sanity-check: we are on line 4
?assertMatch([#{name := ~"foo:go/0", line := 4} | _], ST0),

% Continue!
ContinueResponse = edb_dap_test_client:continue(Client, ThreadId),
?assertMatch(
#{
command := ~"continue",
type := response,
success := true,
body := #{
allThreadsContinued := true
}
},
ContinueResponse
),

% Pause!
PauseResponse = edb_dap_test_client:pause(Client, ThreadId),
EmptyBody = #{},
?assertMatch(
#{
command := ~"pause",
type := response,
success := true,
body := EmptyBody
},
PauseResponse
),

wait_for_stopped_event_with_pause_reason(Client),

ok.

%%--------------------------------------------------------------------
%% Helpers
%% -------------------------------------------------------------------

-spec wait_for_stopped_event_with_pause_reason(Client) -> ok when
Client :: edb_dap_test_client:client().
wait_for_stopped_event_with_pause_reason(Client) ->
{ok, [StoppedEvent]} = edb_dap_test_client:wait_for_event(~"stopped", Client),
?assertMatch(
#{
event := ~"stopped",
body := #{
reason := ~"pause",
preserveFocusHint := true,
allThreadsStopped := true
}
},
StoppedEvent
),
ok.
6 changes: 6 additions & 0 deletions test/edb_dap_test_client.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
set_breakpoints/2,
threads/2,
stack_trace/2,
pause/2,
continue/2,
next/2,
step_out/2,
Expand Down Expand Up @@ -96,6 +97,11 @@ stack_trace(Client, Args) ->
Request = #{type => request, command => <<"stackTrace">>, arguments => Args},
gen_server:call(Client, Request).

-spec pause(client(), edb_dap:pause_request_arguments()) -> ok.
pause(Client, Args) ->
Request = #{type => request, command => <<"pause">>, arguments => Args},
gen_server:call(Client, Request).

-spec continue(client(), edb_dap:continue_request_arguments()) -> ok.
continue(Client, Args) ->
Request = #{type => request, command => <<"continue">>, arguments => Args},
Expand Down

0 comments on commit 285c16f

Please sign in to comment.