• 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     UiDriveOptions customOptions_;
48 };
49 
TEST_F(UiActionTest,computeClickAction)50 TEST_F(UiActionTest, computeClickAction)
51 {
52     GenericClick action(PointerOp::CLICK_P);
53     Point point {100, 200};
54     vector<TouchEvent> events;
55     action.Decompose(events, point, customOptions_);
56     ASSERT_EQ(2, events.size()); // up & down
57     auto event1 = *events.begin();
58     auto event2 = *(events.begin() + 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     GenericClick action(PointerOp::LONG_CLICK_P);
73     Point point {100, 200};
74     vector<TouchEvent> events;
75     action.Decompose(events, point, customOptions_);
76     ASSERT_EQ(2, events.size()); // up & down
77     auto event1 = *events.begin();
78     auto event2 = *(events.begin() + 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     GenericClick action(PointerOp::DOUBLE_CLICK_P);
95     Point point {100, 200};
96     vector<TouchEvent> events;
97     action.Decompose(events, point, customOptions_);
98     ASSERT_EQ(4, events.size()); // up-down-interval-up-down
99     auto event1 = *events.begin();
100     auto event2 = *(events.begin() + 1);
101     auto event3 = *(events.begin() + 2);
102     auto event4 = *(events.begin() + 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     UiDriveOptions opt {};
129     opt.swipeVelocityPps_ = 50; // specify the swipe velocity
130     Point point0(0, 0);
131     Point point1(100, 200);
132     GenericSwipe action(PointerOp::SWIPE_P);
133     vector<TouchEvent> events;
134     action.Decompose(events, point0, point1, opt);
135     // there should be more than 1 touches
136     const int32_t steps = events.size() - 1;
137     ASSERT_TRUE(steps > 1);
138 
139     const int32_t disX = point1.px_ - point0.px_;
140     const int32_t disY = point1.py_ - point0.py_;
141     const uint32_t distance = sqrt(disX * disX + disY * disY);
142     const uint32_t totalCostMs = distance * 1000 / opt.swipeVelocityPps_;
143 
144     uint32_t step = 0;
145     // check the TouchEvent of each step
146     for (auto &event:events) {
147         int32_t expectedPointerX = point0.px_ + (disX * step) / steps;
148         int32_t expectedPointerY = point0.py_ + (disY * step) / steps;
149         uint32_t expectedTimeOffset = (totalCostMs * step) / steps;
150         ASSERT_NEAR(expectedPointerX, event.point_.px_, 5);
151         ASSERT_NEAR(expectedPointerY, event.point_.py_, 5);
152         ASSERT_NEAR(expectedTimeOffset, event.downTimeOffsetMs_, 5);
153         if (step == 0) {
154             // should start with Action.DOWN
155             ASSERT_EQ(ActionStage::DOWN, event.stage_);
156         } else if (step == events.size() - 1) {
157             // should end with Action.UP
158             ASSERT_EQ(ActionStage::UP, event.stage_);
159         } else {
160             // middle events should all be action-MOVE
161             ASSERT_EQ(ActionStage::MOVE, event.stage_);
162         }
163         step++;
164     }
165 }
166 
TEST_F(UiActionTest,computeDragAction)167 TEST_F(UiActionTest, computeDragAction)
168 {
169     UiDriveOptions opt {};
170     opt.longClickHoldMs_ = 2000; // specify the long-click duration
171     Point point0(0, 0);
172     Point point1(100, 200);
173     GenericSwipe swipeAction(PointerOp::SWIPE_P);
174     GenericSwipe dragAction(PointerOp::DRAG_P);
175     vector<TouchEvent> swipeEvents;
176     vector<TouchEvent> dragEvents;
177     swipeAction.Decompose(swipeEvents, point0, point1, opt);
178     dragAction.Decompose(dragEvents, point0, point1, opt);
179 
180     ASSERT_TRUE(swipeEvents.size() > 1);\
181     ASSERT_EQ(swipeEvents.size(), dragEvents.size());
182 
183     // check the hold time of each event
184     for (auto step = 0; step < swipeEvents.size(); step++) {
185         auto &swipeEvent = swipeEvents.at(step);
186         auto &dragEvent = dragEvents.at(step);
187         ASSERT_EQ(swipeEvent.stage_, dragEvent.stage_);
188         // drag needs longPressDown firstly, the downOffSet of following event should be delayed
189         if (step == 0) {
190             ASSERT_EQ(swipeEvent.downTimeOffsetMs_, dragEvent.downTimeOffsetMs_);
191             ASSERT_EQ(swipeEvent.holdMs_ + opt.longClickHoldMs_, dragEvent.holdMs_);
192         } else {
193             ASSERT_EQ(swipeEvent.downTimeOffsetMs_ + opt.longClickHoldMs_, dragEvent.downTimeOffsetMs_);
194             ASSERT_EQ(swipeEvent.holdMs_, dragEvent.holdMs_);
195         }
196     }
197 }
198 
TEST_F(UiActionTest,computeBackKeyAction)199 TEST_F(UiActionTest, computeBackKeyAction)
200 {
201     Back keyAction;
202     vector<KeyEvent> events;
203     keyAction.ComputeEvents(events, customOptions_);
204     ASSERT_EQ(2, events.size()); // up & down
205     auto event1 = *events.begin();
206     auto event2 = *(events.begin() + 1);
207     ASSERT_EQ(KEYCODE_BACK, event1.code_);
208     ASSERT_EQ(ActionStage::DOWN, event1.stage_);
209 
210     ASSERT_EQ(KEYCODE_BACK, event2.code_);
211     ASSERT_EQ(ActionStage::UP, event2.stage_);
212     ASSERT_EQ(KEYNAME_BACK, keyAction.Describe()); // test the description
213 }
214 
TEST_F(UiActionTest,computePasteAction)215 TEST_F(UiActionTest, computePasteAction)
216 {
217     Paste keyAction;
218     vector<KeyEvent> events;
219     keyAction.ComputeEvents(events, customOptions_);
220     ASSERT_EQ(4, events.size()); // ctrl_down/key_down/key_up/ctrl_up
221     auto event1 = *events.begin();
222     auto event2 = *(events.begin() + 1);
223     auto event3 = *(events.begin() + 2);
224     auto event4 = *(events.begin() + 3);
225 
226     ASSERT_EQ(KEYCODE_CTRL, event1.code_);
227     ASSERT_EQ(ActionStage::DOWN, event1.stage_);
228     ASSERT_EQ(KEYCODE_V, event2.code_);
229     ASSERT_EQ(ActionStage::DOWN, event2.stage_);
230 
231     ASSERT_EQ(KEYCODE_V, event3.code_);
232     ASSERT_EQ(ActionStage::UP, event3.stage_);
233     ASSERT_EQ(KEYCODE_CTRL, event4.code_);
234     ASSERT_EQ(ActionStage::UP, event4.stage_);
235     ASSERT_EQ(KEYNAME_PASTE, keyAction.Describe());
236 }
237 
TEST_F(UiActionTest,anonymousSignleKey)238 TEST_F(UiActionTest, anonymousSignleKey)
239 {
240     static constexpr uint32_t keyCode = 1234;
241     static const string expectedDesc = "key_" + to_string(keyCode);
242     AnonymousSingleKey anonymousKey(keyCode);
243     vector<KeyEvent> events;
244     anonymousKey.ComputeEvents(events, customOptions_);
245     ASSERT_EQ(2, events.size()); // up & down
246     auto event1 = *events.begin();
247     auto event2 = *(events.begin() + 1);
248     ASSERT_EQ(keyCode, event1.code_);
249     ASSERT_EQ(ActionStage::DOWN, event1.stage_);
250 
251     ASSERT_EQ(keyCode, event2.code_);
252     ASSERT_EQ(ActionStage::UP, event2.stage_);
253     ASSERT_EQ(expectedDesc, anonymousKey.Describe());
254 }
255