xref: /aosp_15_r20/frameworks/native/services/inputflinger/tests/TestEventMatchers.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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 
pointFToString(const PointF & p)41 inline std::string pointFToString(const PointF& p) {
42     return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
43 }
44 
45 /// Source
46 class WithSourceMatcher {
47 public:
48     using is_gtest_matcher = void;
WithSourceMatcher(uint32_t source)49     explicit WithSourceMatcher(uint32_t source) : mSource(source) {}
50 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)51     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
52         return mSource == args.source;
53     }
54 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)55     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
56         return mSource == args.source;
57     }
58 
MatchAndExplain(const InputEvent & event,std::ostream *)59     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
60         return mSource == event.getSource();
61     }
62 
DescribeTo(std::ostream * os)63     void DescribeTo(std::ostream* os) const {
64         *os << "with source " << inputEventSourceToString(mSource);
65     }
66 
DescribeNegationTo(std::ostream * os)67     void DescribeNegationTo(std::ostream* os) const { *os << "wrong source"; }
68 
69 private:
70     const uint32_t mSource;
71 };
72 
WithSource(uint32_t source)73 inline WithSourceMatcher WithSource(uint32_t source) {
74     return WithSourceMatcher(source);
75 }
76 
77 /// Key action
78 class WithKeyActionMatcher {
79 public:
80     using is_gtest_matcher = void;
WithKeyActionMatcher(int32_t action)81     explicit WithKeyActionMatcher(int32_t action) : mAction(action) {}
82 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)83     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
84         return mAction == args.action;
85     }
86 
MatchAndExplain(const KeyEvent & event,std::ostream *)87     bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
88         return mAction == event.getAction();
89     }
90 
DescribeTo(std::ostream * os)91     void DescribeTo(std::ostream* os) const {
92         *os << "with key action " << KeyEvent::actionToString(mAction);
93     }
94 
DescribeNegationTo(std::ostream * os)95     void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
96 
97 private:
98     const int32_t mAction;
99 };
100 
WithKeyAction(int32_t action)101 inline WithKeyActionMatcher WithKeyAction(int32_t action) {
102     return WithKeyActionMatcher(action);
103 }
104 
105 /// Motion action
106 class WithMotionActionMatcher {
107 public:
108     using is_gtest_matcher = void;
WithMotionActionMatcher(int32_t action)109     explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
110 
MatchAndExplain(const NotifyMotionArgs & args,testing::MatchResultListener * listener)111     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;
117         }
118         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;
124     }
125 
MatchAndExplain(const MotionEvent & event,testing::MatchResultListener * listener)126     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;
131         }
132         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;
138     }
139 
DescribeTo(std::ostream * os)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 
DescribeNegationTo(std::ostream * os)147     void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
148 
149 private:
150     const int32_t mAction;
151 };
152 
WithMotionAction(int32_t action)153 inline WithMotionActionMatcher WithMotionAction(int32_t action) {
154     return WithMotionActionMatcher(action);
155 }
156 
157 /// Display Id
158 class WithDisplayIdMatcher {
159 public:
160     using is_gtest_matcher = void;
WithDisplayIdMatcher(ui::LogicalDisplayId displayId)161     explicit WithDisplayIdMatcher(ui::LogicalDisplayId displayId) : mDisplayId(displayId) {}
162 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)163     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
164         return mDisplayId == args.displayId;
165     }
166 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)167     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
168         return mDisplayId == args.displayId;
169     }
170 
MatchAndExplain(const InputEvent & event,std::ostream *)171     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
172         return mDisplayId == event.getDisplayId();
173     }
174 
DescribeTo(std::ostream * os)175     void DescribeTo(std::ostream* os) const { *os << "with display id " << mDisplayId; }
176 
DescribeNegationTo(std::ostream * os)177     void DescribeNegationTo(std::ostream* os) const { *os << "wrong display id"; }
178 
179 private:
180     const ui::LogicalDisplayId mDisplayId;
181 };
182 
WithDisplayId(ui::LogicalDisplayId displayId)183 inline WithDisplayIdMatcher WithDisplayId(ui::LogicalDisplayId displayId) {
184     return WithDisplayIdMatcher(displayId);
185 }
186 
187 /// Device Id
188 class WithDeviceIdMatcher {
189 public:
190     using is_gtest_matcher = void;
WithDeviceIdMatcher(int32_t deviceId)191     explicit WithDeviceIdMatcher(int32_t deviceId) : mDeviceId(deviceId) {}
192 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)193     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
194         return mDeviceId == args.deviceId;
195     }
196 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)197     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
198         return mDeviceId == args.deviceId;
199     }
200 
MatchAndExplain(const NotifyDeviceResetArgs & args,std::ostream *)201     bool MatchAndExplain(const NotifyDeviceResetArgs& args, std::ostream*) const {
202         return mDeviceId == args.deviceId;
203     }
204 
MatchAndExplain(const InputEvent & event,std::ostream *)205     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
206         return mDeviceId == event.getDeviceId();
207     }
208 
DescribeTo(std::ostream * os)209     void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
210 
DescribeNegationTo(std::ostream * os)211     void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
212 
213 private:
214     const int32_t mDeviceId;
215 };
216 
WithDeviceId(int32_t deviceId)217 inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
218     return WithDeviceIdMatcher(deviceId);
219 }
220 
221 /// Flags
222 class WithFlagsMatcher {
223 public:
224     using is_gtest_matcher = void;
WithFlagsMatcher(int32_t flags)225     explicit WithFlagsMatcher(int32_t flags) : mFlags(flags) {}
226 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)227     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
228         return mFlags == args.flags;
229     }
230 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)231     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
232         return mFlags == args.flags;
233     }
234 
MatchAndExplain(const MotionEvent & event,std::ostream *)235     bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
236         return mFlags == event.getFlags();
237     }
238 
MatchAndExplain(const KeyEvent & event,std::ostream *)239     bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
240         return mFlags == event.getFlags();
241     }
242 
DescribeTo(std::ostream * os)243     void DescribeTo(std::ostream* os) const {
244         *os << "with flags " << base::StringPrintf("0x%x", mFlags);
245     }
246 
DescribeNegationTo(std::ostream * os)247     void DescribeNegationTo(std::ostream* os) const { *os << "wrong flags"; }
248 
249 private:
250     const int32_t mFlags;
251 };
252 
WithFlags(int32_t flags)253 inline WithFlagsMatcher WithFlags(int32_t flags) {
254     return WithFlagsMatcher(flags);
255 }
256 
257 /// DownTime
258 class WithDownTimeMatcher {
259 public:
260     using is_gtest_matcher = void;
WithDownTimeMatcher(nsecs_t downTime)261     explicit WithDownTimeMatcher(nsecs_t downTime) : mDownTime(downTime) {}
262 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)263     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
264         return mDownTime == args.downTime;
265     }
266 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)267     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
268         return mDownTime == args.downTime;
269     }
270 
MatchAndExplain(const MotionEvent & event,std::ostream *)271     bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
272         return mDownTime == event.getDownTime();
273     }
274 
MatchAndExplain(const KeyEvent & event,std::ostream *)275     bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
276         return mDownTime == event.getDownTime();
277     }
278 
DescribeTo(std::ostream * os)279     void DescribeTo(std::ostream* os) const { *os << "with down time " << mDownTime; }
280 
DescribeNegationTo(std::ostream * os)281     void DescribeNegationTo(std::ostream* os) const { *os << "wrong down time"; }
282 
283 private:
284     const nsecs_t mDownTime;
285 };
286 
WithDownTime(nsecs_t downTime)287 inline WithDownTimeMatcher WithDownTime(nsecs_t downTime) {
288     return WithDownTimeMatcher(downTime);
289 }
290 
291 /// Coordinate matcher
292 class WithCoordsMatcher {
293 public:
294     using is_gtest_matcher = void;
WithCoordsMatcher(size_t pointerIndex,float x,float y)295     explicit WithCoordsMatcher(size_t pointerIndex, float x, float y)
296           : mPointerIndex(pointerIndex), mX(x), mY(y) {}
297 
MatchAndExplain(const MotionEvent & event,std::ostream * os)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 
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)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 
DescribeTo(std::ostream * os)329     void DescribeTo(std::ostream* os) const {
330         *os << "with coords (" << mX << ", " << mY << ") at pointer index " << mPointerIndex;
331     }
332 
DescribeNegationTo(std::ostream * os)333     void DescribeNegationTo(std::ostream* os) const { *os << "wrong coords"; }
334 
335 private:
336     const size_t mPointerIndex;
337     const float mX;
338     const float mY;
339 };
340 
WithCoords(float x,float y)341 inline WithCoordsMatcher WithCoords(float x, float y) {
342     return WithCoordsMatcher(0, x, y);
343 }
344 
WithPointerCoords(size_t pointerIndex,float x,float y)345 inline WithCoordsMatcher WithPointerCoords(size_t pointerIndex, float x, float y) {
346     return WithCoordsMatcher(pointerIndex, x, y);
347 }
348 
349 /// Raw coordinate matcher
350 class WithRawCoordsMatcher {
351 public:
352     using is_gtest_matcher = void;
WithRawCoordsMatcher(size_t pointerIndex,float rawX,float rawY)353     explicit WithRawCoordsMatcher(size_t pointerIndex, float rawX, float rawY)
354           : mPointerIndex(pointerIndex), mRawX(rawX), mRawY(rawY) {}
355 
MatchAndExplain(const MotionEvent & event,std::ostream * os)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 
DescribeTo(std::ostream * os)372     void DescribeTo(std::ostream* os) const {
373         *os << "with raw coords (" << mRawX << ", " << mRawY << ") at pointer index "
374             << mPointerIndex;
375     }
376 
DescribeNegationTo(std::ostream * os)377     void DescribeNegationTo(std::ostream* os) const { *os << "wrong raw coords"; }
378 
379 private:
380     const size_t mPointerIndex;
381     const float mRawX;
382     const float mRawY;
383 };
384 
WithRawCoords(float rawX,float rawY)385 inline WithRawCoordsMatcher WithRawCoords(float rawX, float rawY) {
386     return WithRawCoordsMatcher(0, rawX, rawY);
387 }
388 
WithPointerRawCoords(size_t pointerIndex,float rawX,float rawY)389 inline WithRawCoordsMatcher WithPointerRawCoords(size_t pointerIndex, float rawX, float rawY) {
390     return WithRawCoordsMatcher(pointerIndex, rawX, rawY);
391 }
392 
393 /// Pointer count
394 class WithPointerCountMatcher {
395 public:
396     using is_gtest_matcher = void;
WithPointerCountMatcher(size_t pointerCount)397     explicit WithPointerCountMatcher(size_t pointerCount) : mPointerCount(pointerCount) {}
398 
MatchAndExplain(const MotionEvent & event,std::ostream * os)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 
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)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 
DescribeTo(std::ostream * os)417     void DescribeTo(std::ostream* os) const { *os << "with pointer count " << mPointerCount; }
418 
DescribeNegationTo(std::ostream * os)419     void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer count"; }
420 
421 private:
422     const size_t mPointerCount;
423 };
424 
WithPointerCount(size_t pointerCount)425 inline WithPointerCountMatcher WithPointerCount(size_t pointerCount) {
426     return WithPointerCountMatcher(pointerCount);
427 }
428 
429 /// Pointers matcher
430 class WithPointersMatcher {
431 public:
432     using is_gtest_matcher = void;
WithPointersMatcher(std::map<int32_t,PointF> pointers)433     explicit WithPointersMatcher(std::map<int32_t, PointF> pointers) : mPointers(pointers) {}
434 
MatchAndExplain(const MotionEvent & event,std::ostream * os)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 
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)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 
DescribeTo(std::ostream * os)466     void DescribeTo(std::ostream* os) const {
467         *os << "with pointers " << dumpMap(mPointers, constToString, pointFToString);
468     }
469 
DescribeNegationTo(std::ostream * os)470     void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointers"; }
471 
472 private:
473     const std::map<int32_t, PointF> mPointers;
474 };
475 
WithPointers(const std::map<int32_t,PointF> & pointers)476 inline WithPointersMatcher WithPointers(
477         const std::map<int32_t /*id*/, PointF /*coords*/>& pointers) {
478     return WithPointersMatcher(pointers);
479 }
480 
481 /// Pointer ids matcher
482 class WithPointerIdsMatcher {
483 public:
484     using is_gtest_matcher = void;
WithPointerIdsMatcher(std::set<int32_t> pointerIds)485     explicit WithPointerIdsMatcher(std::set<int32_t> pointerIds) : mPointerIds(pointerIds) {}
486 
MatchAndExplain(const MotionEvent & event,std::ostream * os)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 
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)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 
DescribeTo(std::ostream * os)516     void DescribeTo(std::ostream* os) const { *os << "with pointer ids " << dumpSet(mPointerIds); }
517 
DescribeNegationTo(std::ostream * os)518     void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer ids"; }
519 
520 private:
521     const std::set<int32_t> mPointerIds;
522 };
523 
WithPointerIds(const std::set<int32_t> & pointerIds)524 inline WithPointerIdsMatcher WithPointerIds(const std::set<int32_t /*id*/>& pointerIds) {
525     return WithPointerIdsMatcher(pointerIds);
526 }
527 
528 /// Key code
529 class WithKeyCodeMatcher {
530 public:
531     using is_gtest_matcher = void;
WithKeyCodeMatcher(int32_t keyCode)532     explicit WithKeyCodeMatcher(int32_t keyCode) : mKeyCode(keyCode) {}
533 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)534     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
535         return mKeyCode == args.keyCode;
536     }
537 
MatchAndExplain(const KeyEvent & event,std::ostream *)538     bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
539         return mKeyCode == event.getKeyCode();
540     }
541 
DescribeTo(std::ostream * os)542     void DescribeTo(std::ostream* os) const {
543         *os << "with key code " << KeyEvent::getLabel(mKeyCode);
544     }
545 
DescribeNegationTo(std::ostream * os)546     void DescribeNegationTo(std::ostream* os) const { *os << "wrong key code"; }
547 
548 private:
549     const int32_t mKeyCode;
550 };
551 
WithKeyCode(int32_t keyCode)552 inline WithKeyCodeMatcher WithKeyCode(int32_t keyCode) {
553     return WithKeyCodeMatcher(keyCode);
554 }
555 
556 /// Scan code
557 class WithScanCodeMatcher {
558 public:
559     using is_gtest_matcher = void;
WithScanCodeMatcher(int32_t scanCode)560     explicit WithScanCodeMatcher(int32_t scanCode) : mScanCode(scanCode) {}
561 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)562     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
563         return mScanCode == args.scanCode;
564     }
565 
MatchAndExplain(const KeyEvent & event,std::ostream *)566     bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
567         return mScanCode == event.getKeyCode();
568     }
569 
DescribeTo(std::ostream * os)570     void DescribeTo(std::ostream* os) const {
571         *os << "with scan code " << KeyEvent::getLabel(mScanCode);
572     }
573 
DescribeNegationTo(std::ostream * os)574     void DescribeNegationTo(std::ostream* os) const { *os << "wrong scan code"; }
575 
576 private:
577     const int32_t mScanCode;
578 };
579 
WithScanCode(int32_t scanCode)580 inline WithScanCodeMatcher WithScanCode(int32_t scanCode) {
581     return WithScanCodeMatcher(scanCode);
582 }
583 
584 /// EventId
585 class WithEventIdMatcher {
586 public:
587     using is_gtest_matcher = void;
WithEventIdMatcher(int32_t eventId)588     explicit WithEventIdMatcher(int32_t eventId) : mEventId(eventId) {}
589 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)590     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
591         return mEventId == args.id;
592     }
593 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)594     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
595         return mEventId == args.id;
596     }
597 
MatchAndExplain(const InputEvent & event,std::ostream *)598     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
599         return mEventId == event.getId();
600     }
601 
DescribeTo(std::ostream * os)602     void DescribeTo(std::ostream* os) const { *os << "with eventId 0x" << std::hex << mEventId; }
603 
DescribeNegationTo(std::ostream * os)604     void DescribeNegationTo(std::ostream* os) const {
605         *os << "with eventId not equal to 0x" << std::hex << mEventId;
606     }
607 
608 private:
609     const int32_t mEventId;
610 };
611 
WithEventId(int32_t eventId)612 inline WithEventIdMatcher WithEventId(int32_t eventId) {
613     return WithEventIdMatcher(eventId);
614 }
615 
616 /// EventIdSource
617 class WithEventIdSourceMatcher {
618 public:
619     using is_gtest_matcher = void;
WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)620     explicit WithEventIdSourceMatcher(IdGenerator::Source eventIdSource)
621           : mEventIdSource(eventIdSource) {}
622 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream *)623     bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
624         return mEventIdSource == IdGenerator::getSource(args.id);
625     }
626 
MatchAndExplain(const NotifyKeyArgs & args,std::ostream *)627     bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
628         return mEventIdSource == IdGenerator::getSource(args.id);
629     }
630 
MatchAndExplain(const InputEvent & event,std::ostream *)631     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
632         return mEventIdSource == IdGenerator::getSource(event.getId());
633     }
634 
DescribeTo(std::ostream * os)635     void DescribeTo(std::ostream* os) const {
636         *os << "with eventId from source 0x" << std::hex << ftl::to_underlying(mEventIdSource);
637     }
638 
DescribeNegationTo(std::ostream * os)639     void DescribeNegationTo(std::ostream* os) const { *os << "wrong event from source"; }
640 
641 private:
642     const IdGenerator::Source mEventIdSource;
643 };
644 
WithEventIdSource(IdGenerator::Source eventIdSource)645 inline WithEventIdSourceMatcher WithEventIdSource(IdGenerator::Source eventIdSource) {
646     return WithEventIdSourceMatcher(eventIdSource);
647 }
648 
649 MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count") {
650     return arg.getRepeatCount() == repeatCount;
651 }
652 
653 class WithPointerIdMatcher {
654 public:
655     using is_gtest_matcher = void;
WithPointerIdMatcher(size_t index,int32_t pointerId)656     explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
657           : mIndex(index), mPointerId(pointerId) {}
658 
MatchAndExplain(const NotifyMotionArgs & args,std::ostream * os)659     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 
665         return args.pointerProperties[mIndex].id == mPointerId;
666     }
667 
MatchAndExplain(const MotionEvent & event,std::ostream *)668     bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
669         return event.getPointerId(mIndex) == mPointerId;
670     }
671 
DescribeTo(std::ostream * os)672     void DescribeTo(std::ostream* os) const {
673         *os << "with pointer[" << mIndex << "] id = " << mPointerId;
674     }
675 
DescribeNegationTo(std::ostream * os)676     void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; }
677 
678 private:
679     const size_t mIndex;
680     const int32_t mPointerId;
681 };
682 
WithPointerId(size_t index,int32_t pointerId)683 inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) {
684     return WithPointerIdMatcher(index, pointerId);
685 }
686 
687 MATCHER_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 
695 /// Relative motion matcher
696 class WithRelativeMotionMatcher {
697 public:
698     using is_gtest_matcher = void;
WithRelativeMotionMatcher(size_t pointerIndex,float relX,float relY)699     explicit WithRelativeMotionMatcher(size_t pointerIndex, float relX, float relY)
700           : mPointerIndex(pointerIndex), mRelX(relX), mRelY(relY) {}
701 
MatchAndExplain(const NotifyMotionArgs & event,std::ostream * os)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 
DescribeTo(std::ostream * os)720     void DescribeTo(std::ostream* os) const {
721         *os << "with relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
722             << mPointerIndex;
723     }
724 
DescribeNegationTo(std::ostream * os)725     void DescribeNegationTo(std::ostream* os) const { *os << "wrong relative motion"; }
726 
727 private:
728     const size_t mPointerIndex;
729     const float mRelX;
730     const float mRelY;
731 };
732 
WithRelativeMotion(float relX,float relY)733 inline WithRelativeMotionMatcher WithRelativeMotion(float relX, float relY) {
734     return WithRelativeMotionMatcher(0, relX, relY);
735 }
736 
WithPointerRelativeMotion(size_t pointerIndex,float relX,float relY)737 inline WithRelativeMotionMatcher WithPointerRelativeMotion(size_t pointerIndex, float relX,
738                                                            float relY) {
739     return WithRelativeMotionMatcher(pointerIndex, relX, relY);
740 }
741 
742 MATCHER_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 
753 MATCHER_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 
766 MATCHER_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 
775 MATCHER_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 
784 MATCHER_P(WithPressure, pressure, "InputEvent with specified pressure") {
785     const auto argPressure = arg.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
786     *result_listener << "expected pressure " << pressure << ", but got " << argPressure;
787     return argPressure == pressure;
788 }
789 
790 MATCHER_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 
796 MATCHER_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 
802 MATCHER_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 
808 MATCHER_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 
814 MATCHER_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 
823 MATCHER_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 
831 MATCHER_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 
839 MATCHER_P(WithToolType, toolType, "InputEvent with specified tool type") {
840     const auto argToolType = arg.pointerProperties[0].toolType;
841     *result_listener << "expected tool type " << ftl::enum_string(toolType) << ", but got "
842                      << ftl::enum_string(argToolType);
843     return argToolType == toolType;
844 }
845 
846 MATCHER_P2(WithPointerToolType, pointerIndex, toolType,
847            "InputEvent with specified tool type for pointer") {
848     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 "
854                      << ftl::enum_string(toolType) << ", but got " << ftl::enum_string(argToolType);
855     return argToolType == toolType;
856 }
857 
858 MATCHER_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 
865 MATCHER_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 
870 MATCHER_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 
876 MATCHER_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 
882 MATCHER_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 
887 MATCHER_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 
892 MATCHER_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 
898 MATCHER_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 
904 MATCHER_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 
910 } // namespace android
911