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 &)> &¶meters) 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 &)> &¶meters));
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