1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include <cmath>
20 #include <compare>
21 #include <ios>
22
23 #include <android-base/stringprintf.h>
24 #include <android/input.h>
25 #include <gmock/gmock.h>
26 #include <gtest/gtest.h>
27 #include <input/Input.h>
28 #include <input/PrintTools.h>
29
30 #include "NotifyArgs.h"
31 #include "TestConstants.h"
32
33 namespace android {
34
35 struct PointF {
36 float x;
37 float y;
38 auto operator<=>(const PointF&) const = default;
39 };
40
41 namespace internal {
42
43 template <typename T>
valuesMatch(T value1,T value2)44 static bool valuesMatch(T value1, T value2) {
45 if constexpr (std::is_floating_point_v<T>) {
46 return std::abs(value1 - value2) < EPSILON;
47 } else {
48 return value1 == value2;
49 }
50 }
51
pointFToString(const PointF & p)52 inline std::string pointFToString(const PointF& p) {
53 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
54 }
55
56 } // namespace internal
57
58 /// Source
59 class WithSourceMatcher {
60 public:
61 using is_gtest_matcher = void;
WithSourceMatcher(uint32_t source)62 explicit WithSourceMatcher(uint32_t source) : mSource(source) {}
63
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)64 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
65 return mSource == args.source;
66 }
67
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)68 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
69 return mSource == args.source;
70 }
71
MatchAndExplain(const InputEvent & event,std::ostream *)72 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
73 return mSource == event.getSource();
74 }
75
DescribeTo(std::ostream * os)76 void DescribeTo(std::ostream* os) const {
77 *os << "with source " << inputEventSourceToString(mSource);
78 }
79
DescribeNegationTo(std::ostream * os)80 void DescribeNegationTo(std::ostream* os) const { *os << "wrong source"; }
81
82 private:
83 const uint32_t mSource;
84 };
85
WithSource(uint32_t source)86 inline WithSourceMatcher WithSource(uint32_t source) {
87 return WithSourceMatcher(source);
88 }
89
90 /// Key action
91 class WithKeyActionMatcher {
92 public:
93 using is_gtest_matcher = void;
WithKeyActionMatcher(int32_t action)94 explicit WithKeyActionMatcher(int32_t action) : mAction(action) {}
95
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)96 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
97 return mAction == args.action;
98 }
99
MatchAndExplain(const KeyEvent & event,std::ostream *)100 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
101 return mAction == event.getAction();
102 }
103
DescribeTo(std::ostream * os)104 void DescribeTo(std::ostream* os) const {
105 *os << "with key action " << KeyEvent::actionToString(mAction);
106 }
107
DescribeNegationTo(std::ostream * os)108 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
109
110 private:
111 const int32_t mAction;
112 };
113
WithKeyAction(int32_t action)114 inline WithKeyActionMatcher WithKeyAction(int32_t action) {
115 return WithKeyActionMatcher(action);
116 }
117
118 /// Motion action
119 class WithMotionActionMatcher {
120 public:
121 using is_gtest_matcher = void;
WithMotionActionMatcher(int32_t action)122 explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
123
MatchAndExplain(const NotifyMotionArgs & args,testing::MatchResultListener * listener)124 bool MatchAndExplain(const NotifyMotionArgs& args,
125 testing::MatchResultListener* listener) const {
126 if (mAction != args.action) {
127 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
128 << MotionEvent::actionToString(args.action);
129 return false;
130 }
131 if (args.action == AMOTION_EVENT_ACTION_CANCEL &&
132 (args.flags & AMOTION_EVENT_FLAG_CANCELED) == 0) {
133 *listener << "event with CANCEL action is missing FLAG_CANCELED";
134 return false;
135 }
136 return true;
137 }
138
MatchAndExplain(const MotionEvent & event,testing::MatchResultListener * listener)139 bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
140 if (mAction != event.getAction()) {
141 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
142 << MotionEvent::actionToString(event.getAction());
143 return false;
144 }
145 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
146 (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
147 *listener << "event with CANCEL action is missing FLAG_CANCELED";
148 return false;
149 }
150 return true;
151 }
152
DescribeTo(std::ostream * os)153 void DescribeTo(std::ostream* os) const {
154 *os << "with motion action " << MotionEvent::actionToString(mAction);
155 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
156 *os << " and FLAG_CANCELED";
157 }
158 }
159
DescribeNegationTo(std::ostream * os)160 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
161
162 private:
163 const int32_t mAction;
164 };
165
WithMotionAction(int32_t action)166 inline WithMotionActionMatcher WithMotionAction(int32_t action) {
167 return WithMotionActionMatcher(action);
168 }
169
170 /// Display Id
171 class WithDisplayIdMatcher {
172 public:
173 using is_gtest_matcher = void;
WithDisplayIdMatcher(ui::LogicalDisplayId displayId)174 explicit WithDisplayIdMatcher(ui::LogicalDisplayId displayId) : mDisplayId(displayId) {}
175
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)176 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
177 return mDisplayId == args.displayId;
178 }
179
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)180 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
181 return mDisplayId == args.displayId;
182 }
183
MatchAndExplain(const InputEvent & event,std::ostream *)184 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
185 return mDisplayId == event.getDisplayId();
186 }
187
DescribeTo(std::ostream * os)188 void DescribeTo(std::ostream* os) const { *os << "with display id " << mDisplayId; }
189
DescribeNegationTo(std::ostream * os)190 void DescribeNegationTo(std::ostream* os) const { *os << "wrong display id"; }
191
192 private:
193 const ui::LogicalDisplayId mDisplayId;
194 };
195
WithDisplayId(ui::LogicalDisplayId displayId)196 inline WithDisplayIdMatcher WithDisplayId(ui::LogicalDisplayId displayId) {
197 return WithDisplayIdMatcher(displayId);
198 }
199
200 /// Device Id
201 class WithDeviceIdMatcher {
202 public:
203 using is_gtest_matcher = void;
WithDeviceIdMatcher(int32_t deviceId)204 explicit WithDeviceIdMatcher(int32_t deviceId) : mDeviceId(deviceId) {}
205
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)206 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
207 return mDeviceId == args.deviceId;
208 }
209
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)210 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
211 return mDeviceId == args.deviceId;
212 }
213
MatchAndExplain(const NotifyDeviceResetArgs & args,std::ostream *)214 bool MatchAndExplain(const NotifyDeviceResetArgs& args, std::ostream*) const {
215 return mDeviceId == args.deviceId;
216 }
217
MatchAndExplain(const InputEvent & event,std::ostream *)218 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
219 return mDeviceId == event.getDeviceId();
220 }
221
DescribeTo(std::ostream * os)222 void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
223
DescribeNegationTo(std::ostream * os)224 void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
225
226 private:
227 const int32_t mDeviceId;
228 };
229
WithDeviceId(int32_t deviceId)230 inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
231 return WithDeviceIdMatcher(deviceId);
232 }
233
234 /// Flags
235 class WithFlagsMatcher {
236 public:
237 using is_gtest_matcher = void;
WithFlagsMatcher(int32_t flags)238 explicit WithFlagsMatcher(int32_t flags) : mFlags(flags) {}
239
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)240 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
241 return mFlags == args.flags;
242 }
243
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)244 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
245 return mFlags == args.flags;
246 }
247
MatchAndExplain(const MotionEvent & event,std::ostream *)248 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
249 return mFlags == event.getFlags();
250 }
251
MatchAndExplain(const KeyEvent & event,std::ostream *)252 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
253 return mFlags == event.getFlags();
254 }
255
DescribeTo(std::ostream * os)256 void DescribeTo(std::ostream* os) const {
257 *os << "with flags " << base::StringPrintf("0x%x", mFlags);
258 }
259
DescribeNegationTo(std::ostream * os)260 void DescribeNegationTo(std::ostream* os) const { *os << "wrong flags"; }
261
262 private:
263 const int32_t mFlags;
264 };
265
WithFlags(int32_t flags)266 inline WithFlagsMatcher WithFlags(int32_t flags) {
267 return WithFlagsMatcher(flags);
268 }
269
270 /// DownTime
271 class WithDownTimeMatcher {
272 public:
273 using is_gtest_matcher = void;
WithDownTimeMatcher(nsecs_t downTime)274 explicit WithDownTimeMatcher(nsecs_t downTime) : mDownTime(downTime) {}
275
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)276 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
277 return mDownTime == args.downTime;
278 }
279
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)280 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
281 return mDownTime == args.downTime;
282 }
283
MatchAndExplain(const MotionEvent & event,std::ostream *)284 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
285 return mDownTime == event.getDownTime();
286 }
287
MatchAndExplain(const KeyEvent & event,std::ostream *)288 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
289 return mDownTime == event.getDownTime();
290 }
291
DescribeTo(std::ostream * os)292 void DescribeTo(std::ostream* os) const { *os << "with down time " << mDownTime; }
293
DescribeNegationTo(std::ostream * os)294 void DescribeNegationTo(std::ostream* os) const { *os << "wrong down time"; }
295
296 private:
297 const nsecs_t mDownTime;
298 };
299
WithDownTime(nsecs_t downTime)300 inline WithDownTimeMatcher WithDownTime(nsecs_t downTime) {
301 return WithDownTimeMatcher(downTime);
302 }
303
304 /// Coordinate matcher
305 class WithCoordsMatcher {
306 public:
307 using is_gtest_matcher = void;
WithCoordsMatcher(size_t pointerIndex,float x,float y)308 explicit WithCoordsMatcher(size_t pointerIndex, float x, float y)
309 : mPointerIndex(pointerIndex), mX(x), mY(y) {}
310
MatchAndExplain(const MotionEvent & event,std::ostream * os)311 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
312 if (mPointerIndex >= event.getPointerCount()) {
313 *os << "Pointer index " << mPointerIndex << " is out of bounds";
314 return false;
315 }
316
317 bool matches = mX == event.getX(mPointerIndex) && mY == event.getY(mPointerIndex);
318 if (!matches) {
319 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
320 << ", but got (" << event.getX(mPointerIndex) << ", " << event.getY(mPointerIndex)
321 << ")";
322 }
323 return matches;
324 }
325
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)326 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
327 if (mPointerIndex >= event.pointerCoords.size()) {
328 *os << "Pointer index " << mPointerIndex << " is out of bounds";
329 return false;
330 }
331
332 bool matches = mX == event.pointerCoords[mPointerIndex].getX() &&
333 mY == event.pointerCoords[mPointerIndex].getY();
334 if (!matches) {
335 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
336 << ", but got (" << event.pointerCoords[mPointerIndex].getX() << ", "
337 << event.pointerCoords[mPointerIndex].getY() << ")";
338 }
339 return matches;
340 }
341
DescribeTo(std::ostream * os)342 void DescribeTo(std::ostream* os) const {
343 *os << "with coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex;
344 }
345
DescribeNegationTo(std::ostream * os)346 void DescribeNegationTo(std::ostream* os) const { *os << "wrong coords"; }
347
348 private:
349 const size_t mPointerIndex;
350 const float mX;
351 const float mY;
352 };
353
WithCoords(float x,float y)354 inline WithCoordsMatcher WithCoords(float x, float y) {
355 return WithCoordsMatcher(0, x, y);
356 }
357
WithPointerCoords(size_t pointerIndex,float x,float y)358 inline WithCoordsMatcher WithPointerCoords(size_t pointerIndex, float x, float y) {
359 return WithCoordsMatcher(pointerIndex, x, y);
360 }
361
362 /// Raw coordinate matcher
363 class WithRawCoordsMatcher {
364 public:
365 using is_gtest_matcher = void;
WithRawCoordsMatcher(size_t pointerIndex,float rawX,float rawY)366 explicit WithRawCoordsMatcher(size_t pointerIndex, float rawX, float rawY)
367 : mPointerIndex(pointerIndex), mRawX(rawX), mRawY(rawY) {}
368
MatchAndExplain(const MotionEvent & event,std::ostream * os)369 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
370 if (mPointerIndex >= event.getPointerCount()) {
371 *os << "Pointer index " << mPointerIndex << " is out of bounds";
372 return false;
373 }
374
375 bool matches =
376 mRawX == event.getRawX(mPointerIndex) && mRawY == event.getRawY(mPointerIndex);
377 if (!matches) {
378 *os << "expected raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
379 << mPointerIndex << ", but got (" << event.getRawX(mPointerIndex) << ", "
380 << event.getRawY(mPointerIndex) << ")";
381 }
382 return matches;
383 }
384
DescribeTo(std::ostream * os)385 void DescribeTo(std::ostream* os) const {
386 *os << "with raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
387 << mPointerIndex;
388 }
389
DescribeNegationTo(std::ostream * os)390 void DescribeNegationTo(std::ostream* os) const { *os << "wrong raw coords"; }
391
392 private:
393 const size_t mPointerIndex;
394 const float mRawX;
395 const float mRawY;
396 };
397
WithRawCoords(float rawX,float rawY)398 inline WithRawCoordsMatcher WithRawCoords(float rawX, float rawY) {
399 return WithRawCoordsMatcher(0, rawX, rawY);
400 }
401
WithPointerRawCoords(size_t pointerIndex,float rawX,float rawY)402 inline WithRawCoordsMatcher WithPointerRawCoords(size_t pointerIndex, float rawX, float rawY) {
403 return WithRawCoordsMatcher(pointerIndex, rawX, rawY);
404 }
405
406 /// Pointer count
407 class WithPointerCountMatcher {
408 public:
409 using is_gtest_matcher = void;
WithPointerCountMatcher(size_t pointerCount)410 explicit WithPointerCountMatcher(size_t pointerCount) : mPointerCount(pointerCount) {}
411
MatchAndExplain(const MotionEvent & event,std::ostream * os)412 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
413 if (event.getPointerCount() != mPointerCount) {
414 *os << "expected pointer count " << mPointerCount << ", but got "
415 << event.getPointerCount();
416 return false;
417 }
418 return true;
419 }
420
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)421 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
422 if (event.pointerCoords.size() != mPointerCount) {
423 *os << "expected pointer count " << mPointerCount << ", but got "
424 << event.pointerCoords.size();
425 return false;
426 }
427 return true;
428 }
429
DescribeTo(std::ostream * os)430 void DescribeTo(std::ostream* os) const { *os << "with pointer count " << mPointerCount; }
431
DescribeNegationTo(std::ostream * os)432 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer count"; }
433
434 private:
435 const size_t mPointerCount;
436 };
437
WithPointerCount(size_t pointerCount)438 inline WithPointerCountMatcher WithPointerCount(size_t pointerCount) {
439 return WithPointerCountMatcher(pointerCount);
440 }
441
442 /// Pointers matcher
443 class WithPointersMatcher {
444 public:
445 using is_gtest_matcher = void;
WithPointersMatcher(std::map<int32_t,PointF> pointers)446 explicit WithPointersMatcher(std::map<int32_t, PointF> pointers) : mPointers(pointers) {}
447
MatchAndExplain(const MotionEvent & event,std::ostream * os)448 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
449 std::map<int32_t, PointF> actualPointers;
450 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
451 const int32_t pointerId = event.getPointerId(pointerIndex);
452 actualPointers[pointerId] = {event.getX(pointerIndex), event.getY(pointerIndex)};
453 }
454
455 if (mPointers != actualPointers) {
456 *os << "expected pointers "
457 << dumpMap(mPointers, constToString, internal::pointFToString)
458 << ", but got "
459 << dumpMap(actualPointers, constToString, internal::pointFToString);
460 return false;
461 }
462 return true;
463 }
464
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)465 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
466 std::map<int32_t, PointF> actualPointers;
467 for (size_t pointerIndex = 0; pointerIndex < event.pointerCoords.size(); pointerIndex++) {
468 const int32_t pointerId = event.pointerProperties[pointerIndex].id;
469 actualPointers[pointerId] = {event.pointerCoords[pointerIndex].getX(),
470 event.pointerCoords[pointerIndex].getY()};
471 }
472
473 if (mPointers != actualPointers) {
474 *os << "expected pointers "
475 << dumpMap(mPointers, constToString, internal::pointFToString)
476 << ", but got "
477 << dumpMap(actualPointers, constToString, internal::pointFToString);
478 return false;
479 }
480 return true;
481 }
482
DescribeTo(std::ostream * os)483 void DescribeTo(std::ostream* os) const {
484 *os << "with pointers " << dumpMap(mPointers, constToString, internal::pointFToString);
485 }
486
DescribeNegationTo(std::ostream * os)487 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointers"; }
488
489 private:
490 const std::map<int32_t, PointF> mPointers;
491 };
492
WithPointers(const std::map<int32_t,PointF> & pointers)493 inline WithPointersMatcher WithPointers(
494 const std::map<int32_t /*id*/, PointF /*coords*/>& pointers) {
495 return WithPointersMatcher(pointers);
496 }
497
498 /// Pointer ids matcher
499 class WithPointerIdsMatcher {
500 public:
501 using is_gtest_matcher = void;
WithPointerIdsMatcher(std::set<int32_t> pointerIds)502 explicit WithPointerIdsMatcher(std::set<int32_t> pointerIds) : mPointerIds(pointerIds) {}
503
MatchAndExplain(const MotionEvent & event,std::ostream * os)504 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
505 std::set<int32_t> actualPointerIds;
506 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
507 const PointerProperties* properties = event.getPointerProperties(pointerIndex);
508 actualPointerIds.insert(properties->id);
509 }
510
511 if (mPointerIds != actualPointerIds) {
512 *os << "expected pointer ids " << dumpContainer(mPointerIds) << ", but got "
513 << dumpContainer(actualPointerIds);
514 return false;
515 }
516 return true;
517 }
518
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)519 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
520 std::set<int32_t> actualPointerIds;
521 for (const PointerProperties& properties : event.pointerProperties) {
522 actualPointerIds.insert(properties.id);
523 }
524
525 if (mPointerIds != actualPointerIds) {
526 *os << "expected pointer ids " << dumpContainer(mPointerIds) << ", but got "
527 << dumpContainer(actualPointerIds);
528 return false;
529 }
530 return true;
531 }
532
DescribeTo(std::ostream * os)533 void DescribeTo(std::ostream* os) const {
534 *os << "with pointer ids " << dumpContainer(mPointerIds);
535 }
536
DescribeNegationTo(std::ostream * os)537 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer ids"; }
538
539 private:
540 const std::set<int32_t> mPointerIds;
541 };
542
WithPointerIds(const std::set<int32_t> & pointerIds)543 inline WithPointerIdsMatcher WithPointerIds(const std::set<int32_t /*id*/>& pointerIds) {
544 return WithPointerIdsMatcher(pointerIds);
545 }
546
547 /// Key code
548 class WithKeyCodeMatcher {
549 public:
550 using is_gtest_matcher = void;
WithKeyCodeMatcher(int32_t keyCode)551 explicit WithKeyCodeMatcher(int32_t keyCode) : mKeyCode(keyCode) {}
552
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)553 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
554 return mKeyCode == args.keyCode;
555 }
556
MatchAndExplain(const KeyEvent & event,std::ostream *)557 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
558 return mKeyCode == event.getKeyCode();
559 }
560
DescribeTo(std::ostream * os)561 void DescribeTo(std::ostream* os) const {
562 *os << "with key code " << KeyEvent::getLabel(mKeyCode);
563 }
564
DescribeNegationTo(std::ostream * os)565 void DescribeNegationTo(std::ostream* os) const { *os << "wrong key code"; }
566
567 private:
568 const int32_t mKeyCode;
569 };
570
WithKeyCode(int32_t keyCode)571 inline WithKeyCodeMatcher WithKeyCode(int32_t keyCode) {
572 return WithKeyCodeMatcher(keyCode);
573 }
574
575 /// Scan code
576 class WithScanCodeMatcher {
577 public:
578 using is_gtest_matcher = void;
WithScanCodeMatcher(int32_t scanCode)579 explicit WithScanCodeMatcher(int32_t scanCode) : mScanCode(scanCode) {}
580
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)581 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
582 return mScanCode == args.scanCode;
583 }
584
MatchAndExplain(const KeyEvent & event,std::ostream *)585 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
586 return mScanCode == event.getKeyCode();
587 }
588
DescribeTo(std::ostream * os)589 void DescribeTo(std::ostream* os) const {
590 *os << "with scan code " << KeyEvent::getLabel(mScanCode);
591 }
592
DescribeNegationTo(std::ostream * os)593 void DescribeNegationTo(std::ostream* os) const { *os << "wrong scan code"; }
594
595 private:
596 const int32_t mScanCode;
597 };
598
WithScanCode(int32_t scanCode)599 inline WithScanCodeMatcher WithScanCode(int32_t scanCode) {
600 return WithScanCodeMatcher(scanCode);
601 }
602
603 /// EventId
604 class WithEventIdMatcher {
605 public:
606 using is_gtest_matcher = void;
WithEventIdMatcher(int32_t eventId)607 explicit WithEventIdMatcher(int32_t eventId) : mEventId(eventId) {}
608
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)609 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
610 return mEventId == args.id;
611 }
612
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)613 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
614 return mEventId == args.id;
615 }
616
MatchAndExplain(const InputEvent & event,std::ostream *)617 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
618 return mEventId == event.getId();
619 }
620
DescribeTo(std::ostream * os)621 void DescribeTo(std::ostream* os) const { *os << "with eventId 0x" << std::hex << mEventId; }
622
DescribeNegationTo(std::ostream * os)623 void DescribeNegationTo(std::ostream* os) const {
624 *os << "with eventId not equal to 0x" << std::hex << mEventId;
625 }
626
627 private:
628 const int32_t mEventId;
629 };
630
WithEventId(int32_t eventId)631 inline WithEventIdMatcher WithEventId(int32_t eventId) {
632 return WithEventIdMatcher(eventId);
633 }
634
635 /// EventIdSource
636 class WithEventIdSourceMatcher {
637 public:
638 using is_gtest_matcher = void;
WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)639 explicit WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)
640 : mEventIdSource(eventIdSource) {}
641
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)642 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
643 return mEventIdSource == IdGenerator::getSource(args.id);
644 }
645
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)646 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
647 return mEventIdSource == IdGenerator::getSource(args.id);
648 }
649
MatchAndExplain(const InputEvent & event,std::ostream *)650 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
651 return mEventIdSource == IdGenerator::getSource(event.getId());
652 }
653
DescribeTo(std::ostream * os)654 void DescribeTo(std::ostream* os) const {
655 *os << "with eventId from source 0x" << std::hex << ftl::to_underlying(mEventIdSource);
656 }
657
DescribeNegationTo(std::ostream * os)658 void DescribeNegationTo(std::ostream* os) const { *os << "wrong event from source"; }
659
660 private:
661 const IdGenerator::Source mEventIdSource;
662 };
663
WithEventIdSource(IdGenerator::Source eventIdSource)664 inline WithEventIdSourceMatcher WithEventIdSource(IdGenerator::Source eventIdSource) {
665 return WithEventIdSourceMatcher(eventIdSource);
666 }
667
668 MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") {
669 return arg.getRepeatCount() == repeatCount;
670 }
671
672 class WithPointerIdMatcher {
673 public:
674 using is_gtest_matcher = void;
WithPointerIdMatcher(size_t index,int32_t pointerId)675 explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
676 : mIndex(index), mPointerId(pointerId) {}
677
MatchAndExplain(const NotifyMotionArgs & args,std::ostream * os)678 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream* os) const {
679 if (mIndex >= args.pointerCoords.size()) {
680 *os << "Pointer index " << mIndex << " is out of bounds";
681 return false;
682 }
683
684 return args.pointerProperties[mIndex].id == mPointerId;
685 }
686
MatchAndExplain(const MotionEvent & event,std::ostream *)687 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
688 return event.getPointerId(mIndex) == mPointerId;
689 }
690
DescribeTo(std::ostream * os)691 void DescribeTo(std::ostream* os) const {
692 *os << "with pointer[" << mIndex << "] id = " << mPointerId;
693 }
694
DescribeNegationTo(std::ostream * os)695 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; }
696
697 private:
698 const size_t mIndex;
699 const int32_t mPointerId;
700 };
701
WithPointerId(size_t index,int32_t pointerId)702 inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) {
703 return WithPointerIdMatcher(index, pointerId);
704 }
705
706 MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") {
707 const auto argX = arg.xCursorPosition;
708 const auto argY = arg.yCursorPosition;
709 *result_listener << "expected cursor position (" << x << ", " << y << "), but got (" << argX
710 << ", " << argY << ")";
711 return (isnan(x) ? isnan(argX) : x == argX) && (isnan(y) ? isnan(argY) : y == argY);
712 }
713
714 /// Relative motion matcher
715 class WithRelativeMotionMatcher {
716 public:
717 using is_gtest_matcher = void;
WithRelativeMotionMatcher(size_t pointerIndex,float relX,float relY)718 explicit WithRelativeMotionMatcher(size_t pointerIndex, float relX, float relY)
719 : mPointerIndex(pointerIndex), mRelX(relX), mRelY(relY) {}
720
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)721 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
722 if (mPointerIndex >= event.pointerCoords.size()) {
723 *os << "Pointer index " << mPointerIndex << " is out of bounds";
724 return false;
725 }
726
727 const PointerCoords& coords = event.pointerCoords[mPointerIndex];
728 bool matches =
729 internal::valuesMatch(mRelX, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X)) &&
730 internal::valuesMatch(mRelY, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
731 if (!matches) {
732 *os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
733 << mPointerIndex << ", but got ("
734 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) << ", "
735 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y) << ")";
736 }
737 return matches;
738 }
739
DescribeTo(std::ostream * os)740 void DescribeTo(std::ostream* os) const {
741 *os << "with relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
742 << mPointerIndex;
743 }
744
DescribeNegationTo(std::ostream * os)745 void DescribeNegationTo(std::ostream* os) const { *os << "wrong relative motion"; }
746
747 private:
748 const size_t mPointerIndex;
749 const float mRelX;
750 const float mRelY;
751 };
752
WithRelativeMotion(float relX,float relY)753 inline WithRelativeMotionMatcher WithRelativeMotion(float relX, float relY) {
754 return WithRelativeMotionMatcher(0, relX, relY);
755 }
756
WithPointerRelativeMotion(size_t pointerIndex,float relX,float relY)757 inline WithRelativeMotionMatcher WithPointerRelativeMotion(size_t pointerIndex, float relX,
758 float relY) {
759 return WithRelativeMotionMatcher(pointerIndex, relX, relY);
760 }
761
762 MATCHER_P3(WithGestureOffset, dx, dy, epsilon,
763 "InputEvent with specified touchpad gesture offset") {
764 const auto argGestureX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET);
765 const auto argGestureY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET);
766 const double xDiff = fabs(argGestureX - dx);
767 const double yDiff = fabs(argGestureY - dy);
768 *result_listener << "expected gesture offset (" << dx << ", " << dy << ") within " << epsilon
769 << ", but got (" << argGestureX << ", " << argGestureY << ")";
770 return xDiff <= epsilon && yDiff <= epsilon;
771 }
772
773 MATCHER_P3(WithGestureScrollDistance, x, y, epsilon,
774 "InputEvent with specified touchpad gesture scroll distance") {
775 const auto argXDistance =
776 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE);
777 const auto argYDistance =
778 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE);
779 const double xDiff = fabs(argXDistance - x);
780 const double yDiff = fabs(argYDistance - y);
781 *result_listener << "expected gesture offset (" << x << ", " << y << ") within " << epsilon
782 << ", but got (" << argXDistance << ", " << argYDistance << ")";
783 return xDiff <= epsilon && yDiff <= epsilon;
784 }
785
786 MATCHER_P2(WithGesturePinchScaleFactor, factor, epsilon,
787 "InputEvent with specified touchpad pinch gesture scale factor") {
788 const auto argScaleFactor =
789 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR);
790 *result_listener << "expected gesture scale factor " << factor << " within " << epsilon
791 << " but got " << argScaleFactor;
792 return fabs(argScaleFactor - factor) <= epsilon;
793 }
794
795 MATCHER_P(WithGestureSwipeFingerCount, count,
796 "InputEvent with specified touchpad swipe finger count") {
797 const auto argFingerCount =
798 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SWIPE_FINGER_COUNT);
799 *result_listener << "expected gesture swipe finger count " << count << " but got "
800 << argFingerCount;
801 return fabs(argFingerCount - count) <= EPSILON;
802 }
803
804 MATCHER_P(WithPressure, pressure, "InputEvent with specified pressure") {
805 const auto argPressure = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
806 *result_listener << "expected pressure " << pressure << ", but got " << argPressure;
807 return argPressure == pressure;
808 }
809
810 MATCHER_P(WithSize, size, "MotionEvent with specified size") {
811 const auto argSize = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE);
812 *result_listener << "expected size " << size << ", but got " << argSize;
813 return argSize == size;
814 }
815
816 MATCHER_P(WithOrientation, orientation, "MotionEvent with specified orientation") {
817 const auto argOrientation = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
818 *result_listener << "expected orientation " << orientation << ", but got " << argOrientation;
819 return argOrientation == orientation;
820 }
821
822 MATCHER_P(WithDistance, distance, "MotionEvent with specified distance") {
823 const auto argDistance = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_DISTANCE);
824 *result_listener << "expected distance " << distance << ", but got " << argDistance;
825 return argDistance == distance;
826 }
827
828 MATCHER_P(WithScroll, scroll, "InputEvent with specified scroll value") {
829 const auto argScroll = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SCROLL);
830 *result_listener << "expected scroll value " << scroll << ", but got " << argScroll;
831 return argScroll == scroll;
832 }
833
834 MATCHER_P2(WithScroll, scrollX, scrollY, "InputEvent with specified scroll values") {
835 const auto argScrollX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_HSCROLL);
836 const auto argScrollY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_VSCROLL);
837 *result_listener << "expected scroll values " << scrollX << " scroll x " << scrollY
838 << " scroll y, but got " << argScrollX << " scroll x " << argScrollY
839 << " scroll y";
840 return argScrollX == scrollX && argScrollY == scrollY;
841 }
842
843 MATCHER_P2(WithTouchDimensions, maj, min, "InputEvent with specified touch dimensions") {
844 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
845 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
846 *result_listener << "expected touch dimensions " << maj << " major x " << min
847 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
848 return argMajor == maj && argMinor == min;
849 }
850
851 MATCHER_P2(WithToolDimensions, maj, min, "InputEvent with specified tool dimensions") {
852 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR);
853 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR);
854 *result_listener << "expected tool dimensions " << maj << " major x " << min
855 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
856 return argMajor == maj && argMinor == min;
857 }
858
859 MATCHER_P(WithToolType, toolType, "InputEvent with specified tool type") {
860 const auto argToolType = arg.pointerProperties[0].toolType;
861 *result_listener << "expected tool type " << ftl::enum_string(toolType) << ", but got "
862 << ftl::enum_string(argToolType);
863 return argToolType == toolType;
864 }
865
866 MATCHER_P2(WithPointerToolType, pointerIndex, toolType,
867 "InputEvent with specified tool type for pointer") {
868 if (std::cmp_greater_equal(pointerIndex, arg.getPointerCount())) {
869 *result_listener << "Pointer index " << pointerIndex << " is out of bounds";
870 return false;
871 }
872 const auto argToolType = arg.pointerProperties[pointerIndex].toolType;
873 *result_listener << "expected pointer " << pointerIndex << " to have tool type "
874 << ftl::enum_string(toolType) << ", but got " << ftl::enum_string(argToolType);
875 return argToolType == toolType;
876 }
877
878 MATCHER_P(WithMotionClassification, classification,
879 "InputEvent with specified MotionClassification") {
880 *result_listener << "expected classification " << motionClassificationToString(classification)
881 << ", but got " << motionClassificationToString(arg.classification);
882 return arg.classification == classification;
883 }
884
885 MATCHER_P(WithButtonState, buttons, "InputEvent with specified button state") {
886 *result_listener << "expected button state " << buttons << ", but got " << arg.buttonState;
887 return arg.buttonState == buttons;
888 }
889
890 MATCHER_P(WithMetaState, metaState, "InputEvent with specified meta state") {
891 *result_listener << "expected meta state 0x" << std::hex << metaState << ", but got 0x"
892 << arg.metaState;
893 return arg.metaState == metaState;
894 }
895
896 MATCHER_P(WithActionButton, actionButton, "InputEvent with specified action button") {
897 *result_listener << "expected action button " << actionButton << ", but got "
898 << arg.actionButton;
899 return arg.actionButton == actionButton;
900 }
901
902 MATCHER_P(WithEventTime, eventTime, "InputEvent with specified eventTime") {
903 *result_listener << "expected event time " << eventTime << ", but got " << arg.eventTime;
904 return arg.eventTime == eventTime;
905 }
906
907 MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
908 *result_listener << "expected down time " << downTime << ", but got " << arg.downTime;
909 return arg.downTime == downTime;
910 }
911
912 MATCHER_P2(WithPrecision, xPrecision, yPrecision, "MotionEvent with specified precision") {
913 *result_listener << "expected x-precision " << xPrecision << " and y-precision " << yPrecision
914 << ", but got " << arg.xPrecision << " and " << arg.yPrecision;
915 return arg.xPrecision == xPrecision && arg.yPrecision == yPrecision;
916 }
917
918 MATCHER_P(WithPolicyFlags, policyFlags, "InputEvent with specified policy flags") {
919 *result_listener << "expected policy flags 0x" << std::hex << policyFlags << ", but got 0x"
920 << arg.policyFlags;
921 return arg.policyFlags == static_cast<uint32_t>(policyFlags);
922 }
923
924 MATCHER_P(WithEdgeFlags, edgeFlags, "InputEvent with specified edge flags") {
925 *result_listener << "expected edge flags 0x" << std::hex << edgeFlags << ", but got 0x"
926 << arg.edgeFlags;
927 return arg.edgeFlags == edgeFlags;
928 }
929
930 } // namespace android
931