blob: 7078e49343c4763f8dac08b0854bee3b24bb1ca5 [file] [log] [blame]
Prabir Pradhan739dca42022-09-09 20:12:01 +00001/*
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
Prabir Pradhan48108662022-09-09 21:22:04 +000017#pragma once
Prabir Pradhan739dca42022-09-09 20:12:01 +000018
Harry Cuttsc5748d12022-12-02 17:30:18 +000019#include <cmath>
Prabir Pradhan7b6502d2023-10-06 04:08:39 +000020#include <compare>
Harry Cutts7ecbb992023-12-18 14:45:09 +000021#include <ios>
Harry Cuttsc5748d12022-12-02 17:30:18 +000022
Prabir Pradhan7b6502d2023-10-06 04:08:39 +000023#include <android-base/stringprintf.h>
Prabir Pradhan739dca42022-09-09 20:12:01 +000024#include <android/input.h>
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
Prabir Pradhanda20b172022-09-26 17:01:18 +000027#include <input/Input.h>
Prabir Pradhan7b6502d2023-10-06 04:08:39 +000028#include <input/PrintTools.h>
Prabir Pradhan739dca42022-09-09 20:12:01 +000029
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070030#include "NotifyArgs.h"
Harry Cutts8743f182023-05-17 12:03:49 +000031#include "TestConstants.h"
32
Prabir Pradhan739dca42022-09-09 20:12:01 +000033namespace android {
34
Prabir Pradhan7b6502d2023-10-06 04:08:39 +000035struct PointF {
36 float x;
37 float y;
38 auto operator<=>(const PointF&) const = default;
39};
40
41inline std::string pointFToString(const PointF& p) {
42 return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
43}
44
45/// Source
46class WithSourceMatcher {
47public:
48 using is_gtest_matcher = void;
49 explicit WithSourceMatcher(uint32_t source) : mSource(source) {}
50
51 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
52 return mSource == args.source;
53 }
54
55 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
56 return mSource == args.source;
57 }
58
59 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
60 return mSource == event.getSource();
61 }
62
63 void DescribeTo(std::ostream* os) const {
64 *os << "with source " << inputEventSourceToString(mSource);
65 }
66
67 void DescribeNegationTo(std::ostream* os) const { *os << "wrong source"; }
68
69private:
70 const uint32_t mSource;
71};
72
73inline WithSourceMatcher WithSource(uint32_t source) {
74 return WithSourceMatcher(source);
Prabir Pradhan739dca42022-09-09 20:12:01 +000075}
76
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070077/// Key action
78class WithKeyActionMatcher {
79public:
80 using is_gtest_matcher = void;
81 explicit WithKeyActionMatcher(int32_t action) : mAction(action) {}
Prabir Pradhan739dca42022-09-09 20:12:01 +000082
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070083 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
84 return mAction == args.action;
85 }
86
87 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
88 return mAction == event.getAction();
89 }
90
91 void DescribeTo(std::ostream* os) const {
92 *os << "with key action " << KeyEvent::actionToString(mAction);
93 }
94
95 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
96
97private:
98 const int32_t mAction;
99};
100
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000101inline WithKeyActionMatcher WithKeyAction(int32_t action) {
102 return WithKeyActionMatcher(action);
103}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700104
105/// Motion action
106class WithMotionActionMatcher {
107public:
108 using is_gtest_matcher = void;
109 explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
110
Harry Cuttsfb6d5852024-10-29 11:47:32 +0000111 bool MatchAndExplain(const NotifyMotionArgs& args,
112 testing::MatchResultListener* listener) const {
113 if (mAction != args.action) {
114 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
115 << MotionEvent::actionToString(args.action);
116 return false;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700117 }
Harry Cuttsfb6d5852024-10-29 11:47:32 +0000118 if (args.action == AMOTION_EVENT_ACTION_CANCEL &&
119 (args.flags & AMOTION_EVENT_FLAG_CANCELED) == 0) {
120 *listener << "event with CANCEL action is missing FLAG_CANCELED";
121 return false;
122 }
123 return true;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700124 }
125
Harry Cuttsfb6d5852024-10-29 11:47:32 +0000126 bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
127 if (mAction != event.getAction()) {
128 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
129 << MotionEvent::actionToString(event.getAction());
130 return false;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700131 }
Harry Cuttsfb6d5852024-10-29 11:47:32 +0000132 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
133 (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
134 *listener << "event with CANCEL action is missing FLAG_CANCELED";
135 return false;
136 }
137 return true;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700138 }
139
140 void DescribeTo(std::ostream* os) const {
141 *os << "with motion action " << MotionEvent::actionToString(mAction);
142 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
143 *os << " and FLAG_CANCELED";
144 }
145 }
146
147 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
148
149private:
150 const int32_t mAction;
151};
152
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000153inline WithMotionActionMatcher WithMotionAction(int32_t action) {
154 return WithMotionActionMatcher(action);
155}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700156
157/// Display Id
158class WithDisplayIdMatcher {
159public:
160 using is_gtest_matcher = void;
Linnan Li13bf76a2024-05-05 19:18:02 +0800161 explicit WithDisplayIdMatcher(ui::LogicalDisplayId displayId) : mDisplayId(displayId) {}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700162
163 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
164 return mDisplayId == args.displayId;
165 }
166
167 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
168 return mDisplayId == args.displayId;
169 }
170
171 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
172 return mDisplayId == event.getDisplayId();
173 }
174
175 void DescribeTo(std::ostream* os) const { *os << "with display id " << mDisplayId; }
176
177 void DescribeNegationTo(std::ostream* os) const { *os << "wrong display id"; }
178
179private:
Linnan Li13bf76a2024-05-05 19:18:02 +0800180 const ui::LogicalDisplayId mDisplayId;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700181};
182
Linnan Li13bf76a2024-05-05 19:18:02 +0800183inline WithDisplayIdMatcher WithDisplayId(ui::LogicalDisplayId displayId) {
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000184 return WithDisplayIdMatcher(displayId);
185}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700186
187/// Device Id
188class WithDeviceIdMatcher {
189public:
190 using is_gtest_matcher = void;
191 explicit WithDeviceIdMatcher(int32_t deviceId) : mDeviceId(deviceId) {}
192
193 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
194 return mDeviceId == args.deviceId;
195 }
196
197 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
198 return mDeviceId == args.deviceId;
199 }
200
Prabir Pradhan85cf63e2023-08-07 21:02:13 +0000201 bool MatchAndExplain(const NotifyDeviceResetArgs& args, std::ostream*) const {
202 return mDeviceId == args.deviceId;
203 }
204
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700205 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
206 return mDeviceId == event.getDeviceId();
207 }
208
209 void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
210
211 void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
212
213private:
214 const int32_t mDeviceId;
215};
216
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000217inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
218 return WithDeviceIdMatcher(deviceId);
219}
220
221/// Flags
222class WithFlagsMatcher {
223public:
224 using is_gtest_matcher = void;
225 explicit WithFlagsMatcher(int32_t flags) : mFlags(flags) {}
226
227 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
228 return mFlags == args.flags;
229 }
230
231 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
232 return mFlags == args.flags;
233 }
234
235 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
236 return mFlags == event.getFlags();
237 }
238
239 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
240 return mFlags == event.getFlags();
241 }
242
243 void DescribeTo(std::ostream* os) const {
244 *os << "with flags " << base::StringPrintf("0x%x", mFlags);
245 }
246
247 void DescribeNegationTo(std::ostream* os) const { *os << "wrong flags"; }
248
249private:
250 const int32_t mFlags;
251};
252
253inline WithFlagsMatcher WithFlags(int32_t flags) {
254 return WithFlagsMatcher(flags);
255}
256
257/// DownTime
258class WithDownTimeMatcher {
259public:
260 using is_gtest_matcher = void;
261 explicit WithDownTimeMatcher(nsecs_t downTime) : mDownTime(downTime) {}
262
263 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
264 return mDownTime == args.downTime;
265 }
266
267 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
268 return mDownTime == args.downTime;
269 }
270
271 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
272 return mDownTime == event.getDownTime();
273 }
274
275 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
276 return mDownTime == event.getDownTime();
277 }
278
279 void DescribeTo(std::ostream* os) const { *os << "with down time " << mDownTime; }
280
281 void DescribeNegationTo(std::ostream* os) const { *os << "wrong down time"; }
282
283private:
284 const nsecs_t mDownTime;
285};
286
287inline WithDownTimeMatcher WithDownTime(nsecs_t downTime) {
288 return WithDownTimeMatcher(downTime);
289}
290
291/// Coordinate matcher
292class WithCoordsMatcher {
293public:
294 using is_gtest_matcher = void;
295 explicit WithCoordsMatcher(size_t pointerIndex, float x, float y)
296 : mPointerIndex(pointerIndex), mX(x), mY(y) {}
297
298 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
299 if (mPointerIndex >= event.getPointerCount()) {
300 *os << "Pointer index " << mPointerIndex << " is out of bounds";
301 return false;
302 }
303
304 bool matches = mX == event.getX(mPointerIndex) && mY == event.getY(mPointerIndex);
305 if (!matches) {
306 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
307 << ", but got (" << event.getX(mPointerIndex) << ", " << event.getY(mPointerIndex)
308 << ")";
309 }
310 return matches;
311 }
312
313 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
314 if (mPointerIndex >= event.pointerCoords.size()) {
315 *os << "Pointer index " << mPointerIndex << " is out of bounds";
316 return false;
317 }
318
319 bool matches = mX == event.pointerCoords[mPointerIndex].getX() &&
320 mY == event.pointerCoords[mPointerIndex].getY();
321 if (!matches) {
322 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
323 << ", but got (" << event.pointerCoords[mPointerIndex].getX() << ", "
324 << event.pointerCoords[mPointerIndex].getY() << ")";
325 }
326 return matches;
327 }
328
329 void DescribeTo(std::ostream* os) const {
330 *os << "with coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex;
331 }
332
333 void DescribeNegationTo(std::ostream* os) const { *os << "wrong coords"; }
334
335private:
336 const size_t mPointerIndex;
337 const float mX;
338 const float mY;
339};
340
341inline WithCoordsMatcher WithCoords(float x, float y) {
342 return WithCoordsMatcher(0, x, y);
343}
344
345inline WithCoordsMatcher WithPointerCoords(size_t pointerIndex, float x, float y) {
346 return WithCoordsMatcher(pointerIndex, x, y);
347}
348
349/// Raw coordinate matcher
350class WithRawCoordsMatcher {
351public:
352 using is_gtest_matcher = void;
353 explicit WithRawCoordsMatcher(size_t pointerIndex, float rawX, float rawY)
354 : mPointerIndex(pointerIndex), mRawX(rawX), mRawY(rawY) {}
355
356 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
357 if (mPointerIndex >= event.getPointerCount()) {
358 *os << "Pointer index " << mPointerIndex << " is out of bounds";
359 return false;
360 }
361
362 bool matches =
363 mRawX == event.getRawX(mPointerIndex) && mRawY == event.getRawY(mPointerIndex);
364 if (!matches) {
365 *os << "expected raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
366 << mPointerIndex << ", but got (" << event.getRawX(mPointerIndex) << ", "
367 << event.getRawY(mPointerIndex) << ")";
368 }
369 return matches;
370 }
371
372 void DescribeTo(std::ostream* os) const {
373 *os << "with raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
374 << mPointerIndex;
375 }
376
377 void DescribeNegationTo(std::ostream* os) const { *os << "wrong raw coords"; }
378
379private:
380 const size_t mPointerIndex;
381 const float mRawX;
382 const float mRawY;
383};
384
385inline WithRawCoordsMatcher WithRawCoords(float rawX, float rawY) {
386 return WithRawCoordsMatcher(0, rawX, rawY);
387}
388
389inline WithRawCoordsMatcher WithPointerRawCoords(size_t pointerIndex, float rawX, float rawY) {
390 return WithRawCoordsMatcher(pointerIndex, rawX, rawY);
391}
392
393/// Pointer count
394class WithPointerCountMatcher {
395public:
396 using is_gtest_matcher = void;
397 explicit WithPointerCountMatcher(size_t pointerCount) : mPointerCount(pointerCount) {}
398
399 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
400 if (event.getPointerCount() != mPointerCount) {
401 *os << "expected pointer count " << mPointerCount << ", but got "
402 << event.getPointerCount();
403 return false;
404 }
405 return true;
406 }
407
408 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
409 if (event.pointerCoords.size() != mPointerCount) {
410 *os << "expected pointer count " << mPointerCount << ", but got "
411 << event.pointerCoords.size();
412 return false;
413 }
414 return true;
415 }
416
417 void DescribeTo(std::ostream* os) const { *os << "with pointer count " << mPointerCount; }
418
419 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer count"; }
420
421private:
422 const size_t mPointerCount;
423};
424
425inline WithPointerCountMatcher WithPointerCount(size_t pointerCount) {
426 return WithPointerCountMatcher(pointerCount);
427}
428
429/// Pointers matcher
430class WithPointersMatcher {
431public:
432 using is_gtest_matcher = void;
433 explicit WithPointersMatcher(std::map<int32_t, PointF> pointers) : mPointers(pointers) {}
434
435 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
436 std::map<int32_t, PointF> actualPointers;
437 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
438 const int32_t pointerId = event.getPointerId(pointerIndex);
439 actualPointers[pointerId] = {event.getX(pointerIndex), event.getY(pointerIndex)};
440 }
441
442 if (mPointers != actualPointers) {
443 *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
444 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
445 return false;
446 }
447 return true;
448 }
449
450 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
451 std::map<int32_t, PointF> actualPointers;
452 for (size_t pointerIndex = 0; pointerIndex < event.pointerCoords.size(); pointerIndex++) {
453 const int32_t pointerId = event.pointerProperties[pointerIndex].id;
454 actualPointers[pointerId] = {event.pointerCoords[pointerIndex].getX(),
455 event.pointerCoords[pointerIndex].getY()};
456 }
457
458 if (mPointers != actualPointers) {
459 *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
460 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
461 return false;
462 }
463 return true;
464 }
465
466 void DescribeTo(std::ostream* os) const {
467 *os << "with pointers " << dumpMap(mPointers, constToString, pointFToString);
468 }
469
470 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointers"; }
471
472private:
473 const std::map<int32_t, PointF> mPointers;
474};
475
476inline WithPointersMatcher WithPointers(
477 const std::map<int32_t /*id*/, PointF /*coords*/>& pointers) {
478 return WithPointersMatcher(pointers);
479}
Prabir Pradhan484d55a2022-10-14 23:17:16 +0000480
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800481/// Pointer ids matcher
482class WithPointerIdsMatcher {
483public:
484 using is_gtest_matcher = void;
485 explicit WithPointerIdsMatcher(std::set<int32_t> pointerIds) : mPointerIds(pointerIds) {}
486
487 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
488 std::set<int32_t> actualPointerIds;
489 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
490 const PointerProperties* properties = event.getPointerProperties(pointerIndex);
491 actualPointerIds.insert(properties->id);
492 }
493
494 if (mPointerIds != actualPointerIds) {
495 *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
496 << dumpSet(actualPointerIds);
497 return false;
498 }
499 return true;
500 }
501
502 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
503 std::set<int32_t> actualPointerIds;
504 for (const PointerProperties& properties : event.pointerProperties) {
505 actualPointerIds.insert(properties.id);
506 }
507
508 if (mPointerIds != actualPointerIds) {
509 *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
510 << dumpSet(actualPointerIds);
511 return false;
512 }
513 return true;
514 }
515
516 void DescribeTo(std::ostream* os) const { *os << "with pointer ids " << dumpSet(mPointerIds); }
517
518 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer ids"; }
519
520private:
521 const std::set<int32_t> mPointerIds;
522};
523
524inline WithPointerIdsMatcher WithPointerIds(const std::set<int32_t /*id*/>& pointerIds) {
525 return WithPointerIdsMatcher(pointerIds);
526}
527
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000528/// Key code
529class WithKeyCodeMatcher {
530public:
531 using is_gtest_matcher = void;
532 explicit WithKeyCodeMatcher(int32_t keyCode) : mKeyCode(keyCode) {}
533
534 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
535 return mKeyCode == args.keyCode;
536 }
537
538 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
539 return mKeyCode == event.getKeyCode();
540 }
541
542 void DescribeTo(std::ostream* os) const {
543 *os << "with key code " << KeyEvent::getLabel(mKeyCode);
544 }
545
546 void DescribeNegationTo(std::ostream* os) const { *os << "wrong key code"; }
547
548private:
549 const int32_t mKeyCode;
550};
551
552inline WithKeyCodeMatcher WithKeyCode(int32_t keyCode) {
553 return WithKeyCodeMatcher(keyCode);
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000554}
555
David Padlipsky48fd8842024-10-18 03:36:58 +0000556/// Scan code
557class WithScanCodeMatcher {
558public:
559 using is_gtest_matcher = void;
560 explicit WithScanCodeMatcher(int32_t scanCode) : mScanCode(scanCode) {}
561
562 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
563 return mScanCode == args.scanCode;
564 }
565
566 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
567 return mScanCode == event.getKeyCode();
568 }
569
570 void DescribeTo(std::ostream* os) const {
571 *os << "with scan code " << KeyEvent::getLabel(mScanCode);
572 }
573
574 void DescribeNegationTo(std::ostream* os) const { *os << "wrong scan code"; }
575
576private:
577 const int32_t mScanCode;
578};
579
580inline WithScanCodeMatcher WithScanCode(int32_t scanCode) {
581 return WithScanCodeMatcher(scanCode);
582}
583
Prabir Pradhan5893d362023-11-17 04:30:40 +0000584/// EventId
585class WithEventIdMatcher {
586public:
587 using is_gtest_matcher = void;
588 explicit WithEventIdMatcher(int32_t eventId) : mEventId(eventId) {}
589
590 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
591 return mEventId == args.id;
592 }
593
594 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
595 return mEventId == args.id;
596 }
597
598 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
599 return mEventId == event.getId();
600 }
601
602 void DescribeTo(std::ostream* os) const { *os << "with eventId 0x" << std::hex << mEventId; }
603
604 void DescribeNegationTo(std::ostream* os) const {
605 *os << "with eventId not equal to 0x" << std::hex << mEventId;
606 }
607
608private:
609 const int32_t mEventId;
610};
611
612inline WithEventIdMatcher WithEventId(int32_t eventId) {
613 return WithEventIdMatcher(eventId);
614}
615
616/// EventIdSource
617class WithEventIdSourceMatcher {
618public:
619 using is_gtest_matcher = void;
620 explicit WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)
621 : mEventIdSource(eventIdSource) {}
622
623 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
624 return mEventIdSource == IdGenerator::getSource(args.id);
625 }
626
627 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
628 return mEventIdSource == IdGenerator::getSource(args.id);
629 }
630
631 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
632 return mEventIdSource == IdGenerator::getSource(event.getId());
633 }
634
635 void DescribeTo(std::ostream* os) const {
636 *os << "with eventId from source 0x" << std::hex << ftl::to_underlying(mEventIdSource);
637 }
638
639 void DescribeNegationTo(std::ostream* os) const { *os << "wrong event from source"; }
640
641private:
642 const IdGenerator::Source mEventIdSource;
643};
644
645inline WithEventIdSourceMatcher WithEventIdSource(IdGenerator::Source eventIdSource) {
646 return WithEventIdSourceMatcher(eventIdSource);
647}
648
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700649MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") {
650 return arg.getRepeatCount() == repeatCount;
651}
652
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -0700653class WithPointerIdMatcher {
654public:
655 using is_gtest_matcher = void;
656 explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
657 : mIndex(index), mPointerId(pointerId) {}
658
Harry Cuttsccd9d512024-09-17 16:33:27 +0000659 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream* os) const {
660 if (mIndex >= args.pointerCoords.size()) {
661 *os << "Pointer index " << mIndex << " is out of bounds";
662 return false;
663 }
664
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -0700665 return args.pointerProperties[mIndex].id == mPointerId;
666 }
667
668 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
669 return event.getPointerId(mIndex) == mPointerId;
670 }
671
672 void DescribeTo(std::ostream* os) const {
673 *os << "with pointer[" << mIndex << "] id = " << mPointerId;
674 }
675
676 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; }
677
678private:
679 const size_t mIndex;
680 const int32_t mPointerId;
681};
682
683inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) {
684 return WithPointerIdMatcher(index, pointerId);
Harry Cuttsbb24e272023-03-21 10:49:47 +0000685}
686
Siarhei Vishniakou5197ce62023-09-19 08:27:05 -0700687MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") {
688 const auto argX = arg.xCursorPosition;
689 const auto argY = arg.yCursorPosition;
690 *result_listener << "expected cursor position (" << x << ", " << y << "), but got (" << argX
691 << ", " << argY << ")";
692 return (isnan(x) ? isnan(argX) : x == argX) && (isnan(y) ? isnan(argY) : y == argY);
693}
694
Harry Cutts75155342024-08-23 11:11:13 +0000695/// Relative motion matcher
696class WithRelativeMotionMatcher {
697public:
698 using is_gtest_matcher = void;
699 explicit WithRelativeMotionMatcher(size_t pointerIndex, float relX, float relY)
700 : mPointerIndex(pointerIndex), mRelX(relX), mRelY(relY) {}
701
702 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
703 if (mPointerIndex >= event.pointerCoords.size()) {
704 *os << "Pointer index " << mPointerIndex << " is out of bounds";
705 return false;
706 }
707
708 const PointerCoords& coords = event.pointerCoords[mPointerIndex];
709 bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) &&
710 mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
711 if (!matches) {
712 *os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
713 << mPointerIndex << ", but got ("
714 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) << ", "
715 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y) << ")";
716 }
717 return matches;
718 }
719
720 void DescribeTo(std::ostream* os) const {
721 *os << "with relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
722 << mPointerIndex;
723 }
724
725 void DescribeNegationTo(std::ostream* os) const { *os << "wrong relative motion"; }
726
727private:
728 const size_t mPointerIndex;
729 const float mRelX;
730 const float mRelY;
731};
732
733inline WithRelativeMotionMatcher WithRelativeMotion(float relX, float relY) {
734 return WithRelativeMotionMatcher(0, relX, relY);
735}
736
737inline WithRelativeMotionMatcher WithPointerRelativeMotion(size_t pointerIndex, float relX,
738 float relY) {
739 return WithRelativeMotionMatcher(pointerIndex, relX, relY);
Harry Cutts4fb941a2022-12-14 19:14:04 +0000740}
741
Harry Cuttsc5748d12022-12-02 17:30:18 +0000742MATCHER_P3(WithGestureOffset, dx, dy, epsilon,
743 "InputEvent with specified touchpad gesture offset") {
744 const auto argGestureX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET);
745 const auto argGestureY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET);
746 const double xDiff = fabs(argGestureX - dx);
747 const double yDiff = fabs(argGestureY - dy);
748 *result_listener << "expected gesture offset (" << dx << ", " << dy << ") within " << epsilon
749 << ", but got (" << argGestureX << ", " << argGestureY << ")";
750 return xDiff <= epsilon && yDiff <= epsilon;
751}
752
Harry Cuttsef400b22022-12-16 21:26:24 +0000753MATCHER_P3(WithGestureScrollDistance, x, y, epsilon,
754 "InputEvent with specified touchpad gesture scroll distance") {
755 const auto argXDistance =
756 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE);
757 const auto argYDistance =
758 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE);
759 const double xDiff = fabs(argXDistance - x);
760 const double yDiff = fabs(argYDistance - y);
761 *result_listener << "expected gesture offset (" << x << ", " << y << ") within " << epsilon
762 << ", but got (" << argXDistance << ", " << argYDistance << ")";
763 return xDiff <= epsilon && yDiff <= epsilon;
764}
765
Harry Cuttsb1e83552022-12-20 11:02:26 +0000766MATCHER_P2(WithGesturePinchScaleFactor, factor, epsilon,
767 "InputEvent with specified touchpad pinch gesture scale factor") {
768 const auto argScaleFactor =
769 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR);
770 *result_listener << "expected gesture scale factor " << factor << " within " << epsilon
771 << " but got " << argScaleFactor;
772 return fabs(argScaleFactor - factor) <= epsilon;
773}
774
Harry Cutts8743f182023-05-17 12:03:49 +0000775MATCHER_P(WithGestureSwipeFingerCount, count,
776 "InputEvent with specified touchpad swipe finger count") {
777 const auto argFingerCount =
778 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SWIPE_FINGER_COUNT);
779 *result_listener << "expected gesture swipe finger count " << count << " but got "
780 << argFingerCount;
781 return fabs(argFingerCount - count) <= EPSILON;
782}
783
Prabir Pradhanafabcde2022-09-27 19:32:43 +0000784MATCHER_P(WithPressure, pressure, "InputEvent with specified pressure") {
785 const auto argPressure = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +0000786 *result_listener << "expected pressure " << pressure << ", but got " << argPressure;
787 return argPressure == pressure;
Prabir Pradhanafabcde2022-09-27 19:32:43 +0000788}
789
Harry Cutts7ecbb992023-12-18 14:45:09 +0000790MATCHER_P(WithSize, size, "MotionEvent with specified size") {
791 const auto argSize = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE);
792 *result_listener << "expected size " << size << ", but got " << argSize;
793 return argSize == size;
794}
795
796MATCHER_P(WithOrientation, orientation, "MotionEvent with specified orientation") {
797 const auto argOrientation = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
798 *result_listener << "expected orientation " << orientation << ", but got " << argOrientation;
799 return argOrientation == orientation;
800}
801
802MATCHER_P(WithDistance, distance, "MotionEvent with specified distance") {
803 const auto argDistance = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_DISTANCE);
804 *result_listener << "expected distance " << distance << ", but got " << argDistance;
805 return argDistance == distance;
806}
807
Biswarup Palba27d1d2024-07-09 19:57:33 +0000808MATCHER_P(WithScroll, scroll, "InputEvent with specified scroll value") {
809 const auto argScroll = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SCROLL);
810 *result_listener << "expected scroll value " << scroll << ", but got " << argScroll;
811 return argScroll == scroll;
812}
813
Biswarup Pal8ff5e5e2024-06-15 12:58:20 +0000814MATCHER_P2(WithScroll, scrollX, scrollY, "InputEvent with specified scroll values") {
815 const auto argScrollX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_HSCROLL);
816 const auto argScrollY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_VSCROLL);
817 *result_listener << "expected scroll values " << scrollX << " scroll x " << scrollY
818 << " scroll y, but got " << argScrollX << " scroll x " << argScrollY
819 << " scroll y";
820 return argScrollX == scrollX && argScrollY == scrollY;
821}
822
Harry Cuttsbb24e272023-03-21 10:49:47 +0000823MATCHER_P2(WithTouchDimensions, maj, min, "InputEvent with specified touch dimensions") {
824 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
825 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
826 *result_listener << "expected touch dimensions " << maj << " major x " << min
827 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
828 return argMajor == maj && argMinor == min;
829}
830
831MATCHER_P2(WithToolDimensions, maj, min, "InputEvent with specified tool dimensions") {
832 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR);
833 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR);
834 *result_listener << "expected tool dimensions " << maj << " major x " << min
835 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
836 return argMajor == maj && argMinor == min;
837}
838
Prabir Pradhanda20b172022-09-26 17:01:18 +0000839MATCHER_P(WithToolType, toolType, "InputEvent with specified tool type") {
840 const auto argToolType = arg.pointerProperties[0].toolType;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700841 *result_listener << "expected tool type " << ftl::enum_string(toolType) << ", but got "
842 << ftl::enum_string(argToolType);
Prabir Pradhanda20b172022-09-26 17:01:18 +0000843 return argToolType == toolType;
844}
845
Harry Cuttsccd9d512024-09-17 16:33:27 +0000846MATCHER_P2(WithPointerToolType, pointerIndex, toolType,
Harry Cuttsbb24e272023-03-21 10:49:47 +0000847 "InputEvent with specified tool type for pointer") {
Harry Cuttsccd9d512024-09-17 16:33:27 +0000848 if (std::cmp_greater_equal(pointerIndex, arg.getPointerCount())) {
849 *result_listener << "Pointer index " << pointerIndex << " is out of bounds";
850 return false;
851 }
852 const auto argToolType = arg.pointerProperties[pointerIndex].toolType;
853 *result_listener << "expected pointer " << pointerIndex << " to have tool type "
Harry Cuttsbb24e272023-03-21 10:49:47 +0000854 << ftl::enum_string(toolType) << ", but got " << ftl::enum_string(argToolType);
855 return argToolType == toolType;
856}
857
Harry Cuttsc5748d12022-12-02 17:30:18 +0000858MATCHER_P(WithMotionClassification, classification,
859 "InputEvent with specified MotionClassification") {
860 *result_listener << "expected classification " << motionClassificationToString(classification)
861 << ", but got " << motionClassificationToString(arg.classification);
862 return arg.classification == classification;
863}
864
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +0000865MATCHER_P(WithButtonState, buttons, "InputEvent with specified button state") {
866 *result_listener << "expected button state " << buttons << ", but got " << arg.buttonState;
867 return arg.buttonState == buttons;
868}
869
Harry Cutts7ecbb992023-12-18 14:45:09 +0000870MATCHER_P(WithMetaState, metaState, "InputEvent with specified meta state") {
871 *result_listener << "expected meta state 0x" << std::hex << metaState << ", but got 0x"
872 << arg.metaState;
873 return arg.metaState == metaState;
874}
875
Harry Cutts4fb941a2022-12-14 19:14:04 +0000876MATCHER_P(WithActionButton, actionButton, "InputEvent with specified action button") {
877 *result_listener << "expected action button " << actionButton << ", but got "
878 << arg.actionButton;
879 return arg.actionButton == actionButton;
880}
881
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000882MATCHER_P(WithEventTime, eventTime, "InputEvent with specified eventTime") {
883 *result_listener << "expected event time " << eventTime << ", but got " << arg.eventTime;
884 return arg.eventTime == eventTime;
885}
886
Harry Cuttsef400b22022-12-16 21:26:24 +0000887MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
888 *result_listener << "expected down time " << downTime << ", but got " << arg.downTime;
889 return arg.downTime == downTime;
890}
891
Prabir Pradhana9df3162022-12-05 23:57:27 +0000892MATCHER_P2(WithPrecision, xPrecision, yPrecision, "MotionEvent with specified precision") {
893 *result_listener << "expected x-precision " << xPrecision << " and y-precision " << yPrecision
894 << ", but got " << arg.xPrecision << " and " << arg.yPrecision;
895 return arg.xPrecision == xPrecision && arg.yPrecision == yPrecision;
896}
897
Harry Cutts7ecbb992023-12-18 14:45:09 +0000898MATCHER_P(WithPolicyFlags, policyFlags, "InputEvent with specified policy flags") {
899 *result_listener << "expected policy flags 0x" << std::hex << policyFlags << ", but got 0x"
900 << arg.policyFlags;
901 return arg.policyFlags == static_cast<uint32_t>(policyFlags);
902}
903
904MATCHER_P(WithEdgeFlags, edgeFlags, "InputEvent with specified edge flags") {
905 *result_listener << "expected edge flags 0x" << std::hex << edgeFlags << ", but got 0x"
906 << arg.edgeFlags;
907 return arg.edgeFlags == edgeFlags;
908}
909
Prabir Pradhan739dca42022-09-09 20:12:01 +0000910} // namespace android