1 /*
2 * Copyright (c) 2021-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 <cmath>
17 #include "gtest/gtest.h"
18 #include "ui_action.h"
19
20 using namespace OHOS::uitest;
21 using namespace std;
22
23 static constexpr uint32_t CUSTOM_CLICK_HOLD_MS = 100;
24 static constexpr uint32_t CUSTOM_LONGCLICK_HOLD_MS = 200;
25 static constexpr uint32_t CUSTOM_DOUBLECLICK_HOLD_MS = 300;
26 static constexpr uint32_t CUSTOM_KEY_HOLD_MS = 400;
27 static constexpr uint32_t CUSTOM_SWIPE_VELOCITY_PPS = 500;
28 static constexpr uint32_t CUSTOM_UI_STEADY_MS = 600;
29 static constexpr uint32_t CUSTOM_WAIT_UI_STEADY_MS = 700;
30
31 class UiActionTest : public testing::Test {
32 public:
33 ~UiActionTest() override = default;
34 protected:
SetUp()35 void SetUp() override
36 {
37 Test::SetUp();
38 // use custom UiOperationOptions
39 customOptions_.clickHoldMs_ = CUSTOM_CLICK_HOLD_MS;
40 customOptions_.longClickHoldMs_ = CUSTOM_LONGCLICK_HOLD_MS;
41 customOptions_.doubleClickIntervalMs_ = CUSTOM_DOUBLECLICK_HOLD_MS;
42 customOptions_.keyHoldMs_ = CUSTOM_KEY_HOLD_MS;
43 customOptions_.swipeVelocityPps_ = CUSTOM_SWIPE_VELOCITY_PPS;
44 customOptions_.uiSteadyThresholdMs_ = CUSTOM_UI_STEADY_MS;
45 customOptions_.waitUiSteadyMaxMs_ = CUSTOM_WAIT_UI_STEADY_MS;
46 }
47 UiOpArgs customOptions_;
48 };
49
TEST_F(UiActionTest,computeClickAction)50 TEST_F(UiActionTest, computeClickAction)
51 {
52 Point point {100, 200};
53 GenericClick action(TouchOp::CLICK, point);
54 PointerMatrix events;
55 action.Decompose(events, customOptions_);
56 ASSERT_EQ(2, events.GetSize()); // up & down
57 auto &event1 = events.At(0, 0);
58 auto &event2 = events.At(0, 1);
59 ASSERT_EQ(point.px_, event1.point_.px_);
60 ASSERT_EQ(point.py_, event1.point_.py_);
61 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
62 ASSERT_EQ(0, event1.downTimeOffsetMs_);
63
64 ASSERT_EQ(point.px_, event2.point_.px_);
65 ASSERT_EQ(point.py_, event2.point_.py_);
66 ASSERT_EQ(ActionStage::UP, event2.stage_);
67 ASSERT_EQ(customOptions_.clickHoldMs_, event2.downTimeOffsetMs_);
68 }
69
TEST_F(UiActionTest,computeLongClickAction)70 TEST_F(UiActionTest, computeLongClickAction)
71 {
72 Point point {100, 200};
73 GenericClick action(TouchOp::LONG_CLICK, point);
74 PointerMatrix events;
75 action.Decompose(events, customOptions_);
76 ASSERT_EQ(2, events.GetSize()); // up & down
77 auto &event1 = events.At(0, 0);
78 auto &event2 = events.At(0, 1);
79 ASSERT_EQ(point.px_, event1.point_.px_);
80 ASSERT_EQ(point.py_, event1.point_.py_);
81 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
82 ASSERT_EQ(0, event1.downTimeOffsetMs_);
83 // there should be a proper pause after touch down to make long-click
84 ASSERT_EQ(customOptions_.longClickHoldMs_, event1.holdMs_);
85
86 ASSERT_EQ(point.px_, event2.point_.px_);
87 ASSERT_EQ(point.py_, event2.point_.py_);
88 ASSERT_EQ(ActionStage::UP, event2.stage_);
89 ASSERT_EQ(customOptions_.longClickHoldMs_, event2.downTimeOffsetMs_);
90 }
91
TEST_F(UiActionTest,computeDoubleClickAction)92 TEST_F(UiActionTest, computeDoubleClickAction)
93 {
94 Point point {100, 200};
95 GenericClick action(TouchOp::DOUBLE_CLICK_P, point);
96 PointerMatrix events;
97 action.Decompose(events, customOptions_);
98 ASSERT_EQ(4, events.GetSize()); // up-down-interval-up-down
99 auto &event1 = events.At(0, 0);
100 auto &event2 = events.At(0, 1);
101 auto &event3 = events.At(0, 2);
102 auto &event4 = events.At(0, 3);
103 ASSERT_EQ(point.px_, event1.point_.px_);
104 ASSERT_EQ(point.py_, event1.point_.py_);
105 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
106 ASSERT_EQ(0, event1.downTimeOffsetMs_);
107
108 ASSERT_EQ(point.px_, event2.point_.px_);
109 ASSERT_EQ(point.py_, event2.point_.py_);
110 ASSERT_EQ(ActionStage::UP, event2.stage_);
111 ASSERT_EQ(customOptions_.clickHoldMs_, event2.downTimeOffsetMs_);
112 // there should be a proper pause after first click
113 ASSERT_EQ(customOptions_.doubleClickIntervalMs_, event2.holdMs_);
114
115 ASSERT_EQ(point.px_, event3.point_.px_);
116 ASSERT_EQ(point.py_, event3.point_.py_);
117 ASSERT_EQ(ActionStage::DOWN, event3.stage_);
118 ASSERT_EQ(0, event3.downTimeOffsetMs_);
119
120 ASSERT_EQ(point.px_, event4.point_.px_);
121 ASSERT_EQ(point.py_, event4.point_.py_);
122 ASSERT_EQ(ActionStage::UP, event4.stage_);
123 ASSERT_EQ(customOptions_.clickHoldMs_, event4.downTimeOffsetMs_);
124 }
125
TEST_F(UiActionTest,computeSwipeAction)126 TEST_F(UiActionTest, computeSwipeAction)
127 {
128 UiOpArgs opt {};
129 opt.swipeVelocityPps_ = 50; // specify the swipe velocity
130 Point point0(0, 0);
131 Point point1(100, 200);
132 GenericSwipe action(TouchOp::SWIPE, point0, point1);
133 PointerMatrix events;
134 action.Decompose(events, opt);
135 // there should be more than 1 touches
136 const uint32_t steps = events.GetSize() - 1;
137 const int32_t disX = point1.px_ - point0.px_;
138 const int32_t disY = point1.py_ - point0.py_;
139 const uint32_t distance = sqrt(disX * disX + disY * disY);
140 const uint32_t totalCostMs = distance * 1000 / opt.swipeVelocityPps_;
141 constexpr uint32_t intervalMsInSwipe = 5;
142 ASSERT_EQ(steps, totalCostMs / intervalMsInSwipe);
143
144 uint32_t step = 0;
145 float stepLengthX = static_cast<double>(disX) / static_cast<double>(steps);
146 float stepLengthY = static_cast<double>(disY) / static_cast<double>(steps);
147 // check the TouchEvent of each step
148 for (uint32_t event = 0; event < steps; event++) {
149 int32_t expectedPointerX = point0.px_ + stepLengthX * event;
150 int32_t expectedPointerY = point0.py_ + stepLengthY * event;
151 uint32_t expectedTimeOffset = (totalCostMs * step) / steps;
152 ASSERT_NEAR(expectedPointerX, events.At(0, event).point_.px_, 5);
153 ASSERT_NEAR(expectedPointerY, events.At(0, event).point_.py_, 5);
154 ASSERT_NEAR(expectedTimeOffset, events.At(0, event).downTimeOffsetMs_, 5);
155 if (step == 0) {
156 // should start with Action.DOWN
157 ASSERT_EQ(ActionStage::DOWN, events.At(0, event).stage_);
158 } else if (step == events.GetSize() - 1) {
159 // should end with Action.UP
160 ASSERT_EQ(ActionStage::UP, events.At(0, event).stage_);
161 } else {
162 // middle events should all be action-MOVE
163 ASSERT_EQ(ActionStage::MOVE, events.At(0, event).stage_);
164 }
165 step++;
166 }
167 }
168
TEST_F(UiActionTest,computeFlingAction)169 TEST_F(UiActionTest, computeFlingAction)
170 {
171 UiOpArgs opt {};
172 opt.swipeVelocityPps_ = 800; // specify the swipe velocity
173 Point point0(0, 0);
174 Point point1(200, 200);
175
176 const uint32_t stepLen = 2;
177 const int32_t disX = point1.px_ - point0.px_;
178 const int32_t disY = point1.py_ - point0.py_;
179 const uint32_t distance = sqrt(disX * disX + disY * disY);
180 const uint32_t totalCostMs = distance * 1000 / opt.swipeVelocityPps_;
181 opt.swipeStepsCounts_ = distance / stepLen;
182
183 GenericSwipe action(TouchOp::FLING, point0, point1);
184 PointerMatrix events;
185 action.Decompose(events, opt);
186 // there should be more than 1 touches
187 const uint32_t steps = opt.swipeStepsCounts_;
188 ASSERT_TRUE(steps > 1);
189 ASSERT_EQ(steps, 141);
190
191 uint32_t step = 0;
192 float stepLengthX = static_cast<double>(disX) / static_cast<double>(steps);
193 float stepLengthY = static_cast<double>(disY) / static_cast<double>(steps);
194 // check the TouchEvent of each step
195 for (uint32_t event = 0; event < steps; event++) {
196 int32_t expectedPointerX = point0.px_ + stepLengthX * event;
197 int32_t expectedPointerY = point0.py_ + stepLengthY * event;
198 uint32_t expectedTimeOffset = (totalCostMs * step) / steps;
199 ASSERT_NEAR(expectedPointerX, events.At(0, event).point_.px_, 5);
200 ASSERT_NEAR(expectedPointerY, events.At(0, event).point_.py_, 5);
201 ASSERT_NEAR(expectedTimeOffset, events.At(0, event).downTimeOffsetMs_, 5);
202 if (step == 0) {
203 // should start with Action.DOWN
204 ASSERT_EQ(ActionStage::DOWN, events.At(0, event).stage_);
205 } else if (step == events.GetSize() - 1) {
206 // should end with Action.UP
207 ASSERT_EQ(ActionStage::UP, events.At(0, event).stage_);
208 } else {
209 // middle events should all be action-MOVE
210 ASSERT_EQ(ActionStage::MOVE, events.At(0, event).stage_);
211 }
212 step++;
213 }
214 }
215
TEST_F(UiActionTest,computePinchInAction)216 TEST_F(UiActionTest, computePinchInAction)
217 {
218 UiOpArgs opt {};
219 opt.swipeVelocityPps_ = 50; // specify the swipe velocity
220 Rect rect(210, 510, 30, 330);
221 float_t scale = 0.5;
222 GenericPinch action(rect, scale);
223 PointerMatrix events;
224 action.Decompose(events, opt);
225 // there should be more than 1 touches
226 const int32_t steps = events.GetSteps() - 1;
227 ASSERT_TRUE(steps > 1);
228
229 const int32_t disX0 = abs(rect.left_ - rect.GetCenterX()) * abs(scale - 1);
230 ASSERT_EQ(75, disX0);
231
232 uint32_t step = 0;
233 // check the TouchEvent of each step
234 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
235 uint32_t eventFinger = 0;
236 int32_t expectedPointerX0 = rect.left_ + (disX0 * step) / steps;
237 uint32_t x0 = events.At(eventFinger, eventStep).point_.px_;
238 ASSERT_NEAR(expectedPointerX0, x0, opt.pinchWidgetDeadZone_);
239 if (eventStep == 0) {
240 // should start with Action.DOWN
241 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
242 ASSERT_EQ(0, events.At(eventFinger, eventStep).downTimeOffsetMs_);
243 } else if (eventStep == events.GetSteps() - 1) {
244 // should end with Action.UP
245 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
246 } else {
247 // middle events should all be action-MOVE
248 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
249 }
250 step++;
251 }
252 step = 0;
253 float stepLengthX = static_cast<double>(disX0) / static_cast<double>(steps);
254
255 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
256 uint32_t eventFinger = 1;
257 int32_t expectedPointerX0 = rect.right_ - stepLengthX * step;
258 ASSERT_NEAR(expectedPointerX0, events.At(eventFinger, eventStep).point_.px_, opt.pinchWidgetDeadZone_);
259 if (eventStep == 0) {
260 // should start with Action.DOWN
261 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
262 } else if (eventStep == events.GetSteps() - 1) {
263 // should end with Action.UP
264 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
265 } else {
266 // middle events should all be action-MOVE
267 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
268 }
269 step++;
270 }
271 }
272
TEST_F(UiActionTest,computeMultiPointerMatrixAction)273 TEST_F(UiActionTest, computeMultiPointerMatrixAction)
274 {
275 UiOpArgs opt {};
276 opt.swipeVelocityPps_ = 50; // specify the swipe velocity
277 const uint32_t finger = 2;
278 const uint32_t step = 4;
279 PointerMatrix pointer(finger, step);
280 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
281 pointer.At(0, stepIndex).point_.px_ = 245 + 20 * stepIndex;
282 pointer.At(0, stepIndex).point_.py_ = 480;
283 }
284 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
285 pointer.At(1, stepIndex).point_.px_ = 505 - 20 * stepIndex;
286 pointer.At(1, stepIndex).point_.py_ = 480;
287 }
288 MultiPointerAction action(pointer);
289 ASSERT_EQ(2, pointer.GetFingers());
290 ASSERT_EQ(4, pointer.GetSteps());
291 ASSERT_EQ(245, pointer.At(0, 0).point_.px_);
292 PointerMatrix events;
293 action.Decompose(events, opt);
294 // there should be more than 1 touches
295 ASSERT_EQ(10, events.GetSize());
296 ASSERT_EQ(5, events.GetSteps());
297 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
298 for (uint32_t eventFinger = 0; eventFinger < events.GetFingers(); eventFinger++) {
299 if (eventStep == 0) {
300 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
301 } else if (eventStep == events.GetSteps() - 1) {
302 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
303 } else {
304 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
305 }
306 }
307 }
308 }
309
TEST_F(UiActionTest,computeMultiPointerMatrixAction1)310 TEST_F(UiActionTest, computeMultiPointerMatrixAction1)
311 {
312 UiOpArgs opt {};
313 opt.swipeVelocityPps_ = 600; // specify the swipe velocity
314 const uint32_t finger = 4;
315 const uint32_t step = 4;
316 PointerMatrix pointer(finger, step);
317 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
318 pointer.At(0, stepIndex).point_.px_ = 245 + 20 * stepIndex;
319 pointer.At(0, stepIndex).point_.py_ = 480;
320 }
321 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
322 pointer.At(1, stepIndex).point_.px_ = 505 - 20 * stepIndex;
323 pointer.At(1, stepIndex).point_.py_ = 480;
324 }
325 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
326 pointer.At(2, stepIndex).point_.px_ = 375;
327 pointer.At(2, stepIndex).point_.py_ = 350 + 20 * stepIndex;
328 }
329 for (uint32_t stepIndex = 0; stepIndex < step; stepIndex++) {
330 pointer.At(3, stepIndex).point_.px_ = 375;
331 pointer.At(3, stepIndex).point_.py_ = 610 - 20 * stepIndex;
332 }
333 MultiPointerAction action(pointer);
334 ASSERT_EQ(4, pointer.GetFingers());
335 ASSERT_EQ(4, pointer.GetSteps());
336 ASSERT_EQ(245, pointer.At(0, 0).point_.px_);
337 ASSERT_EQ(590, pointer.At(3, 1).point_.py_);
338 PointerMatrix events;
339 action.Decompose(events, opt);
340 // there should be more than 1 touches
341 ASSERT_EQ(20, events.GetSize());
342 ASSERT_EQ(5, events.GetSteps());
343 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
344 for (uint32_t eventFinger = 0; eventFinger < events.GetFingers(); eventFinger++) {
345 if (eventStep == 0) {
346 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
347 } else if (eventStep == events.GetSteps() - 1) {
348 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
349 } else {
350 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
351 }
352 }
353 }
354 }
355
TEST_F(UiActionTest,computePinchOutAction)356 TEST_F(UiActionTest, computePinchOutAction)
357 {
358 UiOpArgs opt {};
359 opt.swipeVelocityPps_ = 50; // specify the swipe velocity
360 Rect rect(210, 510, 30, 330);
361 float_t scale = 1.5;
362 GenericPinch action(rect, scale);
363 PointerMatrix events;
364 action.Decompose(events, opt);
365 // there should be more than 1 touches
366 const int32_t steps = events.GetSteps() - 1;
367 ASSERT_TRUE(steps > 1);
368
369 const int32_t disX0 = abs(rect.left_ - rect.GetCenterX()) * abs(scale - 1);
370 ASSERT_EQ(75, disX0);
371
372 uint32_t step = 0;
373 float stepLengthX = static_cast<double>(disX0) / static_cast<double>(steps);
374 // check the TouchEvent of each step
375 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
376 uint32_t eventFinger = 0;
377 int32_t expectedPointerX0 = rect.GetCenterX() - stepLengthX * step;
378 uint32_t x0 = events.At(eventFinger, eventStep).point_.px_;
379 ASSERT_NEAR(expectedPointerX0, x0, opt.pinchWidgetDeadZone_);
380 if (eventStep == 0) {
381 // should start with Action.DOWN
382 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
383 ASSERT_EQ(0, events.At(eventFinger, eventStep).downTimeOffsetMs_);
384 } else if (eventStep == events.GetSteps() - 1) {
385 // should end with Action.UP
386 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
387 } else {
388 // middle events should all be action-MOVE
389 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
390 }
391 step++;
392 }
393 step = 0;
394 for (uint32_t eventStep = 0; eventStep < events.GetSteps(); eventStep++) {
395 uint32_t eventFinger = 1;
396 int32_t expectedPointerX0 = rect.GetCenterX() + (disX0 * step) / steps;
397 ASSERT_NEAR(expectedPointerX0, events.At(eventFinger, eventStep).point_.px_, opt.pinchWidgetDeadZone_);
398 if (eventStep == 0) {
399 // should start with Action.DOWN
400 ASSERT_EQ(ActionStage::DOWN, events.At(eventFinger, eventStep).stage_);
401 } else if (eventStep == events.GetSteps() - 1) {
402 // should end with Action.UP
403 ASSERT_EQ(ActionStage::UP, events.At(eventFinger, eventStep).stage_);
404 } else {
405 // middle events should all be action-MOVE
406 ASSERT_EQ(ActionStage::MOVE, events.At(eventFinger, eventStep).stage_);
407 }
408 step++;
409 }
410 }
411
TEST_F(UiActionTest,computeDragAction)412 TEST_F(UiActionTest, computeDragAction)
413 {
414 UiOpArgs opt {};
415 opt.longClickHoldMs_ = 2000; // specify the long-click duration
416 Point point0(0, 0);
417 Point point1(100, 200);
418 GenericSwipe swipeAction(TouchOp::SWIPE, point0, point1);
419 GenericSwipe dragAction(TouchOp::DRAG, point0, point1);
420 PointerMatrix swipeEvents;
421 PointerMatrix dragEvents;
422 swipeAction.Decompose(swipeEvents, opt);
423 dragAction.Decompose(dragEvents, opt);
424
425 ASSERT_TRUE(swipeEvents.GetSize() > 1);
426 ASSERT_EQ(swipeEvents.GetSize(), dragEvents.GetSize());
427
428 // check the hold time of each event
429 for (uint32_t step = 0; step < swipeEvents.GetSize(); step++) {
430 auto &swipeEvent = swipeEvents.At(0, step);
431 auto &dragEvent = dragEvents.At(0, step);
432 ASSERT_EQ(swipeEvent.stage_, dragEvent.stage_);
433 // drag needs longPressDown firstly, the downOffSet of following event should be delayed
434 if (step == 0) {
435 ASSERT_EQ(swipeEvent.downTimeOffsetMs_, dragEvent.downTimeOffsetMs_);
436 ASSERT_EQ(swipeEvent.holdMs_ + opt.longClickHoldMs_, dragEvent.holdMs_);
437 } else {
438 ASSERT_EQ(swipeEvent.downTimeOffsetMs_ + opt.longClickHoldMs_, dragEvent.downTimeOffsetMs_);
439 ASSERT_EQ(swipeEvent.holdMs_, dragEvent.holdMs_);
440 }
441 }
442 }
443
TEST_F(UiActionTest,computeBackKeyAction)444 TEST_F(UiActionTest, computeBackKeyAction)
445 {
446 Back keyAction;
447 vector<KeyEvent> events;
448 keyAction.ComputeEvents(events, customOptions_);
449 ASSERT_EQ(2, events.size()); // up & down
450 auto event1 = *events.begin();
451 auto event2 = *(events.begin() + 1);
452 ASSERT_EQ(KEYCODE_BACK, event1.code_);
453 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
454
455 ASSERT_EQ(KEYCODE_BACK, event2.code_);
456 ASSERT_EQ(ActionStage::UP, event2.stage_);
457 }
458
TEST_F(UiActionTest,computePasteAction)459 TEST_F(UiActionTest, computePasteAction)
460 {
461 Paste keyAction;
462 vector<KeyEvent> events;
463 keyAction.ComputeEvents(events, customOptions_);
464 ASSERT_EQ(4, events.size()); // ctrl_down/key_down/key_up/ctrl_up
465 auto event1 = *events.begin();
466 auto event2 = *(events.begin() + 1);
467 auto event3 = *(events.begin() + 2);
468 auto event4 = *(events.begin() + 3);
469
470 ASSERT_EQ(KEYCODE_CTRL, event1.code_);
471 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
472 ASSERT_EQ(KEYCODE_V, event2.code_);
473 ASSERT_EQ(ActionStage::DOWN, event2.stage_);
474
475 ASSERT_EQ(KEYCODE_CTRL, event3.code_);
476 ASSERT_EQ(ActionStage::UP, event3.stage_);
477 ASSERT_EQ(KEYCODE_V, event4.code_);
478 ASSERT_EQ(ActionStage::UP, event4.stage_);
479 }
480
TEST_F(UiActionTest,anonymousSignleKey)481 TEST_F(UiActionTest, anonymousSignleKey)
482 {
483 static constexpr uint32_t keyCode = 1234;
484 static const string expectedDesc = "key_" + to_string(keyCode);
485 AnonymousSingleKey anonymousKey(keyCode);
486 vector<KeyEvent> events;
487 anonymousKey.ComputeEvents(events, customOptions_);
488 ASSERT_EQ(2, events.size()); // up & down
489 auto event1 = *events.begin();
490 auto event2 = *(events.begin() + 1);
491 ASSERT_EQ(keyCode, event1.code_);
492 ASSERT_EQ(ActionStage::DOWN, event1.stage_);
493
494 ASSERT_EQ(keyCode, event2.code_);
495 ASSERT_EQ(ActionStage::UP, event2.stage_);
496 }
497