xref: /aosp_15_r20/frameworks/native/libs/input/tests/TestEventMatchers.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /**
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2024 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
20*38e8c45fSAndroid Build Coastguard Worker #include <cmath>
21*38e8c45fSAndroid Build Coastguard Worker #include <ostream>
22*38e8c45fSAndroid Build Coastguard Worker #include <vector>
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <input/Input.h>
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker namespace android {
29*38e8c45fSAndroid Build Coastguard Worker 
30*38e8c45fSAndroid Build Coastguard Worker namespace {
31*38e8c45fSAndroid Build Coastguard Worker 
32*38e8c45fSAndroid Build Coastguard Worker using ::testing::Matcher;
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker } // namespace
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker /**
37*38e8c45fSAndroid Build Coastguard Worker  * This file contains a copy of Matchers from .../inputflinger/tests/TestEventMatchers.h. Ideally,
38*38e8c45fSAndroid Build Coastguard Worker  * implementations must not be duplicated.
39*38e8c45fSAndroid Build Coastguard Worker  * TODO(b/365606513): Find a way to share TestEventMatchers.h between inputflinger and libinput.
40*38e8c45fSAndroid Build Coastguard Worker  */
41*38e8c45fSAndroid Build Coastguard Worker 
42*38e8c45fSAndroid Build Coastguard Worker struct PointerArgs {
43*38e8c45fSAndroid Build Coastguard Worker     float x{0.0f};
44*38e8c45fSAndroid Build Coastguard Worker     float y{0.0f};
45*38e8c45fSAndroid Build Coastguard Worker     bool isResampled{false};
46*38e8c45fSAndroid Build Coastguard Worker };
47*38e8c45fSAndroid Build Coastguard Worker 
48*38e8c45fSAndroid Build Coastguard Worker struct Sample {
49*38e8c45fSAndroid Build Coastguard Worker     std::chrono::nanoseconds eventTime{0};
50*38e8c45fSAndroid Build Coastguard Worker     std::vector<PointerArgs> pointers{};
51*38e8c45fSAndroid Build Coastguard Worker };
52*38e8c45fSAndroid Build Coastguard Worker 
53*38e8c45fSAndroid Build Coastguard Worker class WithDeviceIdMatcher {
54*38e8c45fSAndroid Build Coastguard Worker public:
55*38e8c45fSAndroid Build Coastguard Worker     using is_gtest_matcher = void;
WithDeviceIdMatcher(DeviceId deviceId)56*38e8c45fSAndroid Build Coastguard Worker     explicit WithDeviceIdMatcher(DeviceId deviceId) : mDeviceId(deviceId) {}
57*38e8c45fSAndroid Build Coastguard Worker 
MatchAndExplain(const InputEvent & event,std::ostream *)58*38e8c45fSAndroid Build Coastguard Worker     bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
59*38e8c45fSAndroid Build Coastguard Worker         return mDeviceId == event.getDeviceId();
60*38e8c45fSAndroid Build Coastguard Worker     }
61*38e8c45fSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)62*38e8c45fSAndroid Build Coastguard Worker     void DescribeTo(std::ostream* os) const { *os << "with device id " << mDeviceId; }
63*38e8c45fSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)64*38e8c45fSAndroid Build Coastguard Worker     void DescribeNegationTo(std::ostream* os) const { *os << "wrong device id"; }
65*38e8c45fSAndroid Build Coastguard Worker 
66*38e8c45fSAndroid Build Coastguard Worker private:
67*38e8c45fSAndroid Build Coastguard Worker     const DeviceId mDeviceId;
68*38e8c45fSAndroid Build Coastguard Worker };
69*38e8c45fSAndroid Build Coastguard Worker 
WithDeviceId(int32_t deviceId)70*38e8c45fSAndroid Build Coastguard Worker inline WithDeviceIdMatcher WithDeviceId(int32_t deviceId) {
71*38e8c45fSAndroid Build Coastguard Worker     return WithDeviceIdMatcher(deviceId);
72*38e8c45fSAndroid Build Coastguard Worker }
73*38e8c45fSAndroid Build Coastguard Worker 
74*38e8c45fSAndroid Build Coastguard Worker class WithMotionActionMatcher {
75*38e8c45fSAndroid Build Coastguard Worker public:
76*38e8c45fSAndroid Build Coastguard Worker     using is_gtest_matcher = void;
WithMotionActionMatcher(int32_t action)77*38e8c45fSAndroid Build Coastguard Worker     explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
78*38e8c45fSAndroid Build Coastguard Worker 
MatchAndExplain(const MotionEvent & event,testing::MatchResultListener * listener)79*38e8c45fSAndroid Build Coastguard Worker     bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
80*38e8c45fSAndroid Build Coastguard Worker         if (mAction != event.getAction()) {
81*38e8c45fSAndroid Build Coastguard Worker             *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
82*38e8c45fSAndroid Build Coastguard Worker                       << MotionEvent::actionToString(event.getAction());
83*38e8c45fSAndroid Build Coastguard Worker             return false;
84*38e8c45fSAndroid Build Coastguard Worker         }
85*38e8c45fSAndroid Build Coastguard Worker         if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
86*38e8c45fSAndroid Build Coastguard Worker             (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
87*38e8c45fSAndroid Build Coastguard Worker             *listener << "event with CANCEL action is missing FLAG_CANCELED";
88*38e8c45fSAndroid Build Coastguard Worker             return false;
89*38e8c45fSAndroid Build Coastguard Worker         }
90*38e8c45fSAndroid Build Coastguard Worker         return true;
91*38e8c45fSAndroid Build Coastguard Worker     }
92*38e8c45fSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)93*38e8c45fSAndroid Build Coastguard Worker     void DescribeTo(std::ostream* os) const {
94*38e8c45fSAndroid Build Coastguard Worker         *os << "with motion action " << MotionEvent::actionToString(mAction);
95*38e8c45fSAndroid Build Coastguard Worker         if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
96*38e8c45fSAndroid Build Coastguard Worker             *os << " and FLAG_CANCELED";
97*38e8c45fSAndroid Build Coastguard Worker         }
98*38e8c45fSAndroid Build Coastguard Worker     }
99*38e8c45fSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)100*38e8c45fSAndroid Build Coastguard Worker     void DescribeNegationTo(std::ostream* os) const { *os << "wrong action"; }
101*38e8c45fSAndroid Build Coastguard Worker 
102*38e8c45fSAndroid Build Coastguard Worker private:
103*38e8c45fSAndroid Build Coastguard Worker     const int32_t mAction;
104*38e8c45fSAndroid Build Coastguard Worker };
105*38e8c45fSAndroid Build Coastguard Worker 
WithMotionAction(int32_t action)106*38e8c45fSAndroid Build Coastguard Worker inline WithMotionActionMatcher WithMotionAction(int32_t action) {
107*38e8c45fSAndroid Build Coastguard Worker     return WithMotionActionMatcher(action);
108*38e8c45fSAndroid Build Coastguard Worker }
109*38e8c45fSAndroid Build Coastguard Worker 
110*38e8c45fSAndroid Build Coastguard Worker class WithSampleCountMatcher {
111*38e8c45fSAndroid Build Coastguard Worker public:
112*38e8c45fSAndroid Build Coastguard Worker     using is_gtest_matcher = void;
WithSampleCountMatcher(size_t sampleCount)113*38e8c45fSAndroid Build Coastguard Worker     explicit WithSampleCountMatcher(size_t sampleCount) : mExpectedSampleCount{sampleCount} {}
114*38e8c45fSAndroid Build Coastguard Worker 
MatchAndExplain(const MotionEvent & motionEvent,std::ostream *)115*38e8c45fSAndroid Build Coastguard Worker     bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream*) const {
116*38e8c45fSAndroid Build Coastguard Worker         return (motionEvent.getHistorySize() + 1) == mExpectedSampleCount;
117*38e8c45fSAndroid Build Coastguard Worker     }
118*38e8c45fSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)119*38e8c45fSAndroid Build Coastguard Worker     void DescribeTo(std::ostream* os) const { *os << "sample count " << mExpectedSampleCount; }
120*38e8c45fSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)121*38e8c45fSAndroid Build Coastguard Worker     void DescribeNegationTo(std::ostream* os) const { *os << "different sample count"; }
122*38e8c45fSAndroid Build Coastguard Worker 
123*38e8c45fSAndroid Build Coastguard Worker private:
124*38e8c45fSAndroid Build Coastguard Worker     const size_t mExpectedSampleCount;
125*38e8c45fSAndroid Build Coastguard Worker };
126*38e8c45fSAndroid Build Coastguard Worker 
WithSampleCount(size_t sampleCount)127*38e8c45fSAndroid Build Coastguard Worker inline WithSampleCountMatcher WithSampleCount(size_t sampleCount) {
128*38e8c45fSAndroid Build Coastguard Worker     return WithSampleCountMatcher(sampleCount);
129*38e8c45fSAndroid Build Coastguard Worker }
130*38e8c45fSAndroid Build Coastguard Worker 
131*38e8c45fSAndroid Build Coastguard Worker class WithSampleMatcher {
132*38e8c45fSAndroid Build Coastguard Worker public:
133*38e8c45fSAndroid Build Coastguard Worker     using is_gtest_matcher = void;
WithSampleMatcher(size_t sampleIndex,const Sample & sample)134*38e8c45fSAndroid Build Coastguard Worker     explicit WithSampleMatcher(size_t sampleIndex, const Sample& sample)
135*38e8c45fSAndroid Build Coastguard Worker           : mSampleIndex{sampleIndex}, mSample{sample} {}
136*38e8c45fSAndroid Build Coastguard Worker 
MatchAndExplain(const MotionEvent & motionEvent,std::ostream * os)137*38e8c45fSAndroid Build Coastguard Worker     bool MatchAndExplain(const MotionEvent& motionEvent, std::ostream* os) const {
138*38e8c45fSAndroid Build Coastguard Worker         if (motionEvent.getHistorySize() < mSampleIndex) {
139*38e8c45fSAndroid Build Coastguard Worker             *os << "sample index out of bounds";
140*38e8c45fSAndroid Build Coastguard Worker             return false;
141*38e8c45fSAndroid Build Coastguard Worker         }
142*38e8c45fSAndroid Build Coastguard Worker 
143*38e8c45fSAndroid Build Coastguard Worker         if (motionEvent.getHistoricalEventTime(mSampleIndex) != mSample.eventTime.count()) {
144*38e8c45fSAndroid Build Coastguard Worker             *os << "event time mismatch. sample: "
145*38e8c45fSAndroid Build Coastguard Worker                 << motionEvent.getHistoricalEventTime(mSampleIndex)
146*38e8c45fSAndroid Build Coastguard Worker                 << " expected: " << mSample.eventTime.count();
147*38e8c45fSAndroid Build Coastguard Worker             return false;
148*38e8c45fSAndroid Build Coastguard Worker         }
149*38e8c45fSAndroid Build Coastguard Worker 
150*38e8c45fSAndroid Build Coastguard Worker         if (motionEvent.getPointerCount() != mSample.pointers.size()) {
151*38e8c45fSAndroid Build Coastguard Worker             *os << "pointer count mismatch. sample: " << motionEvent.getPointerCount()
152*38e8c45fSAndroid Build Coastguard Worker                 << " expected: " << mSample.pointers.size();
153*38e8c45fSAndroid Build Coastguard Worker             return false;
154*38e8c45fSAndroid Build Coastguard Worker         }
155*38e8c45fSAndroid Build Coastguard Worker 
156*38e8c45fSAndroid Build Coastguard Worker         for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
157*38e8c45fSAndroid Build Coastguard Worker              ++pointerIndex) {
158*38e8c45fSAndroid Build Coastguard Worker             const PointerCoords& pointerCoords =
159*38e8c45fSAndroid Build Coastguard Worker                     *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
160*38e8c45fSAndroid Build Coastguard Worker 
161*38e8c45fSAndroid Build Coastguard Worker             if ((std::abs(pointerCoords.getX() - mSample.pointers[pointerIndex].x) >
162*38e8c45fSAndroid Build Coastguard Worker                  MotionEvent::ROUNDING_PRECISION) ||
163*38e8c45fSAndroid Build Coastguard Worker                 (std::abs(pointerCoords.getY() - mSample.pointers[pointerIndex].y) >
164*38e8c45fSAndroid Build Coastguard Worker                  MotionEvent::ROUNDING_PRECISION)) {
165*38e8c45fSAndroid Build Coastguard Worker                 *os << "sample coordinates mismatch at pointer index " << pointerIndex
166*38e8c45fSAndroid Build Coastguard Worker                     << ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
167*38e8c45fSAndroid Build Coastguard Worker                     << ") expected: (" << mSample.pointers[pointerIndex].x << ", "
168*38e8c45fSAndroid Build Coastguard Worker                     << mSample.pointers[pointerIndex].y << ")";
169*38e8c45fSAndroid Build Coastguard Worker                 return false;
170*38e8c45fSAndroid Build Coastguard Worker             }
171*38e8c45fSAndroid Build Coastguard Worker 
172*38e8c45fSAndroid Build Coastguard Worker             if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
173*38e8c45fSAndroid Build Coastguard Worker                 mSample.pointers[pointerIndex].isResampled) {
174*38e8c45fSAndroid Build Coastguard Worker                 *os << "resampling flag mismatch. sample: "
175*38e8c45fSAndroid Build Coastguard Worker                     << motionEvent.isResampled(pointerIndex, mSampleIndex)
176*38e8c45fSAndroid Build Coastguard Worker                     << " expected: " << mSample.pointers[pointerIndex].isResampled;
177*38e8c45fSAndroid Build Coastguard Worker                 return false;
178*38e8c45fSAndroid Build Coastguard Worker             }
179*38e8c45fSAndroid Build Coastguard Worker         }
180*38e8c45fSAndroid Build Coastguard Worker         return true;
181*38e8c45fSAndroid Build Coastguard Worker     }
182*38e8c45fSAndroid Build Coastguard Worker 
DescribeTo(std::ostream * os)183*38e8c45fSAndroid Build Coastguard Worker     void DescribeTo(std::ostream* os) const { *os << "motion event sample properties match."; }
184*38e8c45fSAndroid Build Coastguard Worker 
DescribeNegationTo(std::ostream * os)185*38e8c45fSAndroid Build Coastguard Worker     void DescribeNegationTo(std::ostream* os) const {
186*38e8c45fSAndroid Build Coastguard Worker         *os << "motion event sample properties do not match expected properties.";
187*38e8c45fSAndroid Build Coastguard Worker     }
188*38e8c45fSAndroid Build Coastguard Worker 
189*38e8c45fSAndroid Build Coastguard Worker private:
190*38e8c45fSAndroid Build Coastguard Worker     const size_t mSampleIndex;
191*38e8c45fSAndroid Build Coastguard Worker     const Sample mSample;
192*38e8c45fSAndroid Build Coastguard Worker };
193*38e8c45fSAndroid Build Coastguard Worker 
WithSample(size_t sampleIndex,const Sample & sample)194*38e8c45fSAndroid Build Coastguard Worker inline WithSampleMatcher WithSample(size_t sampleIndex, const Sample& sample) {
195*38e8c45fSAndroid Build Coastguard Worker     return WithSampleMatcher(sampleIndex, sample);
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker } // namespace android
199