• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023 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 "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 
19 #include "common.h"
20 #include "types/location.h"
21 #include "inspector_server.h"
22 #include "server.h"
23 #include "utils/json_builder.h"
24 #include "json_object_matcher.h"
25 #include "runtime.h"
26 #include "assembly-emitter.h"
27 #include "assembly-parser.h"
28 
29 // NOLINTBEGIN
30 
31 using namespace std::placeholders;
32 
33 namespace panda::tooling::inspector::test {
34 
35 class TestServer : public Server {
36 public:
OnValidate(std::function<void ()> && handler)37     void OnValidate([[maybe_unused]] std::function<void()> &&handler) override {};
OnOpen(std::function<void ()> && handler)38     void OnOpen([[maybe_unused]] std::function<void()> &&handler) override {};
OnFail(std::function<void ()> && handler)39     void OnFail([[maybe_unused]] std::function<void()> &&handler) override {};
40 
Call(const std::string & session,const char * method_call,std::function<void (JsonObjectBuilder &)> && parameters)41     void Call(const std::string &session, const char *method_call,
42               std::function<void(JsonObjectBuilder &)> &&parameters) override
43     {
44         std::string tmp(method_call);
45         CallMock(session, tmp, std::move(parameters));
46     }
47 
OnCall(const char * method_call,std::function<void (const std::string &,JsonObjectBuilder &,const JsonObject &)> && handler)48     void OnCall(const char *method_call,
49                 std::function<void(const std::string &, JsonObjectBuilder &, const JsonObject &)> &&handler) override
50     {
51         std::string tmp(method_call);
52         OnCallMock(tmp, std::move(handler));
53     }
54 
55     MOCK_METHOD(void, CallMock,
56                 (const std::string &session, const std::string &method_call,
57                  std::function<void(JsonObjectBuilder &)> &&parameters));
58 
59     MOCK_METHOD(void, OnCallMock,
60                 (const std::string &method_call,
61                  std::function<void(const std::string &, JsonObjectBuilder &, const JsonObject &)> &&handler));
62 
Poll()63     bool Poll() override
64     {
65         return true;
66     };
RunOne()67     bool RunOne() override
68     {
69         return true;
70     };
71 };
72 
73 static PtThread g_mthread = PtThread(PtThread::NONE);
74 static const std::string g_sessionId;
75 static const std::string g_sourceFile = "source";
76 static bool g_handlerCalled = false;
77 
78 class ServerTest : public testing::Test {
79 public:
SetUp()80     void SetUp() override
81     {
82         RuntimeOptions options;
83         options.SetShouldInitializeIntrinsics(false);
84         options.SetShouldLoadBootPandaFiles(false);
85         Runtime::Create(options);
86         g_mthread = PtThread(ManagedThread::GetCurrent());
87         g_handlerCalled = false;
88     }
TearDown()89     void TearDown() override
90     {
91         Runtime::Destroy();
92     }
93     TestServer server;
94     InspectorServer inspectorServer {server};
95 };
96 
TEST_F(ServerTest,CallDebuggerResumed)97 TEST_F(ServerTest, CallDebuggerResumed)
98 {
99     inspectorServer.CallTargetAttachedToTarget(g_mthread);
100     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.resumed", testing::_)).Times(1);
101 
102     inspectorServer.CallDebuggerResumed(g_mthread);
103 }
104 
TEST_F(ServerTest,CallDebuggerScriptParsed)105 TEST_F(ServerTest, CallDebuggerScriptParsed)
106 {
107     inspectorServer.CallTargetAttachedToTarget(g_mthread);
108 
109     size_t scriptId = 4;
110     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.scriptParsed", testing::_))
111         .WillOnce([&](testing::Unused, testing::Unused, auto s) {
112             ASSERT_THAT(ToObject(std::move(s)),
113                         JsonProperties(JsonProperty<JsonObject::NumT> {"executionContextId", g_mthread.GetId()},
114                                        JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
115                                        JsonProperty<JsonObject::NumT> {"startLine", 0},
116                                        JsonProperty<JsonObject::NumT> {"startColumn", 0},
117                                        JsonProperty<JsonObject::NumT> {"endLine", std::numeric_limits<int>::max()},
118                                        JsonProperty<JsonObject::NumT> {"endColumn", std::numeric_limits<int>::max()},
119                                        JsonProperty<JsonObject::StringT> {"hash", ""},
120                                        JsonProperty<JsonObject::StringT> {"url", g_sourceFile.c_str()}));
121         });
122     inspectorServer.CallDebuggerScriptParsed(g_mthread, ScriptId(scriptId), g_sourceFile);
123 }
124 
TEST_F(ServerTest,DebuggerEnable)125 TEST_F(ServerTest, DebuggerEnable)
126 {
127     TestServer server1;
128     EXPECT_CALL(server1, OnCallMock("Debugger.enable", testing::_)).WillOnce([&](testing::Unused, auto handler) {
129         JsonObjectBuilder res;
130         JsonObject empty;
131         handler(g_sessionId, res, empty);
132         ASSERT_THAT(JsonObject(std::move(res).Build()),
133                     JsonProperties(JsonProperty<JsonObject::StringT> {"debuggerId", "debugger"}));
134     });
135     InspectorServer inspector_server1(server1);
136 }
137 
__anond6c00cd00302(auto unused, auto handler) 138 static auto g_simpleHandler = []([[maybe_unused]] auto unused, auto handler) {
139     JsonObjectBuilder res;
140     JsonObject empty;
141     handler(g_sessionId, res, empty);
142     ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
143     ASSERT_TRUE(g_handlerCalled);
144 };
145 
TEST_F(ServerTest,OnCallDebuggerPause)146 TEST_F(ServerTest, OnCallDebuggerPause)
147 {
148     inspectorServer.CallTargetAttachedToTarget(g_mthread);
149 
150     EXPECT_CALL(server, OnCallMock("Debugger.pause", testing::_)).WillOnce(g_simpleHandler);
151     inspectorServer.OnCallDebuggerPause([](PtThread thread) {
152         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
153         g_handlerCalled = true;
154     });
155 }
156 
TEST_F(ServerTest,OnCallDebuggerRemoveBreakpoint)157 TEST_F(ServerTest, OnCallDebuggerRemoveBreakpoint)
158 {
159     size_t break_id = 14;
160 
161     inspectorServer.CallTargetAttachedToTarget(g_mthread);
162 
163     EXPECT_CALL(server, OnCallMock("Debugger.removeBreakpoint", testing::_))
164         .WillOnce([&](testing::Unused, auto handler) {
165             JsonObjectBuilder res;
166             JsonObject empty;
167             handler(g_sessionId, res, empty);
168             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
169             ASSERT_FALSE(g_handlerCalled);
170         });
171 
172     auto breaks = [break_id](PtThread thread, BreakpointId bid) {
173         ASSERT_EQ(bid, BreakpointId(break_id));
174         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
175         g_handlerCalled = true;
176     };
177     inspectorServer.OnCallDebuggerRemoveBreakpoint(std::move(breaks));
178 
179     EXPECT_CALL(server, OnCallMock("Debugger.removeBreakpoint", testing::_))
180         .WillOnce([&](testing::Unused, auto handler) {
181             JsonObjectBuilder res;
182             JsonObjectBuilder params;
183             params.AddProperty("breakpointId", std::to_string(break_id));
184             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
185             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
186             ASSERT_TRUE(g_handlerCalled);
187         });
188 
189     inspectorServer.OnCallDebuggerRemoveBreakpoint(std::move(breaks));
190 }
191 
TEST_F(ServerTest,OnCallDebuggerRestartFrame)192 TEST_F(ServerTest, OnCallDebuggerRestartFrame)
193 {
194     size_t fid = 5;
195 
196     inspectorServer.CallTargetAttachedToTarget(g_mthread);
197 
198     EXPECT_CALL(server, OnCallMock("Debugger.restartFrame", testing::_)).WillOnce([&](testing::Unused, auto handler) {
199         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> callFrames;
200         JsonObjectBuilder res;
201         JsonObjectBuilder params;
202         handler(g_sessionId, res, JsonObject(std::move(params).Build()));
203         ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
204         ASSERT_FALSE(g_handlerCalled);
205     });
206 
207     inspectorServer.OnCallDebuggerRestartFrame([&](auto, auto) { g_handlerCalled = true; });
208 
209     EXPECT_CALL(server, OnCallMock("Debugger.restartFrame", testing::_)).WillOnce([&](testing::Unused, auto handler) {
210         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> callFrames;
211         JsonObjectBuilder res;
212         JsonObjectBuilder params;
213         params.AddProperty("callFrameId", std::to_string(fid));
214         handler(g_sessionId, res, JsonObject(std::move(params).Build()));
215         ASSERT_THAT(JsonObject(std::move(res).Build()),
216                     JsonProperties(JsonProperty<JsonObject::ArrayT> {"callFrames", JsonElementsAreArray(callFrames)}));
217         ASSERT_TRUE(g_handlerCalled);
218     });
219 
220     inspectorServer.OnCallDebuggerRestartFrame([&](PtThread thread, FrameId id) {
221         ASSERT_EQ(id, FrameId(fid));
222         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
223         g_handlerCalled = true;
224     });
225 }
226 
TEST_F(ServerTest,OnCallDebuggerResume)227 TEST_F(ServerTest, OnCallDebuggerResume)
228 {
229     inspectorServer.CallTargetAttachedToTarget(g_mthread);
230 
231     EXPECT_CALL(server, OnCallMock("Debugger.resume", testing::_)).WillOnce(g_simpleHandler);
232     inspectorServer.OnCallDebuggerResume([](PtThread thread) {
233         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
234         g_handlerCalled = true;
235     });
236 }
237 
CreatePossibleBreakpointsRequest(ScriptId startScriptId,size_t start,ScriptId endScriptId,size_t end,bool restrictToFunction)238 static JsonObject CreatePossibleBreakpointsRequest(ScriptId startScriptId, size_t start, ScriptId endScriptId,
239                                                    size_t end, bool restrictToFunction)
240 {
241     JsonObjectBuilder params;
242     params.AddProperty("start", Location(startScriptId, start).ToJson());
243     params.AddProperty("end", Location(endScriptId, end).ToJson());
244     params.AddProperty("restrictToFunction", restrictToFunction);
245     return JsonObject(std::move(params).Build());
246 }
247 
248 static auto g_getPossibleBreakpointsHandler = [](ScriptId scriptId, size_t start, size_t end, bool restrictToFunction,
__anond6c00cd00d02(ScriptId scriptId, size_t start, size_t end, bool restrictToFunction, testing::Unused, auto handler) 249                                                  testing::Unused, auto handler) {
250     JsonObjectBuilder res;
251     handler(g_sessionId, res, CreatePossibleBreakpointsRequest(scriptId, start, scriptId, end, restrictToFunction));
252     std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
253     for (auto i = start; i < end; i++) {
254         locations.push_back(
255             testing::Pointee(JsonProperties(JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
256                                             JsonProperty<JsonObject::NumT> {"lineNumber", i})));
257     }
258     ASSERT_THAT(JsonObject(std::move(res).Build()),
259                 JsonProperties(JsonProperty<JsonObject::ArrayT> {"locations", JsonElementsAreArray(locations)}));
260 };
261 
TEST_F(ServerTest,OnCallDebuggerGetPossibleBreakpoints)262 TEST_F(ServerTest, OnCallDebuggerGetPossibleBreakpoints)
263 {
264     auto scriptId = 0;
265     size_t start = 5;
266     size_t end = 5;
267 
268     auto func = [&](auto &handler) {
269         auto scope_chain = std::vector {Scope(Scope::Type::LOCAL, RemoteObject::Number(72))};
270         handler(FrameId(0), std::to_string(0), g_sourceFile, 0, scope_chain);
271     };
272 
273     inspectorServer.CallTargetAttachedToTarget(g_mthread);
274     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, func);
275 
276     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
277         .WillOnce(std::bind(g_getPossibleBreakpointsHandler, scriptId, start, end,  // NOLINT(modernize-avoid-bind)
278                             true, _1, _2));
279     auto getLinesTrue = [](std::string_view source, size_t startLine, size_t endLine, bool restrictToFunction) {
280         std::set<size_t> result;
281         if ((source == g_sourceFile) && restrictToFunction) {
282             for (auto i = startLine; i < endLine; i++) {
283                 result.insert(i);
284             }
285         }
286         return result;
287     };
288     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesTrue);
289 
290     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
291         .WillOnce(std::bind(g_getPossibleBreakpointsHandler, scriptId, start, end,  // NOLINT(modernize-avoid-bind)
292                             false, _1, _2));
293     auto getLinesFalse = [](std::string_view source, size_t startLine, size_t endLine, bool restrictToFunction) {
294         std::set<size_t> result;
295         if ((source == g_sourceFile) && !restrictToFunction) {
296             for (auto i = startLine; i < endLine; i++) {
297                 result.insert(i);
298             }
299         }
300         return result;
301     };
302     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesFalse);
303 
304     EXPECT_CALL(server, OnCallMock("Debugger.getPossibleBreakpoints", testing::_))
305         .WillOnce([&](testing::Unused, auto handler) {
306             JsonObjectBuilder res;
307             handler(g_sessionId, res, CreatePossibleBreakpointsRequest(scriptId, start, scriptId + 1, end, false));
308             std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
309             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
310         });
311     inspectorServer.OnCallDebuggerGetPossibleBreakpoints(getLinesFalse);
312 }
313 
TEST_F(ServerTest,OnCallDebuggerGetScriptSource)314 TEST_F(ServerTest, OnCallDebuggerGetScriptSource)
315 {
316     auto scriptId = 0;
317 
318     auto func = [&](auto &handler) {
319         auto scope_chain = std::vector {Scope(Scope::Type::LOCAL, RemoteObject::Number(72))};
320         handler(FrameId(0), std::to_string(0), g_sourceFile, 0, scope_chain);
321     };
322 
323     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.paused", testing::_))
324         .WillOnce([&](testing::Unused, testing::Unused, auto s) { ToObject(std::move(s)); });
325     EXPECT_CALL(server, CallMock(g_sessionId, "Debugger.scriptParsed", testing::_)).Times(1);
326 
327     inspectorServer.CallTargetAttachedToTarget(g_mthread);
328     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, func);
329 
330     EXPECT_CALL(server, OnCallMock("Debugger.getScriptSource", testing::_))
331         .WillOnce([&](testing::Unused, auto handler) {
332             JsonObjectBuilder res;
333             JsonObjectBuilder params;
334             params.AddProperty("scriptId", std::to_string(scriptId));
335             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
336             ASSERT_THAT(JsonObject(std::move(res).Build()),
337                         JsonProperties(JsonProperty<JsonObject::StringT> {"scriptSource", g_sourceFile}));
338         });
339     inspectorServer.OnCallDebuggerGetScriptSource([](auto source) {
340         std::string s(source);
341         return s;
342     });
343 
344     EXPECT_CALL(server, OnCallMock("Debugger.getScriptSource", testing::_))
345         .WillOnce([&](testing::Unused, auto handler) {
346             JsonObjectBuilder res;
347             JsonObject empty;
348             handler(g_sessionId, res, empty);
349             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
350         });
351     inspectorServer.OnCallDebuggerGetScriptSource([](auto) { return "a"; });
352 }
353 
TEST_F(ServerTest,OnCallDebuggerStepOut)354 TEST_F(ServerTest, OnCallDebuggerStepOut)
355 {
356     inspectorServer.CallTargetAttachedToTarget(g_mthread);
357 
358     EXPECT_CALL(server, OnCallMock("Debugger.stepOut", testing::_)).WillOnce(g_simpleHandler);
359 
360     inspectorServer.OnCallDebuggerStepOut([](PtThread thread) {
361         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
362         g_handlerCalled = true;
363     });
364 }
365 
TEST_F(ServerTest,OnCallDebuggerStepInto)366 TEST_F(ServerTest, OnCallDebuggerStepInto)
367 {
368     inspectorServer.CallTargetAttachedToTarget(g_mthread);
369 
370     EXPECT_CALL(server, OnCallMock("Debugger.stepInto", testing::_)).WillOnce(g_simpleHandler);
371 
372     inspectorServer.OnCallDebuggerStepInto([](PtThread thread) {
373         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
374         g_handlerCalled = true;
375     });
376 }
377 
TEST_F(ServerTest,OnCallDebuggerStepOver)378 TEST_F(ServerTest, OnCallDebuggerStepOver)
379 {
380     inspectorServer.CallTargetAttachedToTarget(g_mthread);
381 
382     EXPECT_CALL(server, OnCallMock("Debugger.stepOver", testing::_)).WillOnce(g_simpleHandler);
383 
384     inspectorServer.OnCallDebuggerStepOver([](PtThread thread) {
385         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
386         g_handlerCalled = true;
387     });
388 }
389 
handlerForSetBreak(PtThread thread,const std::function<bool (std::string_view)> & comp,size_t line,std::set<std::string_view> & sources)390 std::optional<BreakpointId> handlerForSetBreak([[maybe_unused]] PtThread thread,
391                                                [[maybe_unused]] const std::function<bool(std::string_view)> &comp,
392                                                size_t line, [[maybe_unused]] std::set<std::string_view> &sources)
393 {
394     sources.insert("source");
395     return BreakpointId(line);
396 }
397 
handlerForSetBreakEmpty(PtThread thread,const std::function<bool (std::string_view)> & comp,size_t line,std::set<std::string_view> & sources)398 std::optional<BreakpointId> handlerForSetBreakEmpty([[maybe_unused]] PtThread thread,
399                                                     [[maybe_unused]] const std::function<bool(std::string_view)> &comp,
400                                                     [[maybe_unused]] size_t line,
401                                                     [[maybe_unused]] std::set<std::string_view> &sources)
402 {
403     sources.insert("source");
404     return {};
405 }
406 
TEST_F(ServerTest,OnCallDebuggerSetBreakpoint)407 TEST_F(ServerTest, OnCallDebuggerSetBreakpoint)
408 {
409     auto scriptId = 0;
410     size_t start = 5;
411 
412     auto func = [&](auto &handler) {
413         auto scope_chain = std::vector {Scope(Scope::Type::LOCAL, RemoteObject::Number(72))};
414         handler(FrameId(0), std::to_string(0), g_sourceFile, 0, scope_chain);
415     };
416 
417     inspectorServer.CallTargetAttachedToTarget(g_mthread);
418     inspectorServer.CallDebuggerPaused(g_mthread, {}, {}, func);
419 
420     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
421         JsonObjectBuilder res;
422         JsonObjectBuilder params;
423         params.AddProperty("location", Location(scriptId, start).ToJson());
424         handler(g_sessionId, res, JsonObject(std::move(params).Build()));
425         ASSERT_THAT(JsonObject(std::move(res).Build()),
426                     JsonProperties(JsonProperty<JsonObject::StringT> {"breakpointId", std::to_string(start)},
427                                    JsonProperty<JsonObject::JsonObjPointer> {
428                                        "actualLocation",
429                                        testing::Pointee(JsonProperties(
430                                            JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
431                                            JsonProperty<JsonObject::NumT> {"lineNumber", start - 1}))}));
432     });
433 
434     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreak);
435 
436     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
437         JsonObjectBuilder res;
438         JsonObject empty;
439         handler(g_sessionId, res, empty);
440         ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
441     });
442 
443     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreak);
444 
445     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpoint", testing::_)).WillOnce([&](testing::Unused, auto handler) {
446         JsonObjectBuilder res;
447         JsonObjectBuilder params;
448         params.AddProperty("location", Location(scriptId, start).ToJson());
449         handler(g_sessionId, res, JsonObject(std::move(params).Build()));
450         ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
451     });
452 
453     inspectorServer.OnCallDebuggerSetBreakpoint(handlerForSetBreakEmpty);
454 }
455 
TEST_F(ServerTest,OnCallDebuggerSetBreakpointByUrl)456 TEST_F(ServerTest, OnCallDebuggerSetBreakpointByUrl)
457 {
458     auto scriptId = 0;
459     size_t start = 5;
460 
461     inspectorServer.CallTargetAttachedToTarget(g_mthread);
462 
463     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointByUrl", testing::_))
464         .WillOnce([&](testing::Unused, auto handler) {
465             JsonObjectBuilder res;
466             JsonObjectBuilder params;
467             params.AddProperty("lineNumber", start);
468             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
469             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
470         });
471 
472     inspectorServer.OnCallDebuggerSetBreakpointByUrl(handlerForSetBreak);
473 
474     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointByUrl", testing::_))
475         .WillOnce([&](testing::Unused, auto handler) {
476             JsonObjectBuilder res;
477             JsonObjectBuilder params;
478             params.AddProperty("lineNumber", start);
479             params.AddProperty("url", "file://source");
480             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
481             std::vector<testing::Matcher<JsonObject::JsonObjPointer>> locations;
482             locations.push_back(testing::Pointee(
483                 JsonProperties(JsonProperty<JsonObject::StringT> {"scriptId", std::to_string(scriptId)},
484                                JsonProperty<JsonObject::NumT> {"lineNumber", start})));
485 
486             ASSERT_THAT(
487                 JsonObject(std::move(res).Build()),
488                 JsonProperties(JsonProperty<JsonObject::StringT> {"breakpointId", std::to_string(start + 1)},
489                                JsonProperty<JsonObject::ArrayT> {"locations", JsonElementsAreArray(locations)}));
490         });
491 
492     inspectorServer.OnCallDebuggerSetBreakpointByUrl(handlerForSetBreak);
493 }
494 
TEST_F(ServerTest,OnCallDebuggerSetBreakpointsActive)495 TEST_F(ServerTest, OnCallDebuggerSetBreakpointsActive)
496 {
497     inspectorServer.CallTargetAttachedToTarget(g_mthread);
498 
499     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
500         .WillOnce([&](testing::Unused, auto handler) {
501             JsonObjectBuilder res;
502             JsonObject empty;
503             handler(g_sessionId, res, empty);
504             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
505             ASSERT_FALSE(g_handlerCalled);
506         });
507 
508     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
509         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
510         ASSERT_FALSE(value);
511         g_handlerCalled = true;
512     });
513 
514     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
515         .WillOnce([&](testing::Unused, auto handler) {
516             JsonObjectBuilder res;
517             JsonObjectBuilder params;
518             params.AddProperty("active", true);
519             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
520             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
521             ASSERT_TRUE(g_handlerCalled);
522             g_handlerCalled = false;
523         });
524 
525     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
526         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
527         ASSERT_TRUE(value);
528         g_handlerCalled = true;
529     });
530 
531     EXPECT_CALL(server, OnCallMock("Debugger.setBreakpointsActive", testing::_))
532         .WillOnce([&](testing::Unused, auto handler) {
533             JsonObjectBuilder res;
534             JsonObjectBuilder params;
535             params.AddProperty("active", false);
536             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
537             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
538             ASSERT_TRUE(g_handlerCalled);
539         });
540 
541     inspectorServer.OnCallDebuggerSetBreakpointsActive([](auto thread, auto value) {
542         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
543         ASSERT_FALSE(value);
544         g_handlerCalled = true;
545     });
546 }
547 
TEST_F(ServerTest,OnCallDebuggerSetPauseOnExceptions)548 TEST_F(ServerTest, OnCallDebuggerSetPauseOnExceptions)
549 {
550     inspectorServer.CallTargetAttachedToTarget(g_mthread);
551 
552     EXPECT_CALL(server, OnCallMock("Debugger.setPauseOnExceptions", testing::_))
553         .WillOnce([&](testing::Unused, auto handler) {
554             JsonObjectBuilder res;
555             JsonObjectBuilder params;
556             params.AddProperty("state", "none");
557             handler(g_sessionId, res, JsonObject(std::move(params).Build()));
558             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
559             ASSERT_TRUE(g_handlerCalled);
560         });
561 
562     inspectorServer.OnCallDebuggerSetPauseOnExceptions([](PtThread thread, PauseOnExceptionsState state) {
563         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
564         ASSERT_EQ(PauseOnExceptionsState::NONE, state);
565         g_handlerCalled = true;
566     });
567 }
568 
TEST_F(ServerTest,OnCallRuntimeEnable)569 TEST_F(ServerTest, OnCallRuntimeEnable)
570 {
571     inspectorServer.CallTargetAttachedToTarget(g_mthread);
572 
573     EXPECT_CALL(server, OnCallMock("Runtime.enable", testing::_)).WillOnce([&](testing::Unused, auto handler) {
574         JsonObjectBuilder res;
575         JsonObject empty;
576         handler(g_sessionId, res, empty);
577         ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
578         ASSERT_TRUE(g_handlerCalled);
579     });
580     inspectorServer.OnCallRuntimeEnable([](PtThread thread) {
581         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
582         g_handlerCalled = true;
583     });
584 }
585 
TEST_F(ServerTest,OnCallRuntimeGetProperties)586 TEST_F(ServerTest, OnCallRuntimeGetProperties)
587 {
588     auto object_id = 6;
589     auto preview = true;
590 
591     inspectorServer.CallTargetAttachedToTarget(g_mthread);
592 
593     EXPECT_CALL(server, OnCallMock("Runtime.getProperties", testing::_)).WillOnce([&](testing::Unused, auto handler) {
594         JsonObjectBuilder res;
595         JsonObjectBuilder params;
596         params.AddProperty("objectId", std::to_string(object_id));
597         params.AddProperty("generatePreview", preview);
598         handler(g_sessionId, res, JsonObject(std::move(params).Build()));
599 
600         std::vector<testing::Matcher<JsonObject::JsonObjPointer>> result;
601         result.push_back(testing::Pointee(JsonProperties(
602             JsonProperty<JsonObject::StringT> {"name", "object"},
603             JsonProperty<JsonObject::JsonObjPointer> {
604                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"value", object_id},
605                                                          JsonProperty<JsonObject::StringT> {"type", "number"}))},
606             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
607             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
608             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
609         result.push_back(testing::Pointee(JsonProperties(
610             JsonProperty<JsonObject::StringT> {"name", "preview"},
611             JsonProperty<JsonObject::JsonObjPointer> {
612                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::BoolT> {"value", preview},
613                                                          JsonProperty<JsonObject::StringT> {"type", "boolean"}))},
614             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
615             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
616             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
617         result.push_back(testing::Pointee(JsonProperties(
618             JsonProperty<JsonObject::StringT> {"name", "threadId"},
619             JsonProperty<JsonObject::JsonObjPointer> {
620                 "value", testing::Pointee(JsonProperties(JsonProperty<JsonObject::NumT> {"value", g_mthread.GetId()},
621                                                          JsonProperty<JsonObject::StringT> {"type", "number"}))},
622             JsonProperty<JsonObject::BoolT> {"writable", testing::_},
623             JsonProperty<JsonObject::BoolT> {"configurable", testing::_},
624             JsonProperty<JsonObject::BoolT> {"enumerable", testing::_})));
625 
626         ASSERT_THAT(JsonObject(std::move(res).Build()),
627                     JsonProperties(JsonProperty<JsonObject::ArrayT> {"result", JsonElementsAreArray(result)}));
628     });
629 
630     auto getProperties = [](PtThread thread, RemoteObjectId id, bool need_preview) {
631         std::vector<PropertyDescriptor> res;
632         res.push_back(PropertyDescriptor("object", RemoteObject::Number(id)));
633         res.push_back(PropertyDescriptor("preview", RemoteObject::Boolean(need_preview)));
634         res.push_back(PropertyDescriptor("threadId", RemoteObject::Number(thread.GetId())));
635         return res;
636     };
637 
638     inspectorServer.OnCallRuntimeGetProperties(getProperties);
639 }
640 
TEST_F(ServerTest,OnCallRuntimeRunIfWaitingForDebugger)641 TEST_F(ServerTest, OnCallRuntimeRunIfWaitingForDebugger)
642 {
643     inspectorServer.CallTargetAttachedToTarget(g_mthread);
644 
645     EXPECT_CALL(server, OnCallMock("Runtime.runIfWaitingForDebugger", testing::_))
646         .WillOnce([&](testing::Unused, auto handler) {
647             JsonObjectBuilder res;
648             JsonObject empty;
649             handler(g_sessionId, res, empty);
650             ASSERT_THAT(JsonObject(std::move(res).Build()), JsonProperties());
651             ASSERT_TRUE(g_handlerCalled);
652         });
653 
654     inspectorServer.OnCallRuntimeRunIfWaitingForDebugger([](PtThread thread) {
655         ASSERT_EQ(thread.GetId(), g_mthread.GetId());
656         g_handlerCalled = true;
657     });
658 }
659 
660 }  // namespace panda::tooling::inspector::test
661 
662 // NOLINTEND
663