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_ALLOCATIONTRACK_RECURSION_TEST_H
17 #define ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ALLOCATIONTRACK_RECURSION_TEST_H
18
19 #include "tooling/test/client_utils/test_util.h"
20
21 namespace panda::ecmascript::tooling::test {
22 class JsAllocationTrackRecursionTest : public TestActions {
23 public:
JsAllocationTrackRecursionTest()24 JsAllocationTrackRecursionTest()
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 {SocketAction::SEND, "heapprofiler-enable"},
38 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
39 {SocketAction::SEND, "allocationtrack"},
40 {SocketAction::RECV, "", ActionRule::STRING_CONTAIN},
41
42 // set breakpoint
43 {SocketAction::SEND, "b " DEBUGGER_JS_DIR "common_func.js 67"},
44 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
45
46 // hit breakpoint after resume first time
47 {SocketAction::SEND, "resume"},
48 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
49 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
50 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
51
52 {SocketAction::SEND, "allocationtrack-stop"},
53 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
54 [this](auto recv, auto, auto) -> bool { return RecvReportProgress(recv); }},
55 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
56 [this](auto recv, auto, bool &needMoreMsg) -> bool {
57 return RecvReportProgressFinished(recv, needMoreMsg);
58 }},
59 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
60 [this](auto recv, auto, bool &needMoreMsg) -> bool {
61 return RecvReportProgressChunk(recv, needMoreMsg);
62 }},
63 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
64
65 {SocketAction::SEND, "allocationtrack"},
66 {SocketAction::RECV, "", ActionRule::STRING_CONTAIN},
67
68 {SocketAction::SEND, "resume"},
69 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
70 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
71 {SocketAction::RECV, "Debugger.paused", ActionRule::STRING_CONTAIN},
72
73 {SocketAction::SEND, "allocationtrack-stop"},
74 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
75 [this](auto recv, auto, auto) -> bool { return RecvReportProgress(recv); }},
76 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
77 [this](auto recv, auto, bool &needMoreMsg) -> bool {
78 return RecvReportProgressFinished(recv, needMoreMsg);
79 }},
80 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE,
81 [this](auto recv, auto, bool &needMoreMsg) -> bool {
82 return RecvReportProgressChunk(recv, needMoreMsg);
83 }},
84 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
85 {SocketAction::SEND, "heapprofiler-disable"},
86 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
87 // reply success and run
88 {SocketAction::SEND, "success"},
89 {SocketAction::SEND, "resume"},
90 {SocketAction::RECV, "Debugger.resumed", ActionRule::STRING_CONTAIN},
91 {SocketAction::RECV, "", ActionRule::CUSTOM_RULE, MatchRule::replySuccess},
92 };
93 }
94
RecvReportProgress(std::string recv)95 bool RecvReportProgress(std::string recv)
96 {
97 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
98 Result ret;
99 std::string method = "";
100 ret = json->GetString("method", &method);
101 if (ret != Result::SUCCESS) {
102 return false;
103 }
104
105 if (method != "HeapProfiler.reportHeapSnapshotProgress") {
106 return false;
107 }
108 std::unique_ptr<PtJson> params = nullptr;
109 ret = json->GetObject("params", ¶ms);
110 if (ret != Result::SUCCESS) {
111 return false;
112 }
113 int done = 0;
114 ret = params->GetInt("done", &done);
115 if (ret != Result::SUCCESS) {
116 return false;
117 }
118 return true;
119 }
120
RecvReportProgressFinished(std::string recv,bool & needMoreMsg)121 bool RecvReportProgressFinished(std::string recv, bool &needMoreMsg)
122 {
123 needMoreMsg = false;
124 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
125 Result ret;
126 std::string method = "";
127 ret = json->GetString("method", &method);
128 if (ret != Result::SUCCESS) {
129 return false;
130 }
131
132 if (method != "HeapProfiler.reportHeapSnapshotProgress") {
133 return false;
134 }
135
136 std::unique_ptr<PtJson> params = nullptr;
137 ret = json->GetObject("params", ¶ms);
138 if (ret != Result::SUCCESS) {
139 return false;
140 }
141
142 int done = 0;
143 ret = params->GetInt("done", &done);
144 if (ret != Result::SUCCESS) {
145 return false;
146 }
147
148 bool finished = 0;
149 ret = params->GetBool("finished", &finished);
150 if (ret != Result::SUCCESS) {
151 needMoreMsg = true;
152 }
153 return true;
154 }
155
RecvReportProgressChunk(std::string recv,bool & needMoreMsg)156 bool RecvReportProgressChunk(std::string recv, bool &needMoreMsg)
157 {
158 static std::string content = "";
159 needMoreMsg = false;
160 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
161 Result ret;
162 std::string method = "";
163 ret = json->GetString("method", &method);
164 if (ret != Result::SUCCESS) {
165 return false;
166 }
167
168 if (method != "HeapProfiler.addHeapSnapshotChunk") {
169 return false;
170 }
171
172 std::unique_ptr<PtJson> params = nullptr;
173 ret = json->GetObject("params", ¶ms);
174 if (ret != Result::SUCCESS) {
175 return false;
176 }
177
178 std::string chunk = "";
179 ret = params->GetString("chunk", &chunk);
180 if (ret != Result::SUCCESS) {
181 return false;
182 }
183
184 content += chunk;
185 std::unique_ptr<PtJson> contentJson = PtJson::Parse(content);
186 if (contentJson == nullptr || contentJson->Stringify().empty()) {
187 needMoreMsg = true;
188 }
189 return true;
190 }
191
GetEntryPoint()192 std::pair<std::string, std::string> GetEntryPoint() override
193 {
194 return {pandaFile_, entryPoint_};
195 }
196
197 ~JsAllocationTrackRecursionTest() = default;
198
199 private:
200 std::string pandaFile_ = DEBUGGER_ABC_DIR "common_func.abc";
201 std::string sourceFile_ = DEBUGGER_JS_DIR "common_func.js";
202 std::string entryPoint_ = "_GLOBAL::func_main_0";
203 };
204
GetJsAllocationTrackRecursionTest()205 std::unique_ptr<TestActions> GetJsAllocationTrackRecursionTest()
206 {
207 return std::make_unique<JsAllocationTrackRecursionTest>();
208 }
209 } // namespace panda::ecmascript::tooling::test
210
211 #endif // ECMASCRIPT_TOOLING_TEST_TESTCASES_JS_ALLOCATIONTRACK_RECURSION_TEST_H
212