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