• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "inspector_server.h"
17 
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 
21 #include "assembly-emitter.h"
22 #include "assembly-parser.h"
23 #include "runtime.h"
24 #include "types/location.h"
25 #include "utils/json_builder.h"
26 
27 #include "connection/server.h"
28 
29 #include "common.h"
30 #include "json_object_matcher.h"
31 
32 // NOLINTBEGIN
33 
34 using namespace std::placeholders;
35 
36 namespace ark::tooling::inspector::test {
37 
38 class TestServer : public Server {
39 public:
OnValidate(std::function<void ()> && handler)40     void OnValidate([[maybe_unused]] std::function<void()> &&handler) override {};
OnOpen(std::function<void ()> && handler)41     void OnOpen([[maybe_unused]] std::function<void()> &&handler) override {};
OnFail(std::function<void ()> && handler)42     void OnFail([[maybe_unused]] std::function<void()> &&handler) override {};
43 
Call(const std::string & session,const char * method_call,std::function<void (JsonObjectBuilder &)> && parameters)44     void Call(const std::string &session, const char *method_call,
45               std::function<void(JsonObjectBuilder &)> &&parameters) override
46     {
47         std::string tmp(method_call);
48         CallMock(session, tmp, std::move(parameters));
49     }
50 
OnCall(const char * method_call,Handler && handler)51     void OnCall(const char *method_call, Handler &&handler) override
52     {
53         std::string tmp(method_call);
54         OnCallMock(tmp, std::move(handler));
55     }
56 
57     MOCK_METHOD(void, CallMock,
58                 (const std::string &session, const std::string &method_call,
59                  std::function<void(JsonObjectBuilder &)> &&parameters));
60 
61     MOCK_METHOD(void, OnCallMock, (const std::string &method_call, Handler &&handler));
62 
RunOne()63     bool RunOne() override
64     {
65         return true;
66     };
67 };
68 
69 static PtThread g_mthread = PtThread(PtThread::NONE);
70 static const std::string g_sessionId;
71 static const std::string g_sourceFile = "source";
72 static bool g_handlerCalled = false;
73 
74 class ServerTest : public testing::Test {
75 public:
SetUp()76     void SetUp() override
77     {
78         RuntimeOptions options;
79         options.SetShouldInitializeIntrinsics(false);
80         options.SetShouldLoadBootPandaFiles(false);
81         Runtime::Create(options);
82         g_mthread = PtThread(ManagedThread::GetCurrent());
83         g_handlerCalled = false;
84     }
TearDown()85     void TearDown() override
86     {
87         Runtime::Destroy();
88     }
89     TestServer server;
90     InspectorServer inspectorServer {server};
91 };
92 
TEST_F(ServerTest,CallDebuggerResumed)93 TEST_F(ServerTest, CallDebuggerResumed)
94 {
95     inspectorServer.CallTargetAttachedToTarget(g_mthread);
96     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.resumed", testing::_)).Times(1);
97 
98     inspectorServer.CallDebuggerResumed(g_mthread);
99 }
100 
TEST_F(ServerTest,CallDebuggerScriptParsed)101 TEST_F(ServerTest, CallDebuggerScriptParsed)
102 {
103     inspectorServer.CallTargetAttachedToTarget(g_mthread);
104 
105     size_t scriptId = 4;
106     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.scriptParsed", testing::_))
107         .WillOnce([&](testing::Unused, testing::Unused, auto s) {
108             ASSERT_THAT(ToObject(std::move(s)),
109                         JsonProperties(JsonProperty<JsonObject::NumT> {"executionContextId", 0},
110                                        JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
111                                        JsonProperty<JsonObject::NumT> {"startLine", 0},
112                                        JsonProperty<JsonObject::NumT> {"startColumn", 0},
113                                        JsonProperty<JsonObject::NumT> {"endLine", std::numeric_limits<int>::max()},
114                                        JsonProperty<JsonObject::NumT> {"endColumn", std::numeric_limits<int>::max()},
115                                        JsonProperty<JsonObject::StringT> {"hash", ""},
116                                        JsonProperty<JsonObject::StringT> {"url", g_sourceFile.c_str()}));
117         });
118     inspectorServer.CallDebuggerScriptParsed(ScriptId(scriptId), g_sourceFile);
119 }
120 
121 using ResultHolder = std::optional<JsonObject>;
122 
GetResult(Expected<std::unique_ptr<JsonSerializable>,JRPCError> && returned,ResultHolder & result)123 static void GetResult(Expected<std::unique_ptr<JsonSerializable>, JRPCError> &&returned, ResultHolder &result)
124 {
125     ASSERT_TRUE(returned.HasValue());
126     if (returned.Value() != nullptr) {
127         JsonObjectBuilder builder;
128         returned.Value()->Serialize(builder);
129         result.emplace(std::move(builder).Build());
130     } else {
131         result.emplace("{}");
132     }
133 }
134 
TEST_F(ServerTest,DebuggerEnable)135 TEST_F(ServerTest, DebuggerEnable)
136 {
137     TestServer server1;
138     EXPECT_CALL(server1, OnCallMock("Debugger.enable", testing::_)).WillOnce([&](testing::Unused, auto handler) {
139         JsonObject empty;
140         auto res = handler(g_sessionId, empty);
141         ResultHolder result;
142         GetResult(std::move(res), result);
143         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> protocols;
144         ASSERT_THAT(*result,
145                     JsonProperties(JsonProperty<JsonObject::NumT> {"debuggerId", 0},
146                                    JsonProperty<JsonObject::ArrayT> {"protocols", JsonElementsAreArray(protocols)}));
147     });
148     InspectorServer inspector_server1(server1);
149     inspector_server1.OnCallDebuggerEnable([] {});
150 }
151 
__anon9a312da50402(auto unused, auto handler) 152 static auto g_simpleHandler = []([[maybe_unused]] auto unused, auto handler) {
153     JsonObject empty;
154     auto res = handler(g_sessionId, empty);
155     ResultHolder result;
156     GetResult(std::move(res), result);
157     ASSERT_THAT(*result, JsonProperties());
158     ASSERT_TRUE(g_handlerCalled);
159 };
160 
TEST_F(ServerTest,OnCallDebuggerPause)161 TEST_F(ServerTest, OnCallDebuggerPause)
162 {
163     inspectorServer.CallTargetAttachedToTarget(g_mthread);
164 
165     EXPECT_CALL(server, OnCallMock("Debugger.pause", testing::_)).WillOnce(g_simpleHandler);
166     inspectorServer.OnCallDebuggerPause([](PtThread thread) {
167         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
168         g_handlerCalled = true;
169     });
170 }
171 
TEST_F(ServerTest,OnCallDebuggerRemoveBreakpoint)172 TEST_F(ServerTest, OnCallDebuggerRemoveBreakpoint)
173 {
174     size_t break_id = 14;
175 
176     inspectorServer.CallTargetAttachedToTarget(g_mthread);
177 
178     EXPECT_CALL(server, OnCallMock("Debugger.removeBreakpoint", testing::_))
179         .WillOnce([&](testing::Unused, auto handler) {
180             JsonObject empty;
181             auto res = handler(g_sessionId, empty);
182             ASSERT_FALSE(res.HasValue());
183             ASSERT_FALSE(g_handlerCalled);
184         });
185 
186     auto breaks = [break_id](PtThread thread, BreakpointId bid) {
187         ASSERT_EQ(bid, BreakpointId(break_id));
188         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
189         g_handlerCalled = true;
190     };
191     inspectorServer.OnCallDebuggerRemoveBreakpoint(std::move(breaks));
192 
193     EXPECT_CALL(server, OnCallMock("Debugger.removeBreakpoint", testing::_))
194         .WillOnce([&](testing::Unused, auto handler) {
195             JsonObjectBuilder params;
196             params.AddProperty("breakpointId", std::to_string(break_id));
197             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
198             ResultHolder result;
199             GetResult(std::move(res), result);
200             ASSERT_THAT(*result, JsonProperties());
201             ASSERT_TRUE(g_handlerCalled);
202         });
203 
204     inspectorServer.OnCallDebuggerRemoveBreakpoint(std::move(breaks));
205 }
206 
TEST_F(ServerTest,OnCallDebuggerRestartFrame)207 TEST_F(ServerTest, OnCallDebuggerRestartFrame)
208 {
209     size_t fid = 5;
210 
211     inspectorServer.CallTargetAttachedToTarget(g_mthread);
212 
213     EXPECT_CALL(server, OnCallMock("Debugger.restartFrame", testing::_)).WillOnce([&](testing::Unused, auto handler) {
214         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> callFrames;
215         JsonObjectBuilder params;
216         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
217         ASSERT_FALSE(res.HasValue());
218         ASSERT_FALSE(g_handlerCalled);
219     });
220 
221     inspectorServer.OnCallDebuggerRestartFrame([&](auto, auto) { g_handlerCalled = true; });
222 
223     EXPECT_CALL(server, OnCallMock("Debugger.restartFrame", testing::_)).WillOnce([&](testing::Unused, auto handler) {
224         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> callFrames;
225         JsonObjectBuilder params;
226         params.AddProperty("callFrameId", std::to_string(fid));
227         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
228         ResultHolder result;
229         GetResult(std::move(res), result);
230         ASSERT_THAT(*result,
231                     JsonProperties(JsonProperty<JsonObject::ArrayT> {"callFrames", JsonElementsAreArray(callFrames)}));
232         ASSERT_TRUE(g_handlerCalled);
233     });
234 
235     inspectorServer.OnCallDebuggerRestartFrame([&](PtThread thread, FrameId id) {
236         ASSERT_EQ(id, FrameId(fid));
237         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
238         g_handlerCalled = true;
239     });
240 }
241 
TEST_F(ServerTest,OnCallDebuggerResume)242 TEST_F(ServerTest, OnCallDebuggerResume)
243 {
244     inspectorServer.CallTargetAttachedToTarget(g_mthread);
245 
246     EXPECT_CALL(server, OnCallMock("Debugger.resume", testing::_)).WillOnce(g_simpleHandler);
247     inspectorServer.OnCallDebuggerResume([](PtThread thread) {
248         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
249         g_handlerCalled = true;
250     });
251 }
252 
CreatePossibleBreakpointsRequest(ScriptId startScriptId,size_t start,ScriptId endScriptId,size_t end,bool restrictToFunction)253 static JsonObject CreatePossibleBreakpointsRequest(ScriptId startScriptId, size_t start, ScriptId endScriptId,
254                                                    size_t end, bool restrictToFunction)
255 {
256     JsonObjectBuilder params;
257     params.AddProperty("start", Location(startScriptId, start));
258     params.AddProperty("end", Location(endScriptId, end));
259     params.AddProperty("restrictToFunction", restrictToFunction);
260     return JsonObject(std::move(params).Build());
261 }
262 
263 static auto g_getPossibleBreakpointsHandler = [](ScriptId scriptId, size_t start, size_t end, bool restrictToFunction,
__anon9a312da50e02(ScriptId scriptId, size_t start, size_t end, bool restrictToFunction, testing::Unused, auto handler) 264                                                  testing::Unused, auto handler) {
265     auto res =
266         handler(g_sessionId, CreatePossibleBreakpointsRequest(scriptId, start, scriptId, end, restrictToFunction));
267     ResultHolder result;
268     GetResult(std::move(res), result);
269     std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
270     for (auto i = start; i < end; i++) {
271         locations.push_back(
272             testing::Pointee(JsonProperties(JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
273                                             JsonProperty<JsonObject::NumT> {"lineNumber", i})));
274     }
275     ASSERT_THAT(*result,
276                 JsonProperties(JsonProperty<JsonObject::ArrayT> {"locations", JsonElementsAreArray(locations)}));
277 };
278 
DefaultFrameEnumerator(const InspectorServer::FrameInfoHandler & handler)279 static void DefaultFrameEnumerator(const InspectorServer::FrameInfoHandler &handler)
280 {
281     std::optional<RemoteObject> objThis;
282     auto scope_chain = std::vector {Scope(Scope::Type::LOCAL, RemoteObject::Number(72))};
283     handler(FrameId(0), std::to_string(0), g_sourceFile, 0, scope_chain, objThis);
284 }
285 
TEST_F(ServerTest,OnCallDebuggerGetPossibleBreakpoints)286 TEST_F(ServerTest, OnCallDebuggerGetPossibleBreakpoints)
287 {
288     auto scriptId = 0;
289     size_t start = 5;
290     size_t end = 5;
291 
292     inspectorServer.CallTargetAttachedToTarget(g_mthread);
293     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, PauseReason::OTHER, DefaultFrameEnumerator);
294 
295     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
296         .WillOnce(std::bind(g_getPossibleBreakpointsHandler, scriptId, start, end,  // NOLINT(modernize-avoid-bind)
297                             true, _1, _2));
298     auto getLinesTrue = [](std::string_view source, size_t startLine, size_t endLine, bool restrictToFunction) {
299         std::set<size_t> result;
300         if ((source == g_sourceFile) && restrictToFunction) {
301             for (auto i = startLine; i < endLine; i++) {
302                 result.insert(i);
303             }
304         }
305         return result;
306     };
307     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesTrue);
308 
309     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
310         .WillOnce(std::bind(g_getPossibleBreakpointsHandler, scriptId, start, end,  // NOLINT(modernize-avoid-bind)
311                             false, _1, _2));
312     auto getLinesFalse = [](std::string_view source, size_t startLine, size_t endLine, bool restrictToFunction) {
313         std::set<size_t> result;
314         if ((source == g_sourceFile) && !restrictToFunction) {
315             for (auto i = startLine; i < endLine; i++) {
316                 result.insert(i);
317             }
318         }
319         return result;
320     };
321     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesFalse);
322 
323     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
324         .WillOnce([&](testing::Unused, auto handler) {
325             auto res =
326                 handler(g_sessionId, CreatePossibleBreakpointsRequest(scriptId, start, scriptId + 1, end, false));
327             ASSERT_FALSE(res.HasValue());
328         });
329     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesFalse);
330 }
331 
TEST_F(ServerTest,OnCallDebuggerGetScriptSource)332 TEST_F(ServerTest, OnCallDebuggerGetScriptSource)
333 {
334     auto scriptId = 0;
335 
336     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.paused", testing::_))
337         .WillOnce([&](testing::Unused, testing::Unused, auto s) { ToObject(std::move(s)); });
338 
339     inspectorServer.CallTargetAttachedToTarget(g_mthread);
340     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, PauseReason::OTHER, DefaultFrameEnumerator);
341 
342     EXPECT_CALL(server, OnCallMock("Debugger.getScriptSource", testing::_))
343         .WillOnce([&](testing::Unused, auto handler) {
344             JsonObjectBuilder params;
345             params.AddProperty("scriptId", std::to_string(scriptId));
346             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
347             ResultHolder result;
348             GetResult(std::move(res), result);
349             ASSERT_THAT(*result, JsonProperties(JsonProperty<JsonObject::StringT> {"scriptSource", g_sourceFile}));
350         });
351     inspectorServer.OnCallDebuggerGetScriptSource([](auto source) {
352         std::string s(source);
353         return s;
354     });
355 
356     EXPECT_CALL(server, OnCallMock("Debugger.getScriptSource", testing::_))
357         .WillOnce([&](testing::Unused, auto handler) {
358             JsonObject empty;
359             auto res = handler(g_sessionId, empty);
360             ASSERT_FALSE(res.HasValue());
361         });
362     inspectorServer.OnCallDebuggerGetScriptSource([](auto) { return "a"; });
363 }
364 
TEST_F(ServerTest,OnCallDebuggerStepOut)365 TEST_F(ServerTest, OnCallDebuggerStepOut)
366 {
367     inspectorServer.CallTargetAttachedToTarget(g_mthread);
368 
369     EXPECT_CALL(server, OnCallMock("Debugger.stepOut", testing::_)).WillOnce(g_simpleHandler);
370 
371     inspectorServer.OnCallDebuggerStepOut([](PtThread thread) {
372         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
373         g_handlerCalled = true;
374     });
375 }
376 
TEST_F(ServerTest,OnCallDebuggerStepInto)377 TEST_F(ServerTest, OnCallDebuggerStepInto)
378 {
379     inspectorServer.CallTargetAttachedToTarget(g_mthread);
380 
381     EXPECT_CALL(server, OnCallMock("Debugger.stepInto", testing::_)).WillOnce(g_simpleHandler);
382 
383     inspectorServer.OnCallDebuggerStepInto([](PtThread thread) {
384         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
385         g_handlerCalled = true;
386     });
387 }
388 
TEST_F(ServerTest,OnCallDebuggerStepOver)389 TEST_F(ServerTest, OnCallDebuggerStepOver)
390 {
391     inspectorServer.CallTargetAttachedToTarget(g_mthread);
392 
393     EXPECT_CALL(server, OnCallMock("Debugger.stepOver", testing::_)).WillOnce(g_simpleHandler);
394 
395     inspectorServer.OnCallDebuggerStepOver([](PtThread thread) {
396         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
397         g_handlerCalled = true;
398     });
399 }
400 
handlerForSetBreak(PtThread thread,const std::function<bool (std::string_view)> & comp,size_t line,std::set<std::string_view> & sources,const std::string * condition)401 std::optional<BreakpointId> handlerForSetBreak([[maybe_unused]] PtThread thread,
402                                                [[maybe_unused]] const std::function<bool(std::string_view)> &comp,
403                                                size_t line, [[maybe_unused]] std::set<std::string_view> &sources,
404                                                [[maybe_unused]] const std::string *condition)
405 {
406     sources.insert("source");
407     return BreakpointId(line);
408 }
409 
handlerForSetBreakEmpty(PtThread thread,const std::function<bool (std::string_view)> & comp,size_t line,std::set<std::string_view> & sources,const std::string * condition)410 std::optional<BreakpointId> handlerForSetBreakEmpty([[maybe_unused]] PtThread thread,
411                                                     [[maybe_unused]] const std::function<bool(std::string_view)> &comp,
412                                                     [[maybe_unused]] size_t line,
413                                                     [[maybe_unused]] std::set<std::string_view> &sources,
414                                                     [[maybe_unused]] const std::string *condition)
415 {
416     sources.insert("source");
417     return {};
418 }
419 
TEST_F(ServerTest,OnCallDebuggerSetBreakpoint)420 TEST_F(ServerTest, OnCallDebuggerSetBreakpoint)
421 {
422     auto scriptId = 0;
423     size_t start = 5;
424 
425     inspectorServer.CallTargetAttachedToTarget(g_mthread);
426     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, PauseReason::OTHER, DefaultFrameEnumerator);
427 
428     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
429         JsonObjectBuilder params;
430         params.AddProperty("location", Location(scriptId, start));
431         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
432         ResultHolder result;
433         GetResult(std::move(res), result);
434         ASSERT_THAT(*result,
435                     JsonProperties(JsonProperty<JsonObject::StringT> {"breakpointId", std::to_string(start)},
436                                    JsonProperty<JsonObject::JsonObjPointer> {
437                                        "actualLocation",
438                                        testing::Pointee(JsonProperties(
439                                            JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
440                                            JsonProperty<JsonObject::NumT> {"lineNumber", start - 1}))}));
441     });
442 
443     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreak);
444 
445     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
446         JsonObject empty;
447         auto res = handler(g_sessionId, empty);
448         ASSERT_FALSE(res.HasValue());
449     });
450 
451     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreak);
452 
453     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
454         JsonObjectBuilder params;
455         params.AddProperty("location", Location(scriptId, start));
456         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
457         ASSERT_FALSE(res.HasValue());
458     });
459 
460     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreakEmpty);
461 }
462 
TEST_F(ServerTest,OnCallDebuggerSetBreakpointByUrl)463 TEST_F(ServerTest, OnCallDebuggerSetBreakpointByUrl)
464 {
465     auto scriptId = 0;
466     size_t start = 5;
467 
468     inspectorServer.CallTargetAttachedToTarget(g_mthread);
469 
470     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointByUrl", testing::_))
471         .WillOnce([&](testing::Unused, auto handler) {
472             JsonObjectBuilder params;
473             params.AddProperty("lineNumber", start);
474             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
475             ASSERT_FALSE(res.HasValue());
476         });
477 
478     inspectorServer.OnCallDebuggerSetBreakpointByUrl(handlerForSetBreak);
479 
480     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointByUrl", testing::_))
481         .WillOnce([&](testing::Unused, auto handler) {
482             JsonObjectBuilder params;
483             params.AddProperty("lineNumber", start);
484             params.AddProperty("url", "file://source");
485             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
486             ResultHolder result;
487             GetResult(std::move(res), result);
488 
489             std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
490             locations.push_back(testing::Pointee(
491                 JsonProperties(JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
492                                JsonProperty<JsonObject::NumT> {"lineNumber", start})));
493             auto expected =
494                 JsonProperties(JsonProperty<JsonObject::StringT> {"breakpointId", std::to_string(start + 1)},
495                                JsonProperty<JsonObject::ArrayT> {"locations", JsonElementsAreArray(locations)});
496 
497             ASSERT_THAT(*result, expected);
498         });
499 
500     inspectorServer.OnCallDebuggerSetBreakpointByUrl(handlerForSetBreak);
501 }
502 
TEST_F(ServerTest,OnCallDebuggerSetBreakpointsActive)503 TEST_F(ServerTest, OnCallDebuggerSetBreakpointsActive)
504 {
505     inspectorServer.CallTargetAttachedToTarget(g_mthread);
506 
507     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
508         .WillOnce([&](testing::Unused, auto handler) {
509             JsonObject empty;
510             auto res = handler(g_sessionId, empty);
511             ASSERT_FALSE(res.HasValue());
512             ASSERT_FALSE(g_handlerCalled);
513         });
514 
515     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
516         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
517         ASSERT_FALSE(value);
518         g_handlerCalled = true;
519     });
520 
521     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
522         .WillOnce([&](testing::Unused, auto handler) {
523             JsonObjectBuilder params;
524             params.AddProperty("active", true);
525             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
526             ResultHolder result;
527             GetResult(std::move(res), result);
528             ASSERT_THAT(*result, JsonProperties());
529             ASSERT_TRUE(g_handlerCalled);
530             g_handlerCalled = false;
531         });
532 
533     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
534         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
535         ASSERT_TRUE(value);
536         g_handlerCalled = true;
537     });
538 
539     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
540         .WillOnce([&](testing::Unused, auto handler) {
541             JsonObjectBuilder params;
542             params.AddProperty("active", false);
543             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
544             ResultHolder result;
545             GetResult(std::move(res), result);
546             ASSERT_THAT(*result, JsonProperties());
547             ASSERT_TRUE(g_handlerCalled);
548         });
549 
550     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
551         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
552         ASSERT_FALSE(value);
553         g_handlerCalled = true;
554     });
555 }
556 
TEST_F(ServerTest,OnCallDebuggerSetPauseOnExceptions)557 TEST_F(ServerTest, OnCallDebuggerSetPauseOnExceptions)
558 {
559     inspectorServer.CallTargetAttachedToTarget(g_mthread);
560 
561     EXPECT_CALL(server, OnCallMock("Debugger.setPauseOnExceptions", testing::_))
562         .WillOnce([&](testing::Unused, auto handler) {
563             JsonObjectBuilder params;
564             params.AddProperty("state", "none");
565             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
566             ResultHolder result;
567             GetResult(std::move(res), result);
568             ASSERT_THAT(*result, JsonProperties());
569             ASSERT_TRUE(g_handlerCalled);
570         });
571 
572     inspectorServer.OnCallDebuggerSetPauseOnExceptions([](PtThread thread, PauseOnExceptionsState state) {
573         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
574         ASSERT_EQ(PauseOnExceptionsState::NONE, state);
575         g_handlerCalled = true;
576     });
577 }
578 
TEST_F(ServerTest,OnCallDebuggerDisable)579 TEST_F(ServerTest, OnCallDebuggerDisable)
580 {
581     inspectorServer.CallTargetAttachedToTarget(g_mthread);
582 
583     EXPECT_CALL(server, OnCallMock("Debugger.disable", testing::_)).WillOnce(g_simpleHandler);
584 
585     inspectorServer.OnCallDebuggerDisable([](PtThread thread) {
586         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
587         g_handlerCalled = true;
588     });
589 }
590 
TEST_F(ServerTest,OnCallDebuggerClientDisconnect)591 TEST_F(ServerTest, OnCallDebuggerClientDisconnect)
592 {
593     inspectorServer.CallTargetAttachedToTarget(g_mthread);
594 
595     EXPECT_CALL(server, OnCallMock("Debugger.clientDisconnect", testing::_)).WillOnce(g_simpleHandler);
596 
597     inspectorServer.OnCallDebuggerClientDisconnect([](PtThread thread) {
598         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
599         g_handlerCalled = true;
600     });
601 }
602 
TEST_F(ServerTest,OnCallDebuggerSetAsyncCallStackDepth)603 TEST_F(ServerTest, OnCallDebuggerSetAsyncCallStackDepth)
604 {
605     inspectorServer.CallTargetAttachedToTarget(g_mthread);
606 
607     EXPECT_CALL(server, OnCallMock("Debugger.setAsyncCallStackDepth", testing::_)).WillOnce(g_simpleHandler);
608 
609     inspectorServer.OnCallDebuggerSetAsyncCallStackDepth([](PtThread thread) {
610         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
611         g_handlerCalled = true;
612     });
613 }
614 
TEST_F(ServerTest,OnCallDebuggerSetBlackboxPatterns)615 TEST_F(ServerTest, OnCallDebuggerSetBlackboxPatterns)
616 {
617     inspectorServer.CallTargetAttachedToTarget(g_mthread);
618 
619     EXPECT_CALL(server, OnCallMock("Debugger.setBlackboxPatterns", testing::_)).WillOnce(g_simpleHandler);
620 
621     inspectorServer.OnCallDebuggerSetBlackboxPatterns([](PtThread thread) {
622         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
623         g_handlerCalled = true;
624     });
625 }
626 
TEST_F(ServerTest,OnCallDebuggerSmartStepInto)627 TEST_F(ServerTest, OnCallDebuggerSmartStepInto)
628 {
629     inspectorServer.CallTargetAttachedToTarget(g_mthread);
630 
631     EXPECT_CALL(server, OnCallMock("Debugger.smartStepInto", testing::_)).WillOnce(g_simpleHandler);
632 
633     inspectorServer.OnCallDebuggerSmartStepInto([](PtThread thread) {
634         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
635         g_handlerCalled = true;
636     });
637 }
638 
TEST_F(ServerTest,OnCallDebuggerDropFrame)639 TEST_F(ServerTest, OnCallDebuggerDropFrame)
640 {
641     inspectorServer.CallTargetAttachedToTarget(g_mthread);
642 
643     EXPECT_CALL(server, OnCallMock("Debugger.dropFrame", testing::_)).WillOnce(g_simpleHandler);
644 
645     inspectorServer.OnCallDebuggerDropFrame([](PtThread thread) {
646         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
647         g_handlerCalled = true;
648     });
649 }
650 
TEST_F(ServerTest,OnCallDebuggerSetNativeRange)651 TEST_F(ServerTest, OnCallDebuggerSetNativeRange)
652 {
653     inspectorServer.CallTargetAttachedToTarget(g_mthread);
654 
655     EXPECT_CALL(server, OnCallMock("Debugger.setNativeRange", testing::_)).WillOnce(g_simpleHandler);
656 
657     inspectorServer.OnCallDebuggerSetNativeRange([](PtThread thread) {
658         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
659         g_handlerCalled = true;
660     });
661 }
662 
TEST_F(ServerTest,OnCallDebuggerReplyNativeCalling)663 TEST_F(ServerTest, OnCallDebuggerReplyNativeCalling)
664 {
665     inspectorServer.CallTargetAttachedToTarget(g_mthread);
666 
667     EXPECT_CALL(server, OnCallMock("Debugger.replyNativeCalling", testing::_)).WillOnce(g_simpleHandler);
668 
669     inspectorServer.OnCallDebuggerReplyNativeCalling([](PtThread thread) {
670         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
671         g_handlerCalled = true;
672     });
673 }
674 
TEST_F(ServerTest,OnCallDebuggerContinueToLocation)675 TEST_F(ServerTest, OnCallDebuggerContinueToLocation)
676 {
677     auto scriptId = 0;
678     size_t start = 5;
679 
680     inspectorServer.CallTargetAttachedToTarget(g_mthread);
681 
682     EXPECT_CALL(server, OnCallMock("Debugger.continueToLocation", testing::_))
683         .WillOnce([&](testing::Unused, auto handler) {
684             JsonObjectBuilder params;
685             params.AddProperty("location", Location(scriptId, start));
686             handler(g_sessionId, JsonObject(std::move(params).Build()));
687         });
688 
689     inspectorServer.OnCallDebuggerContinueToLocation([](PtThread thread, std::string_view, size_t) {
690         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
691         g_handlerCalled = true;
692     });
693 }
694 
TEST_F(ServerTest,OnCallDebuggerSetSkipAllPauses)695 TEST_F(ServerTest, OnCallDebuggerSetSkipAllPauses)
696 {
697     inspectorServer.CallTargetAttachedToTarget(g_mthread);
698 
699     EXPECT_CALL(server, OnCallMock("Debugger.setSkipAllPauses", testing::_))
700         .WillOnce([&](testing::Unused, auto handler) {
701             JsonObjectBuilder params;
702             params.AddProperty("skip", true);
703             handler(g_sessionId, JsonObject(std::move(params).Build()));
704         });
705 
706     inspectorServer.OnCallDebuggerSetSkipAllPauses([](PtThread thread, bool) {
707         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
708         g_handlerCalled = true;
709     });
710 }
711 
handlerForEvaluateFailed(PtThread thread,const std::string & bytecodeBase64,size_t frameNumber)712 Expected<EvaluationResult, std::string> handlerForEvaluateFailed([[maybe_unused]] PtThread thread,
713                                                                  [[maybe_unused]] const std::string &bytecodeBase64,
714                                                                  [[maybe_unused]] size_t frameNumber)
715 {
716     return Unexpected(std::string("evaluate failed"));
717 }
718 
handlerForEvaluate(PtThread thread,const std::string & bytecodeBase64,size_t frameNumber)719 Expected<EvaluationResult, std::string> handlerForEvaluate([[maybe_unused]] PtThread thread,
720                                                            [[maybe_unused]] const std::string &bytecodeBase64,
721                                                            [[maybe_unused]] size_t frameNumber)
722 {
723     return Unexpected(std::string("evaluation failed"));
724 }
725 
TEST_F(ServerTest,OnCallDebuggerEvaluateOnCallFrame)726 TEST_F(ServerTest, OnCallDebuggerEvaluateOnCallFrame)
727 {
728     inspectorServer.CallTargetAttachedToTarget(g_mthread);
729 
730     EXPECT_CALL(server, OnCallMock("Debugger.evaluateOnCallFrame", testing::_))
731         .WillOnce([&](testing::Unused, auto handler) {
732             JsonObjectBuilder params;
733             params.AddProperty("callFrameId", -1);
734             params.AddProperty("expression", "any expression");
735 
736             auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
737             ASSERT_FALSE(res.HasValue());
738         });
739 
740     inspectorServer.OnCallDebuggerEvaluateOnCallFrame(handlerForEvaluateFailed);
741 }
742 
TEST_F(ServerTest,OnCallDebuggerCallFunctionOn)743 TEST_F(ServerTest, OnCallDebuggerCallFunctionOn)
744 {
745     inspectorServer.CallTargetAttachedToTarget(g_mthread);
746 
747     EXPECT_CALL(server, OnCallMock("Debugger.callFunctionOn", testing::_)).WillOnce([&](testing::Unused, auto handler) {
748         JsonObjectBuilder params;
749         params.AddProperty("callFrameId", -1);
750         params.AddProperty("functionDeclaration", "any functionDeclaration");
751 
752         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
753         ASSERT_FALSE(res.HasValue());
754     });
755 
756     inspectorServer.OnCallDebuggerCallFunctionOn(handlerForEvaluateFailed);
757 }
758 
TEST_F(ServerTest,OnCallDebuggerGetPossibleAndSetBreakpointByUrl)759 TEST_F(ServerTest, OnCallDebuggerGetPossibleAndSetBreakpointByUrl)
760 {
761     auto scriptId = 0;
762     size_t start1 = 5;
763     size_t start2 = 6;
764 
765     inspectorServer.CallTargetAttachedToTarget(g_mthread);
766 
767     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleAndSetBreakpointByUrl", testing::_))
768         .WillOnce([&](testing::Unused, auto handler) {
769             class RequestLocation : public JsonSerializable {
770             public:
771                 explicit RequestLocation(std::string url, size_t lineNumber) : url_(url), lineNumber_(lineNumber) {}
772 
773                 void Serialize(JsonObjectBuilder &builder) const override
774                 {
775                     builder.AddProperty("url", url_);
776                     builder.AddProperty("lineNumber", lineNumber_);
777                 }
778 
779             private:
780                 std::string url_;
781                 size_t lineNumber_;
782             };
783             std::vector<RequestLocation> requestLocations = {RequestLocation("file://source", start1),
784                                                              RequestLocation("file://source", start2)};
785             JsonObjectBuilder builder;
786             builder.AddProperty("locations", [&](JsonArrayBuilder &locations) {
787                 for (const auto &loc : requestLocations) {
788                     locations.Add(loc);
789                 }
790             });
791 
792             auto res = handler(g_sessionId, JsonObject(std::move(builder).Build()));
793             ResultHolder result;
794             GetResult(std::move(res), result);
795 
796             std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
797             locations.push_back(testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"scriptId", scriptId},
798                                                                 JsonProperty<JsonObject::NumT> {"lineNumber", start1},
799                                                                 JsonProperty<JsonObject::NumT> {"columnNumber", 0},
800                                                                 JsonProperty<JsonObject::StringT> {"id", "6"})));
801             locations.push_back(testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"scriptId", scriptId},
802                                                                 JsonProperty<JsonObject::NumT> {"lineNumber", start2},
803                                                                 JsonProperty<JsonObject::NumT> {"columnNumber", 0},
804                                                                 JsonProperty<JsonObject::StringT> {"id", "7"})));
805             auto expected =
806                 JsonProperties(JsonProperty<JsonObject::ArrayT> {"locations", JsonElementsAreArray(locations)});
807 
808             ASSERT_THAT(*result, expected);
809         });
810 
811     inspectorServer.OnCallDebuggerGetPossibleAndSetBreakpointByUrl(handlerForSetBreak);
812 }
813 
TEST_F(ServerTest,OnCallRuntimeEnable)814 TEST_F(ServerTest, OnCallRuntimeEnable)
815 {
816     inspectorServer.CallTargetAttachedToTarget(g_mthread);
817 
818     EXPECT_CALL(server, OnCallMock("Runtime.enable", testing::_)).WillOnce([&](testing::Unused, auto handler) {
819         JsonObject empty;
820         auto res = handler(g_sessionId, empty);
821         ResultHolder result;
822         GetResult(std::move(res), result);
823         ASSERT_THAT(*result, JsonProperties());
824         ASSERT_TRUE(g_handlerCalled);
825     });
826     inspectorServer.OnCallRuntimeEnable([](PtThread thread) {
827         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
828         g_handlerCalled = true;
829     });
830 }
831 
TEST_F(ServerTest,OnCallRuntimeGetProperties)832 TEST_F(ServerTest, OnCallRuntimeGetProperties)
833 {
834     auto object_id = 6;
835     auto preview = true;
836 
837     inspectorServer.CallTargetAttachedToTarget(g_mthread);
838 
839     EXPECT_CALL(server, OnCallMock("Runtime.getProperties", testing::_)).WillOnce([&](testing::Unused, auto handler) {
840         JsonObjectBuilder params;
841         params.AddProperty("objectId", std::to_string(object_id));
842         params.AddProperty("generatePreview", preview);
843         auto res = handler(g_sessionId, JsonObject(std::move(params).Build()));
844         ResultHolder result;
845         GetResult(std::move(res), result);
846 
847         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> expected;
848         expected.push_back(testing::Pointee(JsonProperties(
849             JsonProperty<JsonObject::StringT> {"name", "object"},
850             JsonProperty<JsonObject::JsonObjPointer> {
851                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"value", object_id},
852                                                          JsonProperty<JsonObject::StringT> {"type", "number"}))},
853             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
854             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
855             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
856         expected.push_back(testing::Pointee(JsonProperties(
857             JsonProperty<JsonObject::StringT> {"name", "preview"},
858             JsonProperty<JsonObject::JsonObjPointer> {
859                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::BoolT> {"value", preview},
860                                                          JsonProperty<JsonObject::StringT> {"type", "boolean"}))},
861             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
862             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
863             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
864         expected.push_back(testing::Pointee(JsonProperties(
865             JsonProperty<JsonObject::StringT> {"name", "threadId"},
866             JsonProperty<JsonObject::JsonObjPointer> {
867                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"value", g_mthread.GetId()},
868                                                          JsonProperty<JsonObject::StringT> {"type", "number"}))},
869             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
870             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
871             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
872 
873         ASSERT_THAT(*result,
874                     JsonProperties(JsonProperty<JsonObject::ArrayT> {"result", JsonElementsAreArray(expected)}));
875     });
876 
877     auto getProperties = [](PtThread thread, RemoteObjectId id, bool need_preview) {
878         std::vector<PropertyDescriptor> res;
879         res.push_back(PropertyDescriptor("object", RemoteObject::Number(id)));
880         res.push_back(PropertyDescriptor("preview", RemoteObject::Boolean(need_preview)));
881         res.push_back(PropertyDescriptor("threadId", RemoteObject::Number(thread.GetId())));
882         return res;
883     };
884 
885     inspectorServer.OnCallRuntimeGetProperties(getProperties);
886 }
887 
TEST_F(ServerTest,OnCallRuntimeRunIfWaitingForDebugger)888 TEST_F(ServerTest, OnCallRuntimeRunIfWaitingForDebugger)
889 {
890     inspectorServer.CallTargetAttachedToTarget(g_mthread);
891 
892     EXPECT_CALL(server, OnCallMock("Runtime.runIfWaitingForDebugger", testing::_))
893         .WillOnce([&](testing::Unused, auto handler) {
894             JsonObject empty;
895             auto res = handler(g_sessionId, empty);
896             ResultHolder result;
897             GetResult(std::move(res), result);
898             ASSERT_THAT(*result, JsonProperties());
899             ASSERT_TRUE(g_handlerCalled);
900         });
901 
902     inspectorServer.OnCallRuntimeRunIfWaitingForDebugger([](PtThread thread) {
903         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
904         g_handlerCalled = true;
905     });
906 }
907 
908 }  // namespace ark::tooling::inspector::test
909 
910 // NOLINTEND
911