1 /*
2 * Copyright (c) 2021 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 #include "tooling/test/client_utils/test_util.h"
17
18 #include "tooling/client/domain/debugger_client.h"
19 #include "tooling/client/domain/runtime_client.h"
20 #include "tooling/client/utils/cli_command.h"
21 #include "tooling/client/session/session.h"
22 #include "websocket/client/websocket_client.h"
23
24 #include <cstring>
25
26 namespace panda::ecmascript::tooling::test {
27 TestMap TestUtil::testMap_;
28
__anond135e1a70102(auto recv, auto, auto) 29 MatchFunc MatchRule::replySuccess = [] (auto recv, auto, auto) -> bool {
30 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
31 Result ret;
32 int32_t id = 0;
33 ret = json->GetInt("id", &id);
34 if (ret != Result::SUCCESS) {
35 return false;
36 }
37
38 std::unique_ptr<PtJson> result = nullptr;
39 ret = json->GetObject("result", &result);
40 if (ret != Result::SUCCESS) {
41 return false;
42 }
43
44 int32_t code = 0;
45 ret = result->GetInt("code", &code);
46 if (ret != Result::NOT_EXIST) {
47 return false;
48 }
49 return true;
50 };
51
operator <<(std::ostream & out,ActionRule value)52 std::ostream &operator<<(std::ostream &out, ActionRule value)
53 {
54 const char *s = nullptr;
55
56 #define ADD_CASE(entry) \
57 case (entry): \
58 s = #entry; \
59 break
60
61 switch (value) {
62 ADD_CASE(ActionRule::STRING_EQUAL);
63 ADD_CASE(ActionRule::STRING_CONTAIN);
64 ADD_CASE(ActionRule::CUSTOM_RULE);
65 default: {
66 ASSERT(false && "Unknown ActionRule");
67 }
68 }
69 #undef ADD_CASE
70
71 return out << s;
72 }
73
NotifySuccess()74 void TestUtil::NotifySuccess()
75 {
76 std::vector<std::string> cliCmdStr = { "success" };
77 CliCommand cmd(cliCmdStr, 0);
78 if (cmd.ExecCommand() == ErrCode::ERR_FAIL) {
79 LOG_DEBUGGER(ERROR) << "ExecCommand Test.success fail";
80 }
81 }
82
NotifyFail()83 void TestUtil::NotifyFail()
84 {
85 std::vector<std::string> cliCmdStr = { "fail" };
86 CliCommand cmd(cliCmdStr, 0);
87 if (cmd.ExecCommand() == ErrCode::ERR_FAIL) {
88 LOG_DEBUGGER(ERROR) << "ExecCommand Test.fail fail";
89 }
90 }
91
ForkSocketClient(int port,const std::string & name)92 void TestUtil::ForkSocketClient([[maybe_unused]] int port, const std::string &name)
93 {
94 #ifdef OHOS_PLATFORM
95 auto correntPid = getpid();
96 #endif
97 pid_t pid = fork();
98 if (pid < 0) {
99 LOG_DEBUGGER(FATAL) << "fork error";
100 UNREACHABLE();
101 } else if (pid == 0) {
102 LOG_DEBUGGER(INFO) << "fork son pid: " << getpid();
103 std::this_thread::sleep_for(std::chrono::microseconds(500000)); // 500000: 500ms for wait debugger
104 #ifdef OHOS_PLATFORM
105 std::string pidStr = std::to_string(correntPid);
106 std::string sockInfo = pidStr + "PandaDebugger";
107 #else
108 std::string sockInfo = std::to_string(port);
109 #endif
110 int ret = SessionManager::getInstance().CreateTestSession(sockInfo);
111 LOG_ECMA_IF(ret, FATAL) << "CreateTestSession fail";
112
113 WebSocketClient &client = SessionManager::getInstance().GetCurrentSession()->GetWebSocketClient();
114 auto &testAction = TestUtil::GetTest(name)->testAction;
115 for (const auto &action: testAction) {
116 LOG_DEBUGGER(INFO) << "message: " << action.message;
117 bool success = true;
118 if (action.action == SocketAction::SEND) {
119 std::vector<std::string> cliCmdStr = Utils::SplitString(action.message, " ");
120 CliCommand cmd(cliCmdStr, 0);
121 success = (cmd.ExecCommand() == ErrCode::ERR_OK);
122 } else {
123 ASSERT(action.action == SocketAction::RECV);
124 std::string recv = client.Decode();
125 HandleAcceptanceMessages(action, client, recv, success);
126 SendMessage(action, recv);
127 LOG_DEBUGGER(INFO) << "recv: " << recv;
128 LOG_DEBUGGER(INFO) << "rule: " << action.rule;
129 }
130 if (!success) {
131 LOG_DEBUGGER(ERROR) << "Notify fail";
132 NotifyFail();
133 SessionManager::getInstance().DelSessionById(0);
134 exit(-1);
135 }
136 }
137
138 SessionManager::getInstance().DelSessionById(0);
139 exit(0);
140 }
141 LOG_DEBUGGER(INFO) << "ForkSocketClient end";
142 }
143
HandleAcceptanceMessages(ActionInfo action,WebSocketClient & client,std::string & recv,bool & success)144 void TestUtil::HandleAcceptanceMessages(ActionInfo action, WebSocketClient &client, std::string &recv, bool &success)
145 {
146 if (recv.empty()) {
147 LOG_DEBUGGER(ERROR) << "Notify fail";
148 NotifyFail();
149 SessionManager::getInstance().DelSessionById(0);
150 exit(-1);
151 }
152 int times = 0;
153 while ((!strcmp(recv.c_str(), "try again")) && (times <= 5)) { // 5: five times
154 std::this_thread::sleep_for(std::chrono::microseconds(500000)); // 500000: 500ms
155 recv = client.Decode();
156 times++;
157 }
158 switch (action.rule) {
159 case ActionRule::STRING_EQUAL: {
160 success = (recv == action.message);
161 break;
162 }
163 case ActionRule::STRING_CONTAIN: {
164 success = (recv.find(action.message) != std::string::npos);
165 break;
166 }
167 case ActionRule::CUSTOM_RULE: {
168 bool needMoreMsg = false;
169 success = action.matchFunc(recv, action.message, needMoreMsg);
170 while (needMoreMsg) {
171 recv = client.Decode();
172 success = action.matchFunc(recv, action.message, needMoreMsg);
173 }
174 break;
175 }
176 }
177 return;
178 }
179
SendMessage(ActionInfo action,std::string recv)180 void TestUtil::SendMessage(ActionInfo action, std::string recv)
181 {
182 switch (action.event) {
183 case TestCase::SOURCE: {
184 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
185 std::unique_ptr<PtJson> params = nullptr;
186 Result ret = json->GetObject("params", ¶ms);
187 std::string scriptId;
188 ret = params->GetString("scriptId", &scriptId);
189 if (ret != Result::SUCCESS) {
190 return;
191 }
192 SessionManager::getInstance().GetCurrentSession()->
193 GetSourceManager().SendRequeSource(std::atoi(scriptId.c_str()));
194 break;
195 }
196 case TestCase::WATCH: {
197 if (!SessionManager::getInstance().GetCurrentSession()->GetWatchManager().GetWatchInfoSize()) {
198 SessionManager::getInstance().GetCurrentSession()->GetWatchManager().AddWatchInfo("a");
199 SessionManager::getInstance().GetCurrentSession()->GetWatchManager().AddWatchInfo("this");
200 }
201 const uint watchInfoSize = 2;
202 for (uint i = 0; i < watchInfoSize; i++) {
203 SessionManager::getInstance().GetCurrentSession()->GetWatchManager().SendRequestWatch(i, "0");
204 }
205 break;
206 }
207 case TestCase::WATCH_OBJECT: {
208 std::unique_ptr<PtJson> json = PtJson::Parse(recv);
209 std::unique_ptr<PtJson> result = nullptr;
210 Result ret = json->GetObject("result", &result);
211 std::unique_ptr<PtJson> watchResult = nullptr;
212 ret = result->GetObject("result", &watchResult);
213 if (ret != Result::SUCCESS) {
214 return;
215 }
216 std::string objectId;
217 ret = watchResult->GetString("objectId", &objectId);
218 if (ret != Result::SUCCESS) {
219 return;
220 }
221 SessionManager::getInstance().GetCurrentSession()->GetWatchManager().GetPropertiesCommand(0, objectId);
222 break;
223 }
224 default: {
225 return;
226 }
227 }
228 return;
229 }
230 } // namespace panda::ecmascript::tooling::test
231