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 26namespace panda::ecmascript::tooling::test { 27TestMap TestUtil::testMap_; 28 29MatchFunc 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 52std::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 74void 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 83void 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 92void 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 144void 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 180void 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