blob: 513bd727971260168e8751c3e6ce085471326beb [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
111 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
112 bool matches = mAction == args.action;
113 if (args.action == AMOTION_EVENT_ACTION_CANCEL) {
114 matches &= (args.flags & AMOTION_EVENT_FLAG_CANCELED) != 0;
115 }
116 return matches;
117 }
118
119 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
120 bool matches = mAction == event.getAction();
121 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL) {
122 matches &= (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
123 }
124 return matches;
125 }
126
127 void DescribeTo(std::ostream* os) const {
128 *os << "with motion action " << MotionEvent::actionToString(mAction);
129 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
130 *os << " and FLAG_CANCELED";
131 }
132 }
133
134 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
135
136private:
137 const int32_t mAction;
138};
139
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000140inline WithMotionActionMatcher WithMotionAction(int32_t action) {
141 return WithMotionActionMatcher(action);
142}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700143
144/// Display Id
145class WithDisplayIdMatcher {
146public:
147 using is_gtest_matcher = void;
Linnan Li13bf76a2024-05-05 19:18:02 +0800148 explicit WithDisplayIdMatcher(ui::LogicalDisplayId displayId) : mDisplayId(displayId) {}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700149
150 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
151 return mDisplayId == args.displayId;
152 }
153
154 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
155 return mDisplayId == args.displayId;
156 }
157
158 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
159 return mDisplayId == event.getDisplayId();
160 }
161
162 void DescribeTo(std::ostream* os) const { *os << "with display id " << mDisplayId; }
163
164 void DescribeNegationTo(std::ostream* os) const { *os << "wrong display id"; }
165
166private:
Linnan Li13bf76a2024-05-05 19:18:02 +0800167 const ui::LogicalDisplayId mDisplayId;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700168};
169
Linnan Li13bf76a2024-05-05 19:18:02 +0800170inline WithDisplayIdMatcher WithDisplayId(ui::LogicalDisplayId displayId) {
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000171 return WithDisplayIdMatcher(displayId);
172}
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700173
174/// Device Id
175class WithDeviceIdMatcher {
176public:
177 using is_gtest_matcher = void;
178 explicit WithDeviceIdMatcher(int32_t deviceId) : mDeviceId(deviceId) {}
179
180 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
181 return mDeviceId == args.deviceId;
182 }
183
184 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
185 return mDeviceId == args.deviceId;
186 }
187
Prabir Pradhan85cf63e2023-08-07 21:02:13 +0000188 bool MatchAndExplain(const NotifyDeviceResetArgs& args, std::ostream*) const {
189 return mDeviceId == args.deviceId;
190 }
191
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700192 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
193 return mDeviceId == event.getDeviceId();
194 }
195
196 void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
197
198 void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
199
200private:
201 const int32_t mDeviceId;
202};
203
Prabir Pradhan7b6502d2023-10-06 04:08:39 +0000204inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
205 return WithDeviceIdMatcher(deviceId);
206}
207
208/// Flags
209class WithFlagsMatcher {
210public:
211 using is_gtest_matcher = void;
212 explicit WithFlagsMatcher(int32_t flags) : mFlags(flags) {}
213
214 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
215 return mFlags == args.flags;
216 }
217
218 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
219 return mFlags == args.flags;
220 }
221
222 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
223 return mFlags == event.getFlags();
224 }
225
226 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
227 return mFlags == event.getFlags();
228 }
229
230 void DescribeTo(std::ostream* os) const {
231 *os << "with flags " << base::StringPrintf("0x%x", mFlags);
232 }
233
234 void DescribeNegationTo(std::ostream* os) const { *os << "wrong flags"; }
235
236private:
237 const int32_t mFlags;
238};
239
240inline WithFlagsMatcher WithFlags(int32_t flags) {
241 return WithFlagsMatcher(flags);
242}
243
244/// DownTime
245class WithDownTimeMatcher {
246public:
247 using is_gtest_matcher = void;
248 explicit WithDownTimeMatcher(nsecs_t downTime) : mDownTime(downTime) {}
249
250 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
251 return mDownTime == args.downTime;
252 }
253
254 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
255 return mDownTime == args.downTime;
256 }
257
258 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
259 return mDownTime == event.getDownTime();
260 }
261
262 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
263 return mDownTime == event.getDownTime();
264 }
265
266 void DescribeTo(std::ostream* os) const { *os << "with down time " << mDownTime; }
267
268 void DescribeNegationTo(std::ostream* os) const { *os << "wrong down time"; }
269
270private:
271 const nsecs_t mDownTime;
272};
273
274inline WithDownTimeMatcher WithDownTime(nsecs_t downTime) {
275 return WithDownTimeMatcher(downTime);
276}
277
278/// Coordinate matcher
279class WithCoordsMatcher {
280public:
281 using is_gtest_matcher = void;
282 explicit WithCoordsMatcher(size_t pointerIndex, float x, float y)
283 : mPointerIndex(pointerIndex), mX(x), mY(y) {}
284
285 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
286 if (mPointerIndex >= event.getPointerCount()) {
287 *os << "Pointer index " << mPointerIndex << " is out of bounds";
288 return false;
289 }
290
291 bool matches = mX == event.getX(mPointerIndex) && mY == event.getY(mPointerIndex);
292 if (!matches) {
293 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
294 << ", but got (" << event.getX(mPointerIndex) << ", " << event.getY(mPointerIndex)
295 << ")";
296 }
297 return matches;
298 }
299
300 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
301 if (mPointerIndex >= event.pointerCoords.size()) {
302 *os << "Pointer index " << mPointerIndex << " is out of bounds";
303 return false;
304 }
305
306 bool matches = mX == event.pointerCoords[mPointerIndex].getX() &&
307 mY == event.pointerCoords[mPointerIndex].getY();
308 if (!matches) {
309 *os << "expected coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex
310 << ", but got (" << event.pointerCoords[mPointerIndex].getX() << ", "
311 << event.pointerCoords[mPointerIndex].getY() << ")";
312 }
313 return matches;
314 }
315
316 void DescribeTo(std::ostream* os) const {
317 *os << "with coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex;
318 }
319
320 void DescribeNegationTo(std::ostream* os) const { *os << "wrong coords"; }
321
322private:
323 const size_t mPointerIndex;
324 const float mX;
325 const float mY;
326};
327
328inline WithCoordsMatcher WithCoords(float x, float y) {
329 return WithCoordsMatcher(0, x, y);
330}
331
332inline WithCoordsMatcher WithPointerCoords(size_t pointerIndex, float x, float y) {
333 return WithCoordsMatcher(pointerIndex, x, y);
334}
335
336/// Raw coordinate matcher
337class WithRawCoordsMatcher {
338public:
339 using is_gtest_matcher = void;
340 explicit WithRawCoordsMatcher(size_t pointerIndex, float rawX, float rawY)
341 : mPointerIndex(pointerIndex), mRawX(rawX), mRawY(rawY) {}
342
343 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
344 if (mPointerIndex >= event.getPointerCount()) {
345 *os << "Pointer index " << mPointerIndex << " is out of bounds";
346 return false;
347 }
348
349 bool matches =
350 mRawX == event.getRawX(mPointerIndex) && mRawY == event.getRawY(mPointerIndex);
351 if (!matches) {
352 *os << "expected raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
353 << mPointerIndex << ", but got (" << event.getRawX(mPointerIndex) << ", "
354 << event.getRawY(mPointerIndex) << ")";
355 }
356 return matches;
357 }
358
359 void DescribeTo(std::ostream* os) const {
360 *os << "with raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
361 << mPointerIndex;
362 }
363
364 void DescribeNegationTo(std::ostream* os) const { *os << "wrong raw coords"; }
365
366private:
367 const size_t mPointerIndex;
368 const float mRawX;
369 const float mRawY;
370};
371
372inline WithRawCoordsMatcher WithRawCoords(float rawX, float rawY) {
373 return WithRawCoordsMatcher(0, rawX, rawY);
374}
375
376inline WithRawCoordsMatcher WithPointerRawCoords(size_t pointerIndex, float rawX, float rawY) {
377 return WithRawCoordsMatcher(pointerIndex, rawX, rawY);
378}
379
380/// Pointer count
381class WithPointerCountMatcher {
382public:
383 using is_gtest_matcher = void;
384 explicit WithPointerCountMatcher(size_t pointerCount) : mPointerCount(pointerCount) {}
385
386 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
387 if (event.getPointerCount() != mPointerCount) {
388 *os << "expected pointer count " << mPointerCount << ", but got "
389 << event.getPointerCount();
390 return false;
391 }
392 return true;
393 }
394
395 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
396 if (event.pointerCoords.size() != mPointerCount) {
397 *os << "expected pointer count " << mPointerCount << ", but got "
398 << event.pointerCoords.size();
399 return false;
400 }
401 return true;
402 }
403
404 void DescribeTo(std::ostream* os) const { *os << "with pointer count " << mPointerCount; }
405
406 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer count"; }
407
408private:
409 const size_t mPointerCount;
410};
411
412inline WithPointerCountMatcher WithPointerCount(size_t pointerCount) {
413 return WithPointerCountMatcher(pointerCount);
414}
415
416/// Pointers matcher
417class WithPointersMatcher {
418public:
419 using is_gtest_matcher = void;
420 explicit WithPointersMatcher(std::map<int32_t, PointF> pointers) : mPointers(pointers) {}
421
422 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
423 std::map<int32_t, PointF> actualPointers;
424 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
425 const int32_t pointerId = event.getPointerId(pointerIndex);
426 actualPointers[pointerId] = {event.getX(pointerIndex), event.getY(pointerIndex)};
427 }
428
429 if (mPointers != actualPointers) {
430 *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
431 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
432 return false;
433 }
434 return true;
435 }
436
437 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
438 std::map<int32_t, PointF> actualPointers;
439 for (size_t pointerIndex = 0; pointerIndex < event.pointerCoords.size(); pointerIndex++) {
440 const int32_t pointerId = event.pointerProperties[pointerIndex].id;
441 actualPointers[pointerId] = {event.pointerCoords[pointerIndex].getX(),
442 event.pointerCoords[pointerIndex].getY()};
443 }
444
445 if (mPointers != actualPointers) {
446 *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
447 << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
448 return false;
449 }
450 return true;
451 }
452
453 void DescribeTo(std::ostream* os) const {
454 *os << "with pointers " << dumpMap(mPointers, constToString, pointFToString);
455 }
456
457 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointers"; }
458
459private:
460 const std::map<int32_t, PointF> mPointers;
461};
462
463inline WithPointersMatcher WithPointers(
464 const std::map<int32_t /*id*/, PointF /*coords*/>& pointers) {
465 return WithPointersMatcher(pointers);
466}
Prabir Pradhan484d55a2022-10-14 23:17:16 +0000467
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -0800468/// Pointer ids matcher
469class WithPointerIdsMatcher {
470public:
471 using is_gtest_matcher = void;
472 explicit WithPointerIdsMatcher(std::set<int32_t> pointerIds) : mPointerIds(pointerIds) {}
473
474 bool MatchAndExplain(const MotionEvent& event, std::ostream* os) const {
475 std::set<int32_t> actualPointerIds;
476 for (size_t pointerIndex = 0; pointerIndex < event.getPointerCount(); pointerIndex++) {
477 const PointerProperties* properties = event.getPointerProperties(pointerIndex);
478 actualPointerIds.insert(properties->id);
479 }
480
481 if (mPointerIds != actualPointerIds) {
482 *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
483 << dumpSet(actualPointerIds);
484 return false;
485 }
486 return true;
487 }
488
489 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
490 std::set<int32_t> actualPointerIds;
491 for (const PointerProperties& properties : event.pointerProperties) {
492 actualPointerIds.insert(properties.id);
493 }
494
495 if (mPointerIds != actualPointerIds) {
496 *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
497 << dumpSet(actualPointerIds);
498 return false;
499 }
500 return true;
501 }
502
503 void DescribeTo(std::ostream* os) const { *os << "with pointer ids " << dumpSet(mPointerIds); }
504
505 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer ids"; }
506
507private:
508 const std::set<int32_t> mPointerIds;
509};
510
511inline WithPointerIdsMatcher WithPointerIds(const std::set<int32_t /*id*/>& pointerIds) {
512 return WithPointerIdsMatcher(pointerIds);
513}
514
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000515/// Key code
516class WithKeyCodeMatcher {
517public:
518 using is_gtest_matcher = void;
519 explicit WithKeyCodeMatcher(int32_t keyCode) : mKeyCode(keyCode) {}
520
521 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
522 return mKeyCode == args.keyCode;
523 }
524
525 bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
526 return mKeyCode == event.getKeyCode();
527 }
528
529 void DescribeTo(std::ostream* os) const {
530 *os << "with key code " << KeyEvent::getLabel(mKeyCode);
531 }
532
533 void DescribeNegationTo(std::ostream* os) const { *os << "wrong key code"; }
534
535private:
536 const int32_t mKeyCode;
537};
538
539inline WithKeyCodeMatcher WithKeyCode(int32_t keyCode) {
540 return WithKeyCodeMatcher(keyCode);
Prabir Pradhane1a41a82022-10-14 18:06:50 +0000541}
542
Prabir Pradhan5893d362023-11-17 04:30:40 +0000543/// EventId
544class WithEventIdMatcher {
545public:
546 using is_gtest_matcher = void;
547 explicit WithEventIdMatcher(int32_t eventId) : mEventId(eventId) {}
548
549 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
550 return mEventId == args.id;
551 }
552
553 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
554 return mEventId == args.id;
555 }
556
557 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
558 return mEventId == event.getId();
559 }
560
561 void DescribeTo(std::ostream* os) const { *os << "with eventId 0x" << std::hex << mEventId; }
562
563 void DescribeNegationTo(std::ostream* os) const {
564 *os << "with eventId not equal to 0x" << std::hex << mEventId;
565 }
566
567private:
568 const int32_t mEventId;
569};
570
571inline WithEventIdMatcher WithEventId(int32_t eventId) {
572 return WithEventIdMatcher(eventId);
573}
574
575/// EventIdSource
576class WithEventIdSourceMatcher {
577public:
578 using is_gtest_matcher = void;
579 explicit WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)
580 : mEventIdSource(eventIdSource) {}
581
582 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
583 return mEventIdSource == IdGenerator::getSource(args.id);
584 }
585
586 bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
587 return mEventIdSource == IdGenerator::getSource(args.id);
588 }
589
590 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
591 return mEventIdSource == IdGenerator::getSource(event.getId());
592 }
593
594 void DescribeTo(std::ostream* os) const {
595 *os << "with eventId from source 0x" << std::hex << ftl::to_underlying(mEventIdSource);
596 }
597
598 void DescribeNegationTo(std::ostream* os) const { *os << "wrong event from source"; }
599
600private:
601 const IdGenerator::Source mEventIdSource;
602};
603
604inline WithEventIdSourceMatcher WithEventIdSource(IdGenerator::Source eventIdSource) {
605 return WithEventIdSourceMatcher(eventIdSource);
606}
607
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700608MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") {
609 return arg.getRepeatCount() == repeatCount;
610}
611
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -0700612class WithPointerIdMatcher {
613public:
614 using is_gtest_matcher = void;
615 explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
616 : mIndex(index), mPointerId(pointerId) {}
617
618 bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
619 return args.pointerProperties[mIndex].id == mPointerId;
620 }
621
622 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
623 return event.getPointerId(mIndex) == mPointerId;
624 }
625
626 void DescribeTo(std::ostream* os) const {
627 *os << "with pointer[" << mIndex << "] id = " << mPointerId;
628 }
629
630 void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; }
631
632private:
633 const size_t mIndex;
634 const int32_t mPointerId;
635};
636
637inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) {
638 return WithPointerIdMatcher(index, pointerId);
Harry Cuttsbb24e272023-03-21 10:49:47 +0000639}
640
Siarhei Vishniakou5197ce62023-09-19 08:27:05 -0700641MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") {
642 const auto argX = arg.xCursorPosition;
643 const auto argY = arg.yCursorPosition;
644 *result_listener << "expected cursor position (" << x << ", " << y << "), but got (" << argX
645 << ", " << argY << ")";
646 return (isnan(x) ? isnan(argX) : x == argX) && (isnan(y) ? isnan(argY) : y == argY);
647}
648
Harry Cutts75155342024-08-23 11:11:13 +0000649/// Relative motion matcher
650class WithRelativeMotionMatcher {
651public:
652 using is_gtest_matcher = void;
653 explicit WithRelativeMotionMatcher(size_t pointerIndex, float relX, float relY)
654 : mPointerIndex(pointerIndex), mRelX(relX), mRelY(relY) {}
655
656 bool MatchAndExplain(const NotifyMotionArgs& event, std::ostream* os) const {
657 if (mPointerIndex >= event.pointerCoords.size()) {
658 *os << "Pointer index " << mPointerIndex << " is out of bounds";
659 return false;
660 }
661
662 const PointerCoords& coords = event.pointerCoords[mPointerIndex];
663 bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) &&
664 mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
665 if (!matches) {
666 *os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
667 << mPointerIndex << ", but got ("
668 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) << ", "
669 << coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y) << ")";
670 }
671 return matches;
672 }
673
674 void DescribeTo(std::ostream* os) const {
675 *os << "with relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
676 << mPointerIndex;
677 }
678
679 void DescribeNegationTo(std::ostream* os) const { *os << "wrong relative motion"; }
680
681private:
682 const size_t mPointerIndex;
683 const float mRelX;
684 const float mRelY;
685};
686
687inline WithRelativeMotionMatcher WithRelativeMotion(float relX, float relY) {
688 return WithRelativeMotionMatcher(0, relX, relY);
689}
690
691inline WithRelativeMotionMatcher WithPointerRelativeMotion(size_t pointerIndex, float relX,
692 float relY) {
693 return WithRelativeMotionMatcher(pointerIndex, relX, relY);
Harry Cutts4fb941a2022-12-14 19:14:04 +0000694}
695
Harry Cuttsc5748d12022-12-02 17:30:18 +0000696MATCHER_P3(WithGestureOffset, dx, dy, epsilon,
697 "InputEvent with specified touchpad gesture offset") {
698 const auto argGestureX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_X_OFFSET);
699 const auto argGestureY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_Y_OFFSET);
700 const double xDiff = fabs(argGestureX - dx);
701 const double yDiff = fabs(argGestureY - dy);
702 *result_listener << "expected gesture offset (" << dx << ", " << dy << ") within " << epsilon
703 << ", but got (" << argGestureX << ", " << argGestureY << ")";
704 return xDiff <= epsilon && yDiff <= epsilon;
705}
706
Harry Cuttsef400b22022-12-16 21:26:24 +0000707MATCHER_P3(WithGestureScrollDistance, x, y, epsilon,
708 "InputEvent with specified touchpad gesture scroll distance") {
709 const auto argXDistance =
710 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_X_DISTANCE);
711 const auto argYDistance =
712 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SCROLL_Y_DISTANCE);
713 const double xDiff = fabs(argXDistance - x);
714 const double yDiff = fabs(argYDistance - y);
715 *result_listener << "expected gesture offset (" << x << ", " << y << ") within " << epsilon
716 << ", but got (" << argXDistance << ", " << argYDistance << ")";
717 return xDiff <= epsilon && yDiff <= epsilon;
718}
719
Harry Cuttsb1e83552022-12-20 11:02:26 +0000720MATCHER_P2(WithGesturePinchScaleFactor, factor, epsilon,
721 "InputEvent with specified touchpad pinch gesture scale factor") {
722 const auto argScaleFactor =
723 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_PINCH_SCALE_FACTOR);
724 *result_listener << "expected gesture scale factor " << factor << " within " << epsilon
725 << " but got " << argScaleFactor;
726 return fabs(argScaleFactor - factor) <= epsilon;
727}
728
Harry Cutts8743f182023-05-17 12:03:49 +0000729MATCHER_P(WithGestureSwipeFingerCount, count,
730 "InputEvent with specified touchpad swipe finger count") {
731 const auto argFingerCount =
732 arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_GESTURE_SWIPE_FINGER_COUNT);
733 *result_listener << "expected gesture swipe finger count " << count << " but got "
734 << argFingerCount;
735 return fabs(argFingerCount - count) <= EPSILON;
736}
737
Prabir Pradhanafabcde2022-09-27 19:32:43 +0000738MATCHER_P(WithPressure, pressure, "InputEvent with specified pressure") {
739 const auto argPressure = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
Prabir Pradhan7d04c4b2022-10-28 19:23:26 +0000740 *result_listener << "expected pressure " << pressure << ", but got " << argPressure;
741 return argPressure == pressure;
Prabir Pradhanafabcde2022-09-27 19:32:43 +0000742}
743
Harry Cutts7ecbb992023-12-18 14:45:09 +0000744MATCHER_P(WithSize, size, "MotionEvent with specified size") {
745 const auto argSize = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE);
746 *result_listener << "expected size " << size << ", but got " << argSize;
747 return argSize == size;
748}
749
750MATCHER_P(WithOrientation, orientation, "MotionEvent with specified orientation") {
751 const auto argOrientation = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
752 *result_listener << "expected orientation " << orientation << ", but got " << argOrientation;
753 return argOrientation == orientation;
754}
755
756MATCHER_P(WithDistance, distance, "MotionEvent with specified distance") {
757 const auto argDistance = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_DISTANCE);
758 *result_listener << "expected distance " << distance << ", but got " << argDistance;
759 return argDistance == distance;
760}
761
Biswarup Palba27d1d2024-07-09 19:57:33 +0000762MATCHER_P(WithScroll, scroll, "InputEvent with specified scroll value") {
763 const auto argScroll = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SCROLL);
764 *result_listener << "expected scroll value " << scroll << ", but got " << argScroll;
765 return argScroll == scroll;
766}
767
Biswarup Pal8ff5e5e2024-06-15 12:58:20 +0000768MATCHER_P2(WithScroll, scrollX, scrollY, "InputEvent with specified scroll values") {
769 const auto argScrollX = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_HSCROLL);
770 const auto argScrollY = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_VSCROLL);
771 *result_listener << "expected scroll values " << scrollX << " scroll x " << scrollY
772 << " scroll y, but got " << argScrollX << " scroll x " << argScrollY
773 << " scroll y";
774 return argScrollX == scrollX && argScrollY == scrollY;
775}
776
Harry Cuttsbb24e272023-03-21 10:49:47 +0000777MATCHER_P2(WithTouchDimensions, maj, min, "InputEvent with specified touch dimensions") {
778 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
779 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
780 *result_listener << "expected touch dimensions " << maj << " major x " << min
781 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
782 return argMajor == maj && argMinor == min;
783}
784
785MATCHER_P2(WithToolDimensions, maj, min, "InputEvent with specified tool dimensions") {
786 const auto argMajor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR);
787 const auto argMinor = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR);
788 *result_listener << "expected tool dimensions " << maj << " major x " << min
789 << " minor, but got " << argMajor << " major x " << argMinor << " minor";
790 return argMajor == maj && argMinor == min;
791}
792
Prabir Pradhanda20b172022-09-26 17:01:18 +0000793MATCHER_P(WithToolType, toolType, "InputEvent with specified tool type") {
794 const auto argToolType = arg.pointerProperties[0].toolType;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700795 *result_listener << "expected tool type " << ftl::enum_string(toolType) << ", but got "
796 << ftl::enum_string(argToolType);
Prabir Pradhanda20b172022-09-26 17:01:18 +0000797 return argToolType == toolType;
798}
799
Harry Cuttsbb24e272023-03-21 10:49:47 +0000800MATCHER_P2(WithPointerToolType, pointer, toolType,
801 "InputEvent with specified tool type for pointer") {
802 const auto argToolType = arg.pointerProperties[pointer].toolType;
803 *result_listener << "expected pointer " << pointer << " to have tool type "
804 << ftl::enum_string(toolType) << ", but got " << ftl::enum_string(argToolType);
805 return argToolType == toolType;
806}
807
Harry Cuttsc5748d12022-12-02 17:30:18 +0000808MATCHER_P(WithMotionClassification, classification,
809 "InputEvent with specified MotionClassification") {
810 *result_listener << "expected classification " << motionClassificationToString(classification)
811 << ", but got " << motionClassificationToString(arg.classification);
812 return arg.classification == classification;
813}
814
Prabir Pradhan4f05b5f2022-10-11 21:24:07 +0000815MATCHER_P(WithButtonState, buttons, "InputEvent with specified button state") {
816 *result_listener << "expected button state " << buttons << ", but got " << arg.buttonState;
817 return arg.buttonState == buttons;
818}
819
Harry Cutts7ecbb992023-12-18 14:45:09 +0000820MATCHER_P(WithMetaState, metaState, "InputEvent with specified meta state") {
821 *result_listener << "expected meta state 0x" << std::hex << metaState << ", but got 0x"
822 << arg.metaState;
823 return arg.metaState == metaState;
824}
825
Harry Cutts4fb941a2022-12-14 19:14:04 +0000826MATCHER_P(WithActionButton, actionButton, "InputEvent with specified action button") {
827 *result_listener << "expected action button " << actionButton << ", but got "
828 << arg.actionButton;
829 return arg.actionButton == actionButton;
830}
831
Prabir Pradhan2f37bcb2022-11-08 20:41:28 +0000832MATCHER_P(WithEventTime, eventTime, "InputEvent with specified eventTime") {
833 *result_listener << "expected event time " << eventTime << ", but got " << arg.eventTime;
834 return arg.eventTime == eventTime;
835}
836
Harry Cuttsef400b22022-12-16 21:26:24 +0000837MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
838 *result_listener << "expected down time " << downTime << ", but got " << arg.downTime;
839 return arg.downTime == downTime;
840}
841
Prabir Pradhana9df3162022-12-05 23:57:27 +0000842MATCHER_P2(WithPrecision, xPrecision, yPrecision, "MotionEvent with specified precision") {
843 *result_listener << "expected x-precision " << xPrecision << " and y-precision " << yPrecision
844 << ", but got " << arg.xPrecision << " and " << arg.yPrecision;
845 return arg.xPrecision == xPrecision && arg.yPrecision == yPrecision;
846}
847
Harry Cutts7ecbb992023-12-18 14:45:09 +0000848MATCHER_P(WithPolicyFlags, policyFlags, "InputEvent with specified policy flags") {
849 *result_listener << "expected policy flags 0x" << std::hex << policyFlags << ", but got 0x"
850 << arg.policyFlags;
851 return arg.policyFlags == static_cast<uint32_t>(policyFlags);
852}
853
854MATCHER_P(WithEdgeFlags, edgeFlags, "InputEvent with specified edge flags") {
855 *result_listener << "expected edge flags 0x" << std::hex << edgeFlags << ", but got 0x"
856 << arg.edgeFlags;
857 return arg.edgeFlags == edgeFlags;
858}
859
Prabir Pradhan739dca42022-09-09 20:12:01 +0000860} // namespace android