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
22namespace panda::ecmascript::tooling::test {
23class JsClosureScopeTest : public TestActions {
24public:
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
337private:
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
343std::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