• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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