• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/dynamic/test/client_utils/test_util.h"
17 
18 #include "tooling/dynamic/client/domain/debugger_client.h"
19 #include "tooling/dynamic/client/domain/runtime_client.h"
20 #include "tooling/dynamic/client/utils/cli_command.h"
21 #include "tooling/dynamic/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 
__anonb852e75d0102(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", &params);
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