blob: 290a97d73668bbfbdbfc7fc85f31012eceb81415 [file] [log] [blame]
Paul Ramirez00cf5d02024-09-05 17:10:12 +00001/**
2 * Copyright 2024 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
Paul Ramireze37f8342024-08-28 18:42:21 +000019#include <chrono>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000020#include <ostream>
Paul Ramireze37f8342024-08-28 18:42:21 +000021#include <vector>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000022
Paul Ramireze37f8342024-08-28 18:42:21 +000023#include <android-base/logging.h>
24#include <gtest/gtest.h>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000025#include <input/Input.h>
26
27namespace android {
28
Paul Ramireze37f8342024-08-28 18:42:21 +000029namespace {
30
31using ::testing::Matcher;
32
33} // namespace
34
Paul Ramirez00cf5d02024-09-05 17:10:12 +000035/**
36 * This file contains a copy of Matchers from .../inputflinger/tests/TestEventMatchers.h. Ideally,
37 * implementations must not be duplicated.
38 * TODO(b/365606513): Find a way to share TestEventMatchers.h between inputflinger and libinput.
39 */
40
Paul Ramireze37f8342024-08-28 18:42:21 +000041struct PointerArgs {
42 float x{0.0f};
43 float y{0.0f};
44 bool isResampled{false};
45};
46
47struct Sample {
48 std::chrono::nanoseconds eventTime{0};
49 std::vector<PointerArgs> pointers{};
50};
51
Paul Ramirez00cf5d02024-09-05 17:10:12 +000052class WithDeviceIdMatcher {
53public:
54 using is_gtest_matcher = void;
55 explicit WithDeviceIdMatcher(DeviceId deviceId) : mDeviceId(deviceId) {}
56
57 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
58 return mDeviceId == event.getDeviceId();
59 }
60
61 void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
62
63 void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
64
65private:
66 const DeviceId mDeviceId;
67};
68
69inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
70 return WithDeviceIdMatcher(deviceId);
71}
72
73class WithMotionActionMatcher {
74public:
75 using is_gtest_matcher = void;
76 explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
77
Harry Cuttsfb6d5852024-10-29 11:47:32 +000078 bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
79 if (mAction != event.getAction()) {
80 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
81 << MotionEvent::actionToString(event.getAction());
82 return false;
Paul Ramirez00cf5d02024-09-05 17:10:12 +000083 }
Harry Cuttsfb6d5852024-10-29 11:47:32 +000084 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
85 (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
86 *listener << "event with CANCEL action is missing FLAG_CANCELED";
87 return false;
88 }
89 return true;
Paul Ramirez00cf5d02024-09-05 17:10:12 +000090 }
91
92 void DescribeTo(std::ostream* os) const {
93 *os << "with motion action " << MotionEvent::actionToString(mAction);
94 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
95 *os << " and FLAG_CANCELED";
96 }
97 }
98
99 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
100
101private:
102 const int32_t mAction;
103};
104
105inline WithMotionActionMatcher WithMotionAction(int32_t action) {
106 return WithMotionActionMatcher(action);
107}
108
Paul Ramireze37f8342024-08-28 18:42:21 +0000109class WithSampleCountMatcher {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000110public:
111 using is_gtest_matcher = void;
Paul Ramireze37f8342024-08-28 18:42:21 +0000112 explicit WithSampleCountMatcher(size_t sampleCount) : mExpectedSampleCount{sampleCount} {}
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000113
114 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream*) const {
Paul Ramireze37f8342024-08-28 18:42:21 +0000115 return (motionEvent.getHistorySize() + 1) == mExpectedSampleCount;
116 }
117
118 void DescribeTo(std::ostream* os) const { *os << "sample count " << mExpectedSampleCount; }
119
120 void DescribeNegationTo(std::ostream* os) const { *os << "different sample count"; }
121
122private:
123 const size_t mExpectedSampleCount;
124};
125
126inline WithSampleCountMatcher WithSampleCount(size_t sampleCount) {
127 return WithSampleCountMatcher(sampleCount);
128}
129
130class WithSampleMatcher {
131public:
132 using is_gtest_matcher = void;
133 explicit WithSampleMatcher(size_t sampleIndex, const Sample& sample)
134 : mSampleIndex{sampleIndex}, mSample{sample} {}
135
136 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream* os) const {
137 if (motionEvent.getHistorySize() < mSampleIndex) {
138 *os << "sample index out of bounds";
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000139 return false;
140 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000141
142 if (motionEvent.getHistoricalEventTime(mSampleIndex) != mSample.eventTime.count()) {
143 *os << "event time mismatch. sample: "
144 << motionEvent.getHistoricalEventTime(mSampleIndex)
145 << " expected: " << mSample.eventTime.count();
146 return false;
147 }
148
149 if (motionEvent.getPointerCount() != mSample.pointers.size()) {
150 *os << "pointer count mismatch. sample: " << motionEvent.getPointerCount()
151 << " expected: " << mSample.pointers.size();
152 return false;
153 }
154
155 for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
156 ++pointerIndex) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000157 const PointerCoords& pointerCoords =
Paul Ramireze37f8342024-08-28 18:42:21 +0000158 *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
159 if ((pointerCoords.getX() != mSample.pointers[pointerIndex].x) ||
160 (pointerCoords.getY() != mSample.pointers[pointerIndex].y)) {
161 *os << "sample coordinates mismatch at pointer index " << pointerIndex
162 << ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
163 << ") expected: (" << mSample.pointers[pointerIndex].x << ", "
164 << mSample.pointers[pointerIndex].y << ")";
165 return false;
166 }
167 if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
168 mSample.pointers[pointerIndex].isResampled) {
169 *os << "resampling flag mismatch. sample: "
170 << motionEvent.isResampled(pointerIndex, mSampleIndex)
171 << " expected: " << mSample.pointers[pointerIndex].isResampled;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000172 return false;
173 }
174 }
175 return true;
176 }
177
Paul Ramireze37f8342024-08-28 18:42:21 +0000178 void DescribeTo(std::ostream* os) const { *os << "motion event sample properties match."; }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000179
Paul Ramireze37f8342024-08-28 18:42:21 +0000180 void DescribeNegationTo(std::ostream* os) const {
181 *os << "motion event sample properties do not match expected properties.";
182 }
183
184private:
185 const size_t mSampleIndex;
186 const Sample mSample;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000187};
188
Paul Ramireze37f8342024-08-28 18:42:21 +0000189inline WithSampleMatcher WithSample(size_t sampleIndex, const Sample& sample) {
190 return WithSampleMatcher(sampleIndex, sample);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000191}
Paul Ramireze37f8342024-08-28 18:42:21 +0000192
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000193} // namespace android