blob: 3589de599ff78d5925889639a4ff9b0b834ff0fc [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
78 bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
79 bool matches = mAction == event.getAction();
80 if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL) {
81 matches &= (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
82 }
83 return matches;
84 }
85
86 void DescribeTo(std::ostream* os) const {
87 *os << "with motion action " << MotionEvent::actionToString(mAction);
88 if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
89 *os << " and FLAG_CANCELED";
90 }
91 }
92
93 void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
94
95private:
96 const int32_t mAction;
97};
98
99inline WithMotionActionMatcher WithMotionAction(int32_t action) {
100 return WithMotionActionMatcher(action);
101}
102
Paul Ramireze37f8342024-08-28 18:42:21 +0000103class WithSampleCountMatcher {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000104public:
105 using is_gtest_matcher = void;
Paul Ramireze37f8342024-08-28 18:42:21 +0000106 explicit WithSampleCountMatcher(size_t sampleCount) : mExpectedSampleCount{sampleCount} {}
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000107
108 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream*) const {
Paul Ramireze37f8342024-08-28 18:42:21 +0000109 return (motionEvent.getHistorySize() + 1) == mExpectedSampleCount;
110 }
111
112 void DescribeTo(std::ostream* os) const { *os << "sample count " << mExpectedSampleCount; }
113
114 void DescribeNegationTo(std::ostream* os) const { *os << "different sample count"; }
115
116private:
117 const size_t mExpectedSampleCount;
118};
119
120inline WithSampleCountMatcher WithSampleCount(size_t sampleCount) {
121 return WithSampleCountMatcher(sampleCount);
122}
123
124class WithSampleMatcher {
125public:
126 using is_gtest_matcher = void;
127 explicit WithSampleMatcher(size_t sampleIndex, const Sample& sample)
128 : mSampleIndex{sampleIndex}, mSample{sample} {}
129
130 bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream* os) const {
131 if (motionEvent.getHistorySize() < mSampleIndex) {
132 *os << "sample index out of bounds";
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000133 return false;
134 }
Paul Ramireze37f8342024-08-28 18:42:21 +0000135
136 if (motionEvent.getHistoricalEventTime(mSampleIndex) != mSample.eventTime.count()) {
137 *os << "event time mismatch. sample: "
138 << motionEvent.getHistoricalEventTime(mSampleIndex)
139 << " expected: " << mSample.eventTime.count();
140 return false;
141 }
142
143 if (motionEvent.getPointerCount() != mSample.pointers.size()) {
144 *os << "pointer count mismatch. sample: " << motionEvent.getPointerCount()
145 << " expected: " << mSample.pointers.size();
146 return false;
147 }
148
149 for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
150 ++pointerIndex) {
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000151 const PointerCoords& pointerCoords =
Paul Ramireze37f8342024-08-28 18:42:21 +0000152 *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
153 if ((pointerCoords.getX() != mSample.pointers[pointerIndex].x) ||
154 (pointerCoords.getY() != mSample.pointers[pointerIndex].y)) {
155 *os << "sample coordinates mismatch at pointer index " << pointerIndex
156 << ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
157 << ") expected: (" << mSample.pointers[pointerIndex].x << ", "
158 << mSample.pointers[pointerIndex].y << ")";
159 return false;
160 }
161 if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
162 mSample.pointers[pointerIndex].isResampled) {
163 *os << "resampling flag mismatch. sample: "
164 << motionEvent.isResampled(pointerIndex, mSampleIndex)
165 << " expected: " << mSample.pointers[pointerIndex].isResampled;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000166 return false;
167 }
168 }
169 return true;
170 }
171
Paul Ramireze37f8342024-08-28 18:42:21 +0000172 void DescribeTo(std::ostream* os) const { *os << "motion event sample properties match."; }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000173
Paul Ramireze37f8342024-08-28 18:42:21 +0000174 void DescribeNegationTo(std::ostream* os) const {
175 *os << "motion event sample properties do not match expected properties.";
176 }
177
178private:
179 const size_t mSampleIndex;
180 const Sample mSample;
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000181};
182
Paul Ramireze37f8342024-08-28 18:42:21 +0000183inline WithSampleMatcher WithSample(size_t sampleIndex, const Sample& sample) {
184 return WithSampleMatcher(sampleIndex, sample);
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000185}
Paul Ramireze37f8342024-08-28 18:42:21 +0000186
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000187} // namespace android