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