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