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