1 /*
2 * Copyright (c) 2024 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 #ifndef ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_BREAKPOINT_LOOP_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_BREAKPOINT_LOOP_TEST_H
18
19 #include "tooling/test/client_utils/test_util.h"
20
21 namespace panda::ecmascript::tooling::test {
22 class JsBreakpointLoopTest : public TestActions {
23 public:
JsBreakpointLoopTest()24 JsBreakpointLoopTest()
25 {
26 testAction = {
27 {SocketAction::SEND, "enable"},
28 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
29 {SocketAction::SEND, "runtime-enable"},
30 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
31 {SocketAction::SEND, "run"},
32 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
33 // load closure_scope.js
34 {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN},
35 // break on start
36 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
37 // set first breakpoint
38 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "common_func.js 29"},
39 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
40 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "common_func.js 37"},
41 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
42 [](auto recv, auto, auto) -> bool {
43 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
44 DebuggerClient debuggerClient(0);
45 debuggerClient.RecvReply(std::move(json));
46 return true;
47 }},
48
49 // hit breakpoint after resume first time
50 {SocketAction::SEND, "resume"},
51 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
52 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
53 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
54
55 {SocketAction::SEND, "resume"},
56 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
57 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
58 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
59 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv, "for_loop", 28); }},
60
61 {SocketAction::SEND, "resume"},
62 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
63 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
64 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
65 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv, "for_loop", 28); }},
66
67 {SocketAction::SEND, "resume"},
68 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
69 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
70 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
71
72 {SocketAction::SEND, "resume"},
73 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
74 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
75 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
76 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv, "while_loop", 36); }},
77
78 {SocketAction::SEND, "resume"},
79 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
80 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
81 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
82 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv, "while_loop", 36); }},
83
84 {SocketAction::SEND, "resume"},
85 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
86 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
87 {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
88 [this](auto recv, auto, auto) -> bool { return RecvBreakInfo(recv, "while_loop", 36); }},
89
90 {SocketAction::SEND, "delete 1"},
91 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
92 {SocketAction::SEND, "resume"},
93 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
94 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
95 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
96
97 // reply success and run
98 {SocketAction::SEND, "success"},
99 {SocketAction::SEND, "resume"},
100 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
101 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
102 };
103 }
104
RecvBreakInfo(std::string recv, std::string funcName, int lineNumber)105 bool RecvBreakInfo(std::string recv, std::string funcName, int lineNumber)
106 {
107 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
108 Result ret;
109 std::string method = "";
110 ret = json->GetString("method", &method);
111 if (ret != Result::SUCCESS || method != "Debugger.paused") {
112 return false;
113 }
114
115 std::unique_ptr<PtJson> params = nullptr;
116 ret = json->GetObject("params", ¶ms);
117 if (ret != Result::SUCCESS) {
118 return false;
119 }
120
121 std::unique_ptr<PtJson> callFrames = nullptr;
122 ret = params->GetArray("callFrames", &callFrames);
123 if (ret != Result::SUCCESS) {
124 return false;
125 }
126
127 std::string functionName = "";
128 ret = callFrames->Get(0)->GetString("functionName", &functionName);
129 if (ret != Result::SUCCESS || functionName != funcName) {
130 return false;
131 }
132
133 std::unique_ptr<PtJson> location = nullptr;
134 ret = callFrames->Get(0)->GetObject("location", &location);
135 if (ret != Result::SUCCESS) {
136 return false;
137 }
138
139 int lineNum = 0;
140 ret = location->GetInt("lineNumber", &lineNum);
141 if (ret != Result::SUCCESS || lineNum != lineNumber) {
142 return false;
143 }
144
145 DebuggerClient debuggerClient(0);
146 debuggerClient.PausedReply(std::move(json));
147 return true;
148 }
149
150 std::pair<std::string, std::string> GetEntryPoint() override
151 {
152 return {pandaFile_, entryPoint_};
153 }
154 ~JsBreakpointLoopTest() = default;
155
156 private:
157 std::string pandaFile_ = DEBUGGER_ABC_DIR "common_func.abc";
158 std::string sourceFile_ = DEBUGGER_JS_DIR "common_func.js";
159 std::string entryPoint_ = "_GLOBAL::func_main_0";
160 };
161
GetJsBreakpointLoopTest()162 std::unique_ptr<TestActions> GetJsBreakpointLoopTest()
163 {
164 return std::make_unique<JsBreakpointLoopTest>();
165 }
166 } // namespace panda::ecmascript::tooling::test
167
168 #endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_BREAKPOINT_LOOP_TEST_H
169