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 #ifndef ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_CLOSURE_SCOPE_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_CLOSURE_SCOPE_TEST_H
18 
19 #include <map>
20 #include "tooling/test/client_utils/test_util.h"
21 
22 namespace panda::ecmascript::tooling::test {
23 class JsClosureScopeTest : public TestActions {
24 public:
JsClosureScopeTest()25     JsClosureScopeTest()
26     {
27         testAction = {
28             {SocketAction::SEND, "enable"},
29             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
30             {SocketAction::SEND, "runtime-enable"},
31             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
32             {SocketAction::SEND, "run"},
33             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
34             // load closure_scope.js
35             {SocketAction::RECV, "Debugger.scriptParsed", ActionRule::STRING_CONTAIN},
36             // break on start
37             {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
38             // set first breakpoint
39             {SocketAction::SEND, "b " DEBUGGER_JS_DIR "closure_scope.js 30"},
40             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
41             // // set second breakpoint
42             {SocketAction::SEND, "b " DEBUGGER_JS_DIR "closure_scope.js 53"},
43             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
44 
45             // hit breakpoint after resume first time
46             {SocketAction::SEND, "resume"},
47             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
48             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
49             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
50                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
51                 Result ret;
52                 std::string method;
53                 ret = json->GetString("method", &method);
54                 if (ret != Result::SUCCESS || method != "Debugger.paused") {
55                     return false;
56                 }
57 
58                 DebuggerClient debuggerClient(0);
59                 debuggerClient.PausedReply(std::move(json));
60                 return true;
61             }},
62             {SocketAction::SEND, "print"},
63             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
64                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
65                 int32_t id = 0;
66                 Result ret = json->GetInt("id", &id);
67                 if (ret != Result::SUCCESS) {
68                     return false;
69                 }
70                 RuntimeClient runtimeClient(0);
71                 runtimeClient.HandleGetProperties(std::move(json), id);
72                 return true;
73             }},
74             {SocketAction::SEND, "print 2"},
75             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
76                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
77                 Result ret;
78                 int32_t id = 0;
79                 ret = json->GetInt("id", &id);
80                 if (ret != Result::SUCCESS) {
81                     return false;
82                 }
83 
84                 std::unique_ptr<PtJson> result = nullptr;
85                 ret = json->GetObject("result", &result);
86                 if (ret != Result::SUCCESS) {
87                     return false;
88                 }
89 
90                 std::unique_ptr<PtJson> innerResult;
91                 ret = result->GetArray("result", &innerResult);
92                 if (ret != Result::SUCCESS) {
93                     return false;
94                 }
95 
96                 std::string name;
97                 ret = innerResult->Get(0)->GetString("name", &name);
98                 if (ret != Result::SUCCESS || name != "v3") {
99                     return false;
100                 }
101 
102                 std::unique_ptr<PtJson> value;
103                 ret = innerResult->Get(0)->GetObject("value", &value);
104                 if (ret != Result::SUCCESS) {
105                     return false;
106                 }
107 
108                 std::string valueDes;
109                 ret = value->GetString("description", &valueDes);
110                 if (ret != Result::SUCCESS || valueDes != "4") {
111                     return false;
112                 }
113                 return true;
114             }},
115             {SocketAction::SEND, "print 3"},
116             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
117                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
118                 Result ret;
119                 int32_t id = 0;
120                 ret = json->GetInt("id", &id);
121                 if (ret != Result::SUCCESS) {
122                     return false;
123                 }
124 
125                 std::unique_ptr<PtJson> result = nullptr;
126                 ret = json->GetObject("result", &result);
127                 if (ret != Result::SUCCESS) {
128                     return false;
129                 }
130 
131                 std::unique_ptr<PtJson> innerResult;
132                 ret = result->GetArray("result", &innerResult);
133                 if (ret != Result::SUCCESS) {
134                     return false;
135                 }
136 
137                 std::string name;
138                 ret = innerResult->Get(0)->GetString("name", &name);
139                 if (ret != Result::SUCCESS || name != "v2_2") {
140                     return false;
141                 }
142 
143                 std::unique_ptr<PtJson> value;
144                 ret = innerResult->Get(0)->GetObject("value", &value);
145                 if (ret != Result::SUCCESS) {
146                     return false;
147                 }
148 
149                 std::string valueDes;
150                 ret = value->GetString("description", &valueDes);
151                 if (ret != Result::SUCCESS || valueDes != "3") {
152                     return false;
153                 }
154 
155                 ret = innerResult->Get(1)->GetString("name", &name);
156                 if (ret != Result::SUCCESS || name != "v2_1") {
157                     return false;
158                 }
159 
160                 ret = innerResult->Get(1)->GetObject("value", &value);
161                 if (ret != Result::SUCCESS) {
162                     return false;
163                 }
164 
165                 ret = value->GetString("description", &valueDes);
166                 if (ret != Result::SUCCESS || valueDes != "2") {
167                     return false;
168                 }
169                 return true;
170             }},
171             {SocketAction::SEND, "print 4"},
172             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
173                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
174                 Result ret;
175                 int32_t id = 0;
176                 ret = json->GetInt("id", &id);
177                 if (ret != Result::SUCCESS) {
178                     return false;
179                 }
180 
181                 std::unique_ptr<PtJson> result = nullptr;
182                 ret = json->GetObject("result", &result);
183                 if (ret != Result::SUCCESS) {
184                     return false;
185                 }
186 
187                 std::unique_ptr<PtJson> innerResult;
188                 ret = result->GetArray("result", &innerResult);
189                 if (ret != Result::SUCCESS) {
190                     return false;
191                 }
192 
193                 std::string name;
194                 ret = innerResult->Get(0)->GetString("name", &name);
195                 if (ret != Result::SUCCESS || name != "v1") {
196                     return false;
197                 }
198 
199                 std::unique_ptr<PtJson> value;
200                 ret = innerResult->Get(0)->GetObject("value", &value);
201                 if (ret != Result::SUCCESS) {
202                     return false;
203                 }
204 
205                 std::string valueDes;
206                 ret = value->GetString("description", &valueDes);
207                 if (ret != Result::SUCCESS || valueDes != "1") {
208                     return false;
209                 }
210                 return true;
211             }},
212 
213             // hit breakpoint after resume second time
214             {SocketAction::SEND, "resume"},
215             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
216             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
217             {SocketAction::RECV, "Debugger.paused", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
218                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
219                 Result ret;
220                 std::string method;
221                 ret = json->GetString("method", &method);
222                 if (ret != Result::SUCCESS || method != "Debugger.paused") {
223                     return false;
224                 }
225                 DebuggerClient debuggerClient(0);
226                 debuggerClient.PausedReply(std::move(json));
227                 return true;
228             }},
229             {SocketAction::SEND, "print"},
230             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
231                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
232                 int32_t id = 0;
233                 Result ret = json->GetInt("id", &id);
234                 if (ret != Result::SUCCESS) {
235                     return false;
236                 }
237                 RuntimeClient runtimeClient(0);
238                 runtimeClient.HandleGetProperties(std::move(json), id);
239                 return true;
240             }},
241             {SocketAction::SEND, "print 2"},
242             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
243                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
244                 Result ret;
245                 int32_t id = 0;
246                 ret = json->GetInt("id", &id);
247                 if (ret != Result::SUCCESS) {
248                     return false;
249                 }
250 
251                 std::unique_ptr<PtJson> result = nullptr;
252                 ret = json->GetObject("result", &result);
253                 if (ret != Result::SUCCESS) {
254                     return false;
255                 }
256 
257                 std::unique_ptr<PtJson> innerResult;
258                 ret = result->GetArray("result", &innerResult);
259                 if (ret != Result::SUCCESS) {
260                     return false;
261                 }
262 
263                 std::string name;
264                 ret = innerResult->Get(0)->GetString("name", &name);
265                 if (ret != Result::SUCCESS || name != "i") {
266                     return false;
267                 }
268 
269                 std::unique_ptr<PtJson> value;
270                 ret = innerResult->Get(0)->GetObject("value", &value);
271                 if (ret != Result::SUCCESS) {
272                     return false;
273                 }
274 
275                 std::string valueDes;
276                 ret = value->GetString("description", &valueDes);
277                 if (ret != Result::SUCCESS || valueDes != "5") {
278                     return false;
279                 }
280                 return true;
281             }},
282             {SocketAction::SEND, "print 3"},
283             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, [] (auto recv, auto, auto) -> bool {
284                 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
285                 Result ret;
286                 int32_t id = 0;
287                 ret = json->GetInt("id", &id);
288                 if (ret != Result::SUCCESS) {
289                     return false;
290                 }
291 
292                 std::unique_ptr<PtJson> result = nullptr;
293                 ret = json->GetObject("result", &result);
294                 if (ret != Result::SUCCESS) {
295                     return false;
296                 }
297 
298                 std::unique_ptr<PtJson> innerResult;
299                 ret = result->GetArray("result", &innerResult);
300                 if (ret != Result::SUCCESS) {
301                     return false;
302                 }
303 
304                 std::string name;
305                 ret = innerResult->Get(0)->GetString("name", &name);
306                 if (ret != Result::SUCCESS || name != "a") {
307                     return false;
308                 }
309 
310                 std::unique_ptr<PtJson> value;
311                 ret = innerResult->Get(0)->GetObject("value", &value);
312                 if (ret != Result::SUCCESS) {
313                     return false;
314                 }
315 
316                 std::string valueDes;
317                 ret = value->GetString("description", &valueDes);
318                 if (ret != Result::SUCCESS || valueDes != "10") {
319                     return false;
320                 }
321                 return true;
322             }},
323             // reply success and run
324             {SocketAction::SEND, "success"},
325             {SocketAction::SEND, "resume"},
326             {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
327             {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
328         };
329     }
330 
331     std::pair<std::string, std::string> GetEntryPoint() override
332     {
333         return {pandaFile_, entryPoint_};
334     }
335     ~JsClosureScopeTest() = default;
336 
337 private:
338     std::string pandaFile_ = DEBUGGER_ABC_DIR "closure_scope.abc";
339     std::string sourceFile_ = DEBUGGER_JS_DIR "closure_scope.js";
340     std::string entryPoint_ = "_GLOBAL::func_main_0";
341 };
342 
GetJsClosureScopeTest()343 std::unique_ptr<TestActions> GetJsClosureScopeTest()
344 {
345     return std::make_unique<JsClosureScopeTest>();
346 }
347 }  // namespace panda::ecmascript::tooling::test
348 
349 #endif  // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_CLOSURE_SCOPE_TEST_H
350