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_STEPOVER_LOOP_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOVER_LOOP_TEST_H
18 
19 #include "tooling/test/client_utils/test_util.h"
20 
21 namespace panda::ecmascript::tooling::test {
22 class JsStepoverLoopTest : public TestActions {
23 public:
JsStepoverLoopTest()24     JsStepoverLoopTest()
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 common_func.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 27"},
39             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
40                 [](auto recv, auto, auto) -> bool {
41                     std::unique_ptr<PtJson> json = PtJson::Parse(recv);
42                     DebuggerClient debuggerClient(0);
43                     debuggerClient.RecvReply(std::move(json));
44                     return true;
45                 }},
46 
47             // hit breakpoint after resume first time
48             {SocketAction::SEND, "resume"},
49             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
50             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
51             {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
52 
53             {SocketAction::SEND, "sov"},
54             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
55             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
56             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
57                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 27); }},
58 
59             {SocketAction::SEND, "sov"},
60             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
61             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
62             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
63                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 28); }},
64 
65             {SocketAction::SEND, "sov"},
66             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
67             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
68             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
69                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 26); }},
70 
71             {SocketAction::SEND, "sov"},
72             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
73             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
74             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
75                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 27); }},
76 
77             {SocketAction::SEND, "sov"},
78             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
79             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
80             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
81                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 28); }},
82 
83             {SocketAction::SEND, "sov"},
84             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
85             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
86             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
87                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "for_loop", 26); }},
88 
89             {SocketAction::SEND, "delete 1"},
90             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
91 
92             {SocketAction::SEND, "b " DEBUGGER_JS_DIR "common_func.js 35"},
93             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
94                 [](auto recv, auto, auto) -> bool {
95                     std::unique_ptr<PtJson> json = PtJson::Parse(recv);
96                     DebuggerClient debuggerClient(0);
97                     debuggerClient.RecvReply(std::move(json));
98                     return true;
99                 }},
100             {SocketAction::SEND, "resume"},
101             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
102             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
103             {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
104 
105             {SocketAction::SEND, "sov"},
106             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
107             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
108             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
109                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 35); }},
110 
111             {SocketAction::SEND, "sov"},
112             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
113             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
114             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
115                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 36); }},
116 
117             {SocketAction::SEND, "sov"},
118             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
119             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
120             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
121                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 37); }},
122             {SocketAction::SEND, "sov"},
123             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
124             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
125             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
126                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 38); }},
127 
128             {SocketAction::SEND, "sov"},
129             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
130             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
131             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
132                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 35); }},
133             {SocketAction::SEND, "sov"},
134             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
135             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
136             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
137                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 36); }},
138 
139             {SocketAction::SEND, "sov"},
140             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
141             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
142             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
143                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 37); }},
144             {SocketAction::SEND, "sov"},
145             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
146             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
147             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE,
148                 [this](auto recv, auto, auto) -> bool { return RecvStepoverInfo(recv, "while_loop", 38); }},
149 
150             {SocketAction::SEND, "delete 1"},
151             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
152             {SocketAction::SEND, "resume"},
153             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
154             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
155             {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
156 
157             // reply success and run
158             {SocketAction::SEND, "success"},
159             {SocketAction::SEND, "resume"},
160             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
161             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
162         };
163     }
164 
RecvStepoverInfo(std::string recv, std::string funcName, int lineNumber)165     bool RecvStepoverInfo(std::string recv, std::string funcName, int lineNumber)
166     {
167         std::unique_ptr<PtJson> json = PtJson::Parse(recv);
168         Result ret;
169         std::string method = "";
170         ret = json->GetString("method", &method);
171         if (ret != Result::SUCCESS || method != "Debugger.paused") {
172             return false;
173         }
174 
175         std::unique_ptr<PtJson> params = nullptr;
176         ret = json->GetObject("params", &params);
177         if (ret != Result::SUCCESS) {
178             return false;
179         }
180 
181         std::unique_ptr<PtJson> callFrames = nullptr;
182         ret = params->GetArray("callFrames", &callFrames);
183         if (ret != Result::SUCCESS) {
184             return false;
185         }
186 
187         std::string functionName = "";
188         ret = callFrames->Get(0)->GetString("functionName", &functionName);
189         if (ret != Result::SUCCESS || functionName != funcName) {
190             return false;
191         }
192 
193         std::unique_ptr<PtJson> location = nullptr;
194         ret = callFrames->Get(0)->GetObject("location", &location);
195         if (ret != Result::SUCCESS) {
196             return false;
197         }
198 
199         int lineNum = 0;
200         ret = location->GetInt("lineNumber", &lineNum);
201         if (ret != Result::SUCCESS || lineNum != lineNumber) {
202             return false;
203         }
204 
205         DebuggerClient debuggerClient(0);
206         debuggerClient.PausedReply(std::move(json));
207         return true;
208     }
209 
210     std::pair<std::string, std::string> GetEntryPoint() override
211     {
212         return {pandaFile_, entryPoint_};
213     }
214     ~JsStepoverLoopTest() = default;
215 
216 private:
217     std::string pandaFile_ = DEBUGGER_ABC_DIR "common_func.abc";
218     std::string sourceFile_ = DEBUGGER_JS_DIR "common_func.js";
219     std::string entryPoint_ = "_GLOBAL::func_main_0";
220 };
221 
GetJsStepoverLoopTest()222 std::unique_ptr<TestActions> GetJsStepoverLoopTest()
223 {
224     return std::make_unique<JsStepoverLoopTest>();
225 }
226 }  // namespace panda::ecmascript::tooling::test
227 
228 #endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_STEPOVER_LOOP_TEST_H
229