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 24namespace OHOS { 25namespace WuKong { 26namespace { 27const 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 47const std::string SHORT_OPTIONS = "c:hi:T:t:kSbs:e:C:pr:R:u:"; 48const 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}; 65const int ONE_MINUTE = 60000; 66bool g_commandSWAPENABLE = false; 67bool g_commandHELPENABLE = false; 68bool g_commandTIMEENABLE = false; 69bool g_commandTOUCHENABLE = false; 70bool g_commandPOWERENABLE = false; 71bool g_commandGOBACKENABLE = false; 72bool g_commandCOUNTENABLE = false; 73bool g_commandCOMPONENTENABLE = false; 74bool g_commandSCREENSHOTENABLE = false; 75bool g_commandRECORDABLE = false; 76bool g_commandREPLAYABLE = false; 77bool g_commandUITEST = false; 78 79const int NUMBER_TWO = 2; 80} // namespace 81using namespace std; 82 83SpecialTestFlow::SpecialTestFlow(WuKongShellCommand &shellcommand) : TestFlow(shellcommand) 84{ 85} 86 87SpecialTestFlow::~SpecialTestFlow() 88{ 89 if (timer_ != nullptr) { 90 timer_->Shutdown(); 91 timer_->Unregister(timerId_); 92 timer_ = nullptr; 93 } 94} 95 96ErrCode 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 161ErrCode 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} 206ErrCode 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 244InputType 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 264const struct option *SpecialTestFlow::GetOptionArguments(std::string &shortOpts) 265{ 266 shortOpts = SHORT_OPTIONS; 267 return LONG_OPTIONS; 268} 269 270ErrCode 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 301ErrCode 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 316ErrCode 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 336ErrCode 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 363ErrCode 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 390void 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 399void SpecialTestFlow::TestTimeout() 400{ 401 g_commandTIMEENABLE = false; 402 isFinished_ = true; 403} 404 405ErrCode 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 427ErrCode 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 440ErrCode 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 461ErrCode 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