1 /*
2 * Copyright (c) 2022 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 "special_test_flow.h"
17
18 #include <string>
19 #include "ability_manager_client.h"
20 #include "report.h"
21 #include "string_ex.h"
22 #include "wukong_define.h"
23
24 namespace OHOS {
25 namespace WuKong {
26 namespace {
27 const std::string SPECIAL_TEST_HELP_MSG =
28 "usage: wukong special [<arguments>]\n"
29 "These are wukong special arguments list:\n"
30 " -h, --help special test help\n"
31 " -t, --touch[x,y] touch event \n"
32 " -c, --count total count of test\n"
33 " -i, --interval interval\n"
34 " -S, --swap[option] swap event\n"
35 " option is -s| -e| -b\n"
36 " -s, --start: the start point of swap\n"
37 " -e, --end: the end point of swap\n"
38 " -b, --bilateral: swap go and back\n"
39 " -k, --spec_insomnia power on/off event\n"
40 " -T, --time total time of test\n"
41 " -C, --component component event\n"
42 " -p, --screenshot get screenshot(only in componment input)\n"
43 " -r, --record record user operation\n"
44 " -R, --replay replay user operation\n"
45 " -u, --uitest uitest dumpLayout\n";
46
47 const std::string SHORT_OPTIONS = "c:hi:T:t:kSbs:e:C:pr:R:u:";
48 const struct option LONG_OPTIONS[] = {
49 {"count", required_argument, nullptr, 'c'}, // test count
50 {"help", no_argument, nullptr, 'h'}, // help information
51 {"interval", required_argument, nullptr, 'i'}, // test interval
52 {"touch", required_argument, nullptr, 't'}, // touch
53 {"spec_insomnia", no_argument, nullptr, 'k'}, // sleep and awake
54 {"time", required_argument, nullptr, 'T'}, // test time
55 {"swap", required_argument, nullptr, 'S'}, // swap
56 {"bilateral", no_argument, nullptr, 'b'}, // swap go and back
57 {"start", no_argument, nullptr, 's'}, // the start point of swap
58 {"end", no_argument, nullptr, 'e'}, // the end point of swap
59 {"component", required_argument, nullptr, 'C'}, // the end point of swap
60 {"screenshot", no_argument, nullptr, 'p'}, // get photo of screenshot
61 {"record", required_argument, nullptr, 'r'}, // record user operation
62 {"replay", required_argument, nullptr, 'R'}, // replay user operation
63 {"uitest", no_argument, nullptr, 'u'} // uitest dumpLayout
64 };
65 const int ONE_MINUTE = 60000;
66 bool g_commandSWAPENABLE = false;
67 bool g_commandHELPENABLE = false;
68 bool g_commandTIMEENABLE = false;
69 bool g_commandTOUCHENABLE = false;
70 bool g_commandPOWERENABLE = false;
71 bool g_commandGOBACKENABLE = false;
72 bool g_commandCOUNTENABLE = false;
73 bool g_commandCOMPONENTENABLE = false;
74 bool g_commandSCREENSHOTENABLE = false;
75 bool g_commandRECORDABLE = false;
76 bool g_commandREPLAYABLE = false;
77 bool g_commandUITEST = false;
78
79 const int NUMBER_TWO = 2;
80 } // namespace
81 using namespace std;
82
SpecialTestFlow(WuKongShellCommand & shellcommand)83 SpecialTestFlow::SpecialTestFlow(WuKongShellCommand &shellcommand) : TestFlow(shellcommand)
84 {
85 }
86
~SpecialTestFlow()87 SpecialTestFlow::~SpecialTestFlow()
88 {
89 if (timer_ != nullptr) {
90 timer_->Shutdown();
91 timer_->Unregister(timerId_);
92 timer_ = nullptr;
93 }
94 }
95
EnvInit()96 ErrCode SpecialTestFlow::EnvInit()
97 {
98 ErrCode result = OHOS::ERR_OK;
99 const std::string paramError = "param is incorrect";
100 if (g_commandSWAPENABLE == true) {
101 if (swapStartPoint_.size() == NUMBER_TWO && swapEndPoint_.size() == NUMBER_TWO) {
102 // set the params of touch special test
103 std::shared_ptr<SwapParam> swapParam = std::make_shared<SwapParam>();
104 swapParam->startX_ = stoi(swapStartPoint_[0]);
105 swapParam->startY_ = stoi(swapStartPoint_[1]);
106 swapParam->endX_ = stoi(swapEndPoint_[0]);
107 swapParam->endY_ = stoi(swapEndPoint_[1]);
108 swapParam->isGoBack_ = g_commandGOBACKENABLE;
109 if (specialTestObject_ == nullptr) {
110 specialTestObject_ = swapParam;
111 }
112 } else {
113 DEBUG_LOG(paramError.c_str());
114 shellcommand_.ResultReceiverAppend(paramError + "\n");
115 result = OHOS::ERR_INVALID_VALUE;
116 }
117 } else if (g_commandTOUCHENABLE == true) {
118 if (touchParam_.size() == NUMBER_TWO) {
119 // set the params of swap special test
120 std::shared_ptr<TouchParam> touchParam = std::make_shared<TouchParam>();
121 touchParam->x_ = stoi(touchParam_[0]);
122 touchParam->y_ = stoi(touchParam_[1]);
123 if (specialTestObject_ == nullptr) {
124 specialTestObject_ = touchParam;
125 }
126 } else {
127 DEBUG_LOG(paramError.c_str());
128 shellcommand_.ResultReceiverAppend(paramError + "\n");
129 result = OHOS::ERR_INVALID_VALUE;
130 }
131 } else if (g_commandCOMPONENTENABLE == true) {
132 std::shared_ptr<ComponentParam> componentParam = std::make_shared<ComponentParam>();
133 for (auto name : bundleName_) {
134 componentParam->PushBundleName(name);
135 }
136 componentParam->isAllFinished_ = false;
137 specialTestObject_ = componentParam;
138 } else if (g_commandRECORDABLE == true) {
139 std::shared_ptr<RecordParam> recordParam = std::make_shared<RecordParam>();
140 recordParam->recordName_ = specialRecordName_;
141 recordParam->recordStatus_ = true;
142 if (specialTestObject_ == nullptr) {
143 specialTestObject_ = recordParam;
144 }
145 } else if (g_commandREPLAYABLE == true) {
146 std::shared_ptr<RecordParam> replayParam = std::make_shared<RecordParam>();
147 replayParam->recordName_ = specialRecordName_;
148 replayParam->recordStatus_ = false;
149 if (specialTestObject_ == nullptr) {
150 specialTestObject_ = replayParam;
151 }
152 }
153
154 // if time test flow, register timer.
155 if (g_commandTIMEENABLE) {
156 RegisterTimer();
157 }
158 return result;
159 }
160
RunStep()161 ErrCode SpecialTestFlow::RunStep()
162 {
163 // control the count test flow
164 if (g_commandCOUNTENABLE == true) {
165 totalCount_--;
166 if (totalCount_ < 0) {
167 isFinished_ = true;
168 return OHOS::ERR_OK;
169 }
170 }
171 // order test
172 ErrCode result;
173 if (g_commandSCREENSHOTENABLE) {
174 std::string screenStorePath;
175 result = WuKongUtil::GetInstance()->WukongScreenCap(screenStorePath, g_commandUITEST);
176 if (result == OHOS::ERR_OK) {
177 Report::GetInstance()->RecordScreenPath(screenStorePath);
178 }
179 }
180 InputType inputTypeId = DistrbuteInputType();
181 std::shared_ptr<InputAction> inputaction = InputFactory::GetInputAction(inputTypeId);
182 result = inputaction->OrderInput(specialTestObject_);
183 if (result != OHOS::ERR_OK) {
184 WARN_LOG("This test failed");
185 }
186 if (!g_commandPOWERENABLE) {
187 if (ProtectRightAbility() == OHOS::ERR_INVALID_VALUE) {
188 return OHOS::ERR_INVALID_VALUE;
189 }
190 }
191 if (g_commandCOMPONENTENABLE) {
192 if (specialTestObject_->isAllFinished_) {
193 isFinished_ = true;
194 }
195 }
196 if (g_commandRECORDABLE) {
197 isFinished_ = true;
198 }
199 if (g_commandREPLAYABLE) {
200 isFinished_ = true;
201 }
202 usleep(intervalArgs_ * oneSecond_);
203 return result;
204 }
ProtectRightAbility()205 ErrCode SpecialTestFlow::ProtectRightAbility()
206 {
207 ErrCode result = OHOS::ERR_OK;
208 auto elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility();
209 auto curBundleName = elementName.GetBundleName();
210 auto static lastBundleName = elementName.GetBundleName();
211 if (curBundleName != lastBundleName) {
212 auto it = find(bundleName_.begin(), bundleName_.end(), curBundleName);
213 if (it == bundleName_.end()) {
214 std::vector<std::string> bundleList(0);
215 std::vector<std::string> abilityList(0);
216 auto util = WuKongUtil::GetInstance();
217 util->GetBundleList(bundleList, abilityList);
218 if (bundleList.size() == 0 || abilityList.size() == 0) {
219 ERROR_LOG_STR("bundleList (%u) or abilityList (%u) is 0", bundleList.size(), abilityList.size());
220 return OHOS::ERR_INVALID_VALUE;
221 }
222 uint32_t index = util->FindElement(bundleList, lastBundleName);
223 if (index == INVALIDVALUE) {
224 ERROR_LOG("not found bundle");
225 return OHOS::ERR_INVALID_VALUE;
226 }
227 // start ability through bundle information
228 result = AppManager::GetInstance()->StartAbilityByBundleInfo(abilityList[index], bundleList[index]);
229 if (result == OHOS::ERR_OK) {
230 INFO_LOG_STR("Bundle Name: (%s) startup successful", bundleList[index].c_str());
231 WuKongUtil::GetInstance()->SetIsFirstStartAppFlag(true);
232 } else {
233 INFO_LOG_STR("Bundle Name: (%s) startup failed", bundleList[index].c_str());
234 }
235 } else {
236 lastBundleName = curBundleName;
237 DEBUG_LOG_STR("lastBundleName change to : %s", curBundleName.c_str());
238 }
239 }
240 return result;
241 }
242
DistrbuteInputType()243 InputType SpecialTestFlow::DistrbuteInputType()
244 {
245 InputType iputType = INPUTTYPE_INVALIDINPUT;
246
247 if (g_commandTOUCHENABLE == true) {
248 iputType = INPUTTYPE_TOUCHINPUT;
249 } else if (g_commandSWAPENABLE) {
250 iputType = INPUTTYPE_SWAPINPUT;
251 } else if (g_commandPOWERENABLE) {
252 iputType = INPUTTYPE_HARDKEYINPUT;
253 } else if (g_commandCOMPONENTENABLE) {
254 iputType = INPUTTYPE_ELEMENTINPUT;
255 } else if (g_commandRECORDABLE) {
256 iputType = INPUTTYPE_RECORDINPUT;
257 } else if (g_commandREPLAYABLE) {
258 iputType = INPUTTYPE_REPPLAYINPUT;
259 }
260 return iputType;
261 }
262
GetOptionArguments(std::string & shortOpts)263 const struct option *SpecialTestFlow::GetOptionArguments(std::string &shortOpts)
264 {
265 shortOpts = SHORT_OPTIONS;
266 return LONG_OPTIONS;
267 }
268
HandleUnknownOption(const char optopt)269 ErrCode SpecialTestFlow::HandleUnknownOption(const char optopt)
270 {
271 ErrCode result = OHOS::ERR_OK;
272 switch (optopt) {
273 case 'T':
274 case 'i':
275 case 'c':
276 case 's':
277 case 'e':
278 case 'C':
279 shellcommand_.ResultReceiverAppend("error: option '-");
280 shellcommand_.ResultReceiverAppend(string(1, optopt));
281 shellcommand_.ResultReceiverAppend("' requires a value.\n");
282 result = OHOS::ERR_INVALID_VALUE;
283 break;
284 case 'h': {
285 result = OHOS::ERR_INVALID_VALUE;
286 break;
287 }
288 default: {
289 // 'wukong special' with a unknown option: wukong special -x
290 shellcommand_.ResultReceiverAppend(
291 "'wukong special' with an unknown option, please reference help information:\n");
292 result = OHOS::ERR_INVALID_VALUE;
293 break;
294 }
295 }
296 shellcommand_.ResultReceiverAppend(SPECIAL_TEST_HELP_MSG);
297 return result;
298 }
299
HandleNormalOption(const int option)300 ErrCode SpecialTestFlow::HandleNormalOption(const int option)
301 {
302 ErrCode result = OHOS::ERR_OK;
303 if (option == 'c' || option == 'T') {
304 CheckArgument(option);
305 } else if (option == 'i' || option == 't' || option == 's' || option == 'e' || option == 'C') {
306 result = SetRunningParam(option);
307 } else if (option == 'S' || option == 'k' || option == 'h' || option == 'b' || option == 'p' ||
308 option == 'r' || option == 'R' || option == 'u') {
309 result = SetRunningIndicator(option);
310 }
311 WuKongUtil::GetInstance()->SetOrderFlag(true);
312 return result;
313 }
314
CheckArgument(const int option)315 ErrCode SpecialTestFlow::CheckArgument(const int option)
316 {
317 ErrCode result = OHOS::ERR_OK;
318 switch (option) {
319 case 'c': {
320 // check if the '-c' and 'T' is exist at the same time
321 if (g_commandTIMEENABLE == false) {
322 g_commandCOUNTENABLE = true;
323 countArgs_ = std::stoi(optarg);
324 TEST_RUN_LOG(("Count: " + std::to_string(countArgs_)).c_str());
325 totalCount_ = countArgs_;
326 } else {
327 DEBUG_LOG(PARAM_COUNT_TIME_ERROR);
328 shellcommand_.ResultReceiverAppend(std::string(PARAM_COUNT_TIME_ERROR) + "\n");
329 result = OHOS::ERR_INVALID_VALUE;
330 }
331 break;
332 }
333 case 'T': {
334 // check if the '-c' and 'T' is exist at the same time
335 if (g_commandCOUNTENABLE == false) {
336 totalTime_ = std::stof(optarg);
337 TEST_RUN_LOG(("Time: " + std::to_string(totalTime_)).c_str());
338 g_commandTIMEENABLE = true;
339 } else {
340 DEBUG_LOG(PARAM_TIME_COUNT_ERROR);
341 shellcommand_.ResultReceiverAppend(std::string(PARAM_TIME_COUNT_ERROR) + "\n");
342 result = OHOS::ERR_INVALID_VALUE;
343 }
344 break;
345 }
346 default: {
347 result = OHOS::ERR_INVALID_VALUE;
348 break;
349 }
350 }
351 return result;
352 }
353
SetRunningParam(const int option)354 ErrCode SpecialTestFlow::SetRunningParam(const int option)
355 {
356 ErrCode result = OHOS::ERR_OK;
357 if (option == 'i') {
358 intervalArgs_ = std::stoi(optarg);
359 TEST_RUN_LOG(("Interval: " + std::to_string(intervalArgs_)).c_str());
360 } else if (option == 't') {
361 SplitStr(optarg, ",", touchParam_);
362 // check if param is valid
363 result = CheckPosition(touchParam_);
364 g_commandTOUCHENABLE = true;
365 } else if (option == 's') {
366 SplitStr(optarg, ",", swapStartPoint_);
367 // check if param is valid
368 result = CheckPosition(swapStartPoint_);
369 } else if (option == 'e') {
370 SplitStr(optarg, ",", swapEndPoint_);
371 // check if param is valid
372 result = CheckPosition(swapEndPoint_);
373 } else if (option == 'C') {
374 SplitStr(optarg, ",", bundleName_);
375 result = WuKongUtil::GetInstance()->CheckArgumentList(bundleName_, true);
376 g_commandCOMPONENTENABLE = true;
377 }
378 return OHOS::ERR_OK;
379 }
380
SetRunningIndicator(const int option)381 ErrCode SpecialTestFlow::SetRunningIndicator(const int option)
382 {
383 ErrCode result = OHOS::ERR_OK;
384 if (option == 'S') {
385 g_commandSWAPENABLE = true;
386 } else if (option == 'k') {
387 g_commandPOWERENABLE = true;
388 } else if (option == 'h') {
389 shellcommand_.ResultReceiverAppend(SPECIAL_TEST_HELP_MSG);
390 result = ERR_NO_INIT;
391 g_commandHELPENABLE = true;
392 } else if (option == 'b') {
393 g_commandGOBACKENABLE = true;
394 } else if (option == 'p') {
395 g_commandSCREENSHOTENABLE = true;
396 } else if (option == 'r') {
397 g_commandRECORDABLE = true;
398 specialRecordName_ = optarg;
399 } else if (option == 'R') {
400 g_commandREPLAYABLE = true;
401 specialRecordName_ = optarg;
402 } else if (option == 'u') {
403 g_commandUITEST = true;
404 }
405 return OHOS::ERR_OK;
406 }
407
RegisterTimer()408 void SpecialTestFlow::RegisterTimer()
409 {
410 if (timer_ == nullptr) {
411 timer_ = std::make_shared<Utils::Timer>("wukong");
412 timerId_ = timer_->Register(std::bind(&SpecialTestFlow::TestTimeout, this), totalTime_ * ONE_MINUTE, true);
413 timer_->Setup();
414 }
415 }
416
TestTimeout()417 void SpecialTestFlow::TestTimeout()
418 {
419 g_commandTIMEENABLE = false;
420 isFinished_ = true;
421 }
422
CheckPosition(std::vector<std::string> argumentlist)423 ErrCode SpecialTestFlow::CheckPosition(std::vector<std::string> argumentlist)
424 {
425 int32_t screenWidth = -1;
426 int32_t screenHeight = -1;
427
428 // get the size of screen
429 ErrCode result = WuKongUtil::GetInstance()->GetScreenSize(screenWidth, screenHeight);
430 if (result != OHOS::ERR_OK) {
431 return result;
432 }
433 if (argumentlist.size() > 0) {
434 if (stoi(argumentlist[0]) > screenWidth || stoi(argumentlist[1]) > screenHeight || stoi(argumentlist[0]) < 0 ||
435 stoi(argumentlist[1]) < 0) {
436 std::string paramError = "the param of position is incorrect";
437 DEBUG_LOG(paramError.c_str());
438 shellcommand_.ResultReceiverAppend(paramError + "\n");
439 result = OHOS::ERR_NO_INIT;
440 }
441 }
442 return result;
443 }
444
LauncherApp()445 ErrCode SpecialTestFlow::LauncherApp()
446 {
447 std::shared_ptr<InputAction> inputaction = InputFactory::GetInputAction(INPUTTYPE_APPSWITCHINPUT);
448 ErrCode result = inputaction->OrderInput(specialTestObject_);
449 if (result != OHOS::ERR_OK) {
450 ERROR_LOG("launcher app failed");
451 }
452 return result;
453 }
454 } // namespace WuKong
455 } // namespace OHOS
456