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 if (!inputaction) {
183 WARN_LOG("This test failed, the inputaction is nullptr.");
184 return OHOS::ERR_INVALID_VALUE;
185 }
186 result = inputaction->OrderInput(specialTestObject_);
187 if (result != OHOS::ERR_OK) {
188 WARN_LOG("This test failed");
189 }
190 if (!g_commandPOWERENABLE) {
191 if (ProtectRightAbility() == OHOS::ERR_INVALID_VALUE) {
192 return OHOS::ERR_INVALID_VALUE;
193 }
194 }
195 if (g_commandCOMPONENTENABLE) {
196 if (specialTestObject_->isAllFinished_) {
197 isFinished_ = true;
198 }
199 }
200 if (g_commandRECORDABLE) {
201 isFinished_ = true;
202 }
203 usleep(intervalArgs_ * oneSecond_);
204 return result;
205 }
ProtectRightAbility()206 ErrCode SpecialTestFlow::ProtectRightAbility()
207 {
208 ErrCode result = OHOS::ERR_OK;
209 auto elementName = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility();
210 auto curBundleName = elementName.GetBundleName();
211 auto static lastBundleName = elementName.GetBundleName();
212 if (curBundleName != lastBundleName) {
213 auto it = find(bundleName_.begin(), bundleName_.end(), curBundleName);
214 if (it == bundleName_.end()) {
215 std::vector<std::string> bundleList(0);
216 std::vector<std::string> abilityList(0);
217 auto util = WuKongUtil::GetInstance();
218 util->GetBundleList(bundleList, abilityList);
219 if (bundleList.size() == 0 || abilityList.size() == 0) {
220 ERROR_LOG_STR("bundleList (%u) or abilityList (%u) is 0", bundleList.size(), abilityList.size());
221 return OHOS::ERR_INVALID_VALUE;
222 }
223 uint32_t index = util->FindElement(bundleList, lastBundleName);
224 if (index == INVALIDVALUE) {
225 ERROR_LOG("not found bundle");
226 return OHOS::ERR_INVALID_VALUE;
227 }
228 // start ability through bundle information
229 result = AppManager::GetInstance()->StartAbilityByBundleInfo(abilityList[index], bundleList[index]);
230 if (result == OHOS::ERR_OK) {
231 INFO_LOG_STR("Bundle Name: (%s) startup successful", bundleList[index].c_str());
232 WuKongUtil::GetInstance()->SetIsFirstStartAppFlag(true);
233 } else {
234 INFO_LOG_STR("Bundle Name: (%s) startup failed", bundleList[index].c_str());
235 }
236 } else {
237 lastBundleName = curBundleName;
238 DEBUG_LOG_STR("lastBundleName change to : %s", curBundleName.c_str());
239 }
240 }
241 return result;
242 }
243
DistrbuteInputType()244 InputType SpecialTestFlow::DistrbuteInputType()
245 {
246 InputType iputType = INPUTTYPE_INVALIDINPUT;
247
248 if (g_commandTOUCHENABLE == true) {
249 iputType = INPUTTYPE_TOUCHINPUT;
250 } else if (g_commandSWAPENABLE) {
251 iputType = INPUTTYPE_SWAPINPUT;
252 } else if (g_commandPOWERENABLE) {
253 iputType = INPUTTYPE_HARDKEYINPUT;
254 } else if (g_commandCOMPONENTENABLE) {
255 iputType = INPUTTYPE_ELEMENTINPUT;
256 } else if (g_commandRECORDABLE) {
257 iputType = INPUTTYPE_RECORDINPUT;
258 } else if (g_commandREPLAYABLE) {
259 iputType = INPUTTYPE_REPPLAYINPUT;
260 }
261 return iputType;
262 }
263
GetOptionArguments(std::string &shortOpts)264 const struct option *SpecialTestFlow::GetOptionArguments(std::string &shortOpts)
265 {
266 shortOpts = SHORT_OPTIONS;
267 return LONG_OPTIONS;
268 }
269
HandleUnknownOption(const char optopt)270 ErrCode SpecialTestFlow::HandleUnknownOption(const char optopt)
271 {
272 ErrCode result = OHOS::ERR_OK;
273 switch (optopt) {
274 case 'T':
275 case 'i':
276 case 'c':
277 case 's':
278 case 'e':
279 case 'C':
280 shellcommand_.ResultReceiverAppend("error: option '-");
281 shellcommand_.ResultReceiverAppend(string(1, optopt));
282 shellcommand_.ResultReceiverAppend("' requires a value.\n");
283 result = OHOS::ERR_INVALID_VALUE;
284 break;
285 case 'h': {
286 result = OHOS::ERR_INVALID_VALUE;
287 break;
288 }
289 default: {
290 // 'wukong special' with a unknown option: wukong special -x
291 shellcommand_.ResultReceiverAppend(
292 "'wukong special' with an unknown option, please reference help information:\n");
293 result = OHOS::ERR_INVALID_VALUE;
294 break;
295 }
296 }
297 shellcommand_.ResultReceiverAppend(SPECIAL_TEST_HELP_MSG);
298 return result;
299 }
300
HandleNormalOption(const int option)301 ErrCode SpecialTestFlow::HandleNormalOption(const int option)
302 {
303 ErrCode result = OHOS::ERR_OK;
304 if (option == 'c' || option == 'T') {
305 result = CheckArgument(option);
306 } else if (option == 'i' || option == 't' || option == 's' || option == 'e' || option == 'C') {
307 result = SetRunningParam(option);
308 } else if (option == 'S' || option == 'k' || option == 'h' || option == 'b' || option == 'p' ||
309 option == 'r' || option == 'R' || option == 'u') {
310 result = SetRunningIndicator(option);
311 }
312 WuKongUtil::GetInstance()->SetOrderFlag(true);
313 return result;
314 }
315
CheckArgument(const int option)316 ErrCode SpecialTestFlow::CheckArgument(const int option)
317 {
318 ErrCode result = OHOS::ERR_OK;
319 switch (option) {
320 case 'c': {
321 result = CheckArgumentOptionOfc();
322 break;
323 }
324 case 'T': {
325 result = CheckArgumentOptionOfT();
326 break;
327 }
328 default: {
329 result = OHOS::ERR_INVALID_VALUE;
330 break;
331 }
332 }
333 return result;
334 }
335
SetRunningParam(const int option)336 ErrCode SpecialTestFlow::SetRunningParam(const int option)
337 {
338 ErrCode result = OHOS::ERR_OK;
339 if (option == 'i') {
340 intervalArgs_ = std::stoi(optarg);
341 TEST_RUN_LOG(("Interval: " + std::to_string(intervalArgs_)).c_str());
342 } else if (option == 't') {
343 SplitStr(optarg, ",", touchParam_);
344 // check if param is valid
345 result = CheckPosition(touchParam_);
346 g_commandTOUCHENABLE = true;
347 } else if (option == 's') {
348 SplitStr(optarg, ",", swapStartPoint_);
349 // check if param is valid
350 result = CheckPosition(swapStartPoint_);
351 } else if (option == 'e') {
352 SplitStr(optarg, ",", swapEndPoint_);
353 // check if param is valid
354 result = CheckPosition(swapEndPoint_);
355 } else if (option == 'C') {
356 SplitStr(optarg, ",", bundleName_);
357 result = WuKongUtil::GetInstance()->CheckArgumentList(bundleName_, true);
358 g_commandCOMPONENTENABLE = true;
359 }
360 return OHOS::ERR_OK;
361 }
362
SetRunningIndicator(const int option)363 ErrCode SpecialTestFlow::SetRunningIndicator(const int option)
364 {
365 ErrCode result = OHOS::ERR_OK;
366 if (option == 'S') {
367 g_commandSWAPENABLE = true;
368 } else if (option == 'k') {
369 g_commandPOWERENABLE = true;
370 } else if (option == 'h') {
371 shellcommand_.ResultReceiverAppend(SPECIAL_TEST_HELP_MSG);
372 result = ERR_NO_INIT;
373 g_commandHELPENABLE = true;
374 } else if (option == 'b') {
375 g_commandGOBACKENABLE = true;
376 } else if (option == 'p') {
377 g_commandSCREENSHOTENABLE = true;
378 } else if (option == 'r') {
379 g_commandRECORDABLE = true;
380 specialRecordName_ = optarg;
381 } else if (option == 'R') {
382 g_commandREPLAYABLE = true;
383 specialRecordName_ = optarg;
384 } else if (option == 'u') {
385 g_commandUITEST = true;
386 }
387 return OHOS::ERR_OK;
388 }
389
RegisterTimer()390 void SpecialTestFlow::RegisterTimer()
391 {
392 if (timer_ == nullptr) {
393 timer_ = std::make_shared<Utils::Timer>("wukong");
394 timerId_ = timer_->Register([this] () { SpecialTestFlow::TestTimeout(); }, totalTime_ * ONE_MINUTE, true);
395 timer_->Setup();
396 }
397 }
398
TestTimeout()399 void SpecialTestFlow::TestTimeout()
400 {
401 g_commandTIMEENABLE = false;
402 isFinished_ = true;
403 }
404
CheckPosition(std::vector<std::string> argumentlist)405 ErrCode SpecialTestFlow::CheckPosition(std::vector<std::string> argumentlist)
406 {
407 int32_t screenWidth = -1;
408 int32_t screenHeight = -1;
409
410 // get the size of screen
411 ErrCode result = WuKongUtil::GetInstance()->GetScreenSize(screenWidth, screenHeight);
412 if (result != OHOS::ERR_OK) {
413 return result;
414 }
415 if (argumentlist.size() > 0) {
416 if (stoi(argumentlist[0]) > screenWidth || stoi(argumentlist[1]) > screenHeight || stoi(argumentlist[0]) < 0 ||
417 stoi(argumentlist[1]) < 0) {
418 std::string paramError = "the param of position is incorrect";
419 DEBUG_LOG(paramError.c_str());
420 shellcommand_.ResultReceiverAppend(paramError + "\n");
421 result = OHOS::ERR_NO_INIT;
422 }
423 }
424 return result;
425 }
426
LauncherApp()427 ErrCode SpecialTestFlow::LauncherApp()
428 {
429 std::shared_ptr<InputAction> inputaction = InputFactory::GetInputAction(INPUTTYPE_APPSWITCHINPUT);
430 if (!inputaction) {
431 return OHOS::ERR_INVALID_VALUE;
432 }
433 ErrCode result = inputaction->OrderInput(specialTestObject_);
434 if (result != OHOS::ERR_OK) {
435 ERROR_LOG("launcher app failed");
436 }
437 return result;
438 }
439
CheckArgumentOptionOfc()440 ErrCode SpecialTestFlow::CheckArgumentOptionOfc()
441 {
442 // check if the '-c' and 'T' is exist at the same time
443 if (g_commandTIMEENABLE == false) {
444 std::stringstream ss(optarg);
445 if (ss >> countArgs_) {
446 g_commandCOUNTENABLE = true;
447 TEST_RUN_LOG(("Count: " + std::to_string(countArgs_)).c_str());
448 totalCount_ = countArgs_;
449 return OHOS::ERR_OK;
450 } else {
451 ERROR_LOG("Setting -c must follow an interger");
452 return OHOS::ERR_INVALID_VALUE;
453 }
454 } else {
455 DEBUG_LOG(PARAM_COUNT_TIME_ERROR);
456 shellcommand_.ResultReceiverAppend(std::string(PARAM_COUNT_TIME_ERROR) + "\n");
457 return OHOS::ERR_INVALID_VALUE;
458 }
459 }
460
CheckArgumentOptionOfT()461 ErrCode SpecialTestFlow::CheckArgumentOptionOfT()
462 {
463 // check if the '-c' and 'T' is exist at the same time
464 if (g_commandCOUNTENABLE == false) {
465 std::stringstream ss(optarg);
466 if (ss >> totalTime_) {
467 TEST_RUN_LOG(("Time: " + std::to_string(totalTime_)).c_str());
468 g_commandTIMEENABLE = true;
469 return OHOS::ERR_OK;
470 } else {
471 ERROR_LOG("Setting -T must follow a float");
472 return OHOS::ERR_INVALID_VALUE;
473 }
474 } else {
475 DEBUG_LOG(PARAM_TIME_COUNT_ERROR);
476 shellcommand_.ResultReceiverAppend(std::string(PARAM_TIME_COUNT_ERROR) + "\n");
477 return OHOS::ERR_INVALID_VALUE;
478 }
479 }
480
481 } // namespace WuKong
482 } // namespace OHOS
483