blob: 56eaefd0746716217f55ed948659d4a55c18d1ac [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 Ramirez53463392024-11-11 21:49:51 +000020#include <cmath>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000021#include <ostream>
Paul Ramireze37f8342024-08-28 18:42:21 +000022#include <vector>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000023
Paul Ramireze37f8342024-08-28 18:42:21 +000024#include <android-base/logging.h>
25#include <gtest/gtest.h>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000026#include <input/Input.h>
27
28namespace android {
29
Paul Ramireze37f8342024-08-28 18:42:21 +000030namespace {
31
32using ::testing::Matcher;
33
34} // namespace
35
Paul Ramirez00cf5d02024-09-05 17:10:12 +000036/**
37 * This file contains a copy of Matchers from .../inputflinger/tests/TestEventMatchers.h. Ideally,
38 * implementations must not be duplicated.
39 * TODO(b/365606513): Find a way to share TestEventMatchers.h between inputflinger and libinput.
40 */
41
Paul Ramireze37f8342024-08-28 18:42:21 +000042struct PointerArgs {
43 float x{0.0f};
44 float y{0.0f};
45 bool isResampled{false};
46};
47
48struct Sample {
49 std::chrono::nanoseconds eventTime{0};
50 std::vector<PointerArgs> pointers{};
51};
52
Paul Ramirez00cf5d02024-09-05 17:10:12 +000053class WithDeviceIdMatcher {
54public:
55 using is_gtest_matcher = void;
56 explicit WithDeviceIdMatcher(DeviceId deviceId) : mDeviceId(deviceId) {}
57
58 bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
59 return mDeviceId == event.getDeviceId();
60 }
61
62 void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
63
64 void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
65
66private:
67 const DeviceId mDeviceId;
68};
69
70inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
71 return WithDeviceIdMatcher(deviceId);
72}
73
74class WithMotionActionMatcher {
75public:
76 using is_gtest_matcher = void;
77 explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
78
Harry Cuttsfb6d5852024-10-29 11:47:32 +000079 bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
80 if (mAction != event.getAction()) {
81 *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
82 << MotionEvent::actionToString(event.getAction());
83 return false;
Paul Ramirez00cf5d02024-09-05 17:10:12 +000084 }
Harry Cuttsfb6d5852024-10-29 11:47:32 +000085 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
86 (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
87 *listener << "event with CANCEL action is missing FLAG_CANCELED";
88 return false;
89 }
90 return true;
Paul Ramirez00cf5d02024-09-05 17:10:12 +000091 }
92
93 void DescribeTo(std::ostream* os) const {
94 *os << "with motion action " << MotionEvent::actionToString(mAction);
95 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
96 *os << " and FLAG_CANCELED";
97 }
98 }
99
100 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
101
102private:
103 const int32_t mAction;
104};
105
106inline WithMotionActionMatcher WithMotionAction(int32_t action) {
107 return WithMotionActionMatcher(action);
108}
109
Paul Ramireze37f8342024-08-28 18:42:21 +0000110class WithSampleCountMatcher {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000111public:
112 using is_gtest_matcher = void;
Paul Ramireze37f8342024-08-28 18:42:21 +0000113 explicit WithSampleCountMatcher(size_t sampleCount) : mExpectedSampleCount{sampleCount} {}
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000114
115 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream*) const {
Paul Ramireze37f8342024-08-28 18:42:21 +0000116 return (motionEvent.getHistorySize() + 1) == mExpectedSampleCount;
117 }
118
119 void DescribeTo(std::ostream* os) const { *os << "sample count " << mExpectedSampleCount; }
120
121 void DescribeNegationTo(std::ostream* os) const { *os << "different sample count"; }
122
123private:
124 const size_t mExpectedSampleCount;
125};
126
127inline WithSampleCountMatcher WithSampleCount(size_t sampleCount) {
128 return WithSampleCountMatcher(sampleCount);
129}
130
131class WithSampleMatcher {
132public:
133 using is_gtest_matcher = void;
134 explicit WithSampleMatcher(size_t sampleIndex, const Sample& sample)
135 : mSampleIndex{sampleIndex}, mSample{sample} {}
136
137 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream* os) const {
138 if (motionEvent.getHistorySize() < mSampleIndex) {
139 *os << "sample index out of bounds";
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000140 return false;
141 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000142
143 if (motionEvent.getHistoricalEventTime(mSampleIndex) != mSample.eventTime.count()) {
144 *os << "event time mismatch. sample: "
145 << motionEvent.getHistoricalEventTime(mSampleIndex)
146 << " expected: " << mSample.eventTime.count();
147 return false;
148 }
149
150 if (motionEvent.getPointerCount() != mSample.pointers.size()) {
151 *os << "pointer count mismatch. sample: " << motionEvent.getPointerCount()
152 << " expected: " << mSample.pointers.size();
153 return false;
154 }
155
156 for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
157 ++pointerIndex) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000158 const PointerCoords& pointerCoords =
Paul Ramireze37f8342024-08-28 18:42:21 +0000159 *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
Paul Ramirez53463392024-11-11 21:49:51 +0000160
161 if ((std::abs(pointerCoords.getX() - mSample.pointers[pointerIndex].x) >
162 MotionEvent::ROUNDING_PRECISION) ||
163 (std::abs(pointerCoords.getY() - mSample.pointers[pointerIndex].y) >
164 MotionEvent::ROUNDING_PRECISION)) {
Paul Ramireze37f8342024-08-28 18:42:21 +0000165 *os << "sample coordinates mismatch at pointer index " << pointerIndex
166 << ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
167 << ") expected: (" << mSample.pointers[pointerIndex].x << ", "
168 << mSample.pointers[pointerIndex].y << ")";
169 return false;
170 }
Paul Ramirez53463392024-11-11 21:49:51 +0000171
Paul Ramireze37f8342024-08-28 18:42:21 +0000172 if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
173 mSample.pointers[pointerIndex].isResampled) {
174 *os << "resampling flag mismatch. sample: "
175 << motionEvent.isResampled(pointerIndex, mSampleIndex)
176 << " expected: " << mSample.pointers[pointerIndex].isResampled;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000177 return false;
178 }
179 }
180 return true;
181 }
182
Paul Ramireze37f8342024-08-28 18:42:21 +0000183 void DescribeTo(std::ostream* os) const { *os << "motion event sample properties match."; }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000184
Paul Ramireze37f8342024-08-28 18:42:21 +0000185 void DescribeNegationTo(std::ostream* os) const {
186 *os << "motion event sample properties do not match expected properties.";
187 }
188
189private:
190 const size_t mSampleIndex;
191 const Sample mSample;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000192};
193
Paul Ramireze37f8342024-08-28 18:42:21 +0000194inline WithSampleMatcher WithSample(size_t sampleIndex, const Sample& sample) {
195 return WithSampleMatcher(sampleIndex, sample);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000196}
Paul Ramireze37f8342024-08-28 18:42:21 +0000197
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000198} // namespace android