Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a627330f authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Automerger Merge Worker
Browse files

Merge "Add a unit test for TouchpadInputMapper" into udc-dev am: 1930f60d

parents b5351775 1930f60d
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -242,6 +242,19 @@ enum class ToolType {
    ftl_last = PALM,
    ftl_last = PALM,
};
};


/**
 * The state of the key. This should have 1:1 correspondence with the values of anonymous enum
 * defined in input.h
 */
enum class KeyState {
    UNKNOWN = AKEY_STATE_UNKNOWN,
    UP = AKEY_STATE_UP,
    DOWN = AKEY_STATE_DOWN,
    VIRTUAL = AKEY_STATE_VIRTUAL,
    ftl_first = UNKNOWN,
    ftl_last = VIRTUAL,
};

bool isStylusToolType(ToolType toolType);
bool isStylusToolType(ToolType toolType);


/*
/*
+2 −0
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ cc_test {
        "AnrTracker_test.cpp",
        "AnrTracker_test.cpp",
        "BlockingQueue_test.cpp",
        "BlockingQueue_test.cpp",
        "CapturedTouchpadEventConverter_test.cpp",
        "CapturedTouchpadEventConverter_test.cpp",
        "CursorInputMapper_test.cpp",
        "EventHub_test.cpp",
        "EventHub_test.cpp",
        "FakeEventHub.cpp",
        "FakeEventHub.cpp",
        "FakeInputReaderPolicy.cpp",
        "FakeInputReaderPolicy.cpp",
@@ -58,6 +59,7 @@ cc_test {
        "PreferStylusOverTouch_test.cpp",
        "PreferStylusOverTouch_test.cpp",
        "PropertyProvider_test.cpp",
        "PropertyProvider_test.cpp",
        "TestInputListener.cpp",
        "TestInputListener.cpp",
        "TouchpadInputMapper_test.cpp",
        "UinputDevice.cpp",
        "UinputDevice.cpp",
        "UnwantedInteractionBlocker_test.cpp",
        "UnwantedInteractionBlocker_test.cpp",
    ],
    ],
+105 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CursorInputMapper.h"

#include <android-base/logging.h>
#include <gtest/gtest.h>

#include "FakePointerController.h"
#include "InputMapperTest.h"
#include "InterfaceMocks.h"
#include "TestInputListenerMatchers.h"

#define TAG "CursorInputMapper_test"

namespace android {

using testing::Return;
using testing::VariantWith;
constexpr auto ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
constexpr auto ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
constexpr auto ACTION_UP = AMOTION_EVENT_ACTION_UP;
constexpr auto BUTTON_PRESS = AMOTION_EVENT_ACTION_BUTTON_PRESS;
constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;

/**
 * Unit tests for CursorInputMapper.
 * This class is named 'CursorInputMapperUnitTest' to avoid name collision with the existing
 * 'CursorInputMapperTest'. If all of the CursorInputMapper tests are migrated here, the name
 * can be simplified to 'CursorInputMapperTest'.
 * TODO(b/283812079): move CursorInputMapper tests here.
 */
class CursorInputMapperUnitTest : public InputMapperUnitTest {
protected:
    void SetUp() override {
        InputMapperUnitTest::SetUp();

        // Current scan code state - all keys are UP by default
        setScanCodeState(KeyState::UP,
                         {BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_BACK, BTN_SIDE, BTN_FORWARD,
                          BTN_EXTRA, BTN_TASK});
        EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL))
                .WillRepeatedly(Return(false));
        EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL))
                .WillRepeatedly(Return(false));

        EXPECT_CALL(mMockInputReaderContext, bumpGeneration()).WillRepeatedly(Return(1));

        mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
    }
};

/**
 * Move the mouse and then click the button. Check whether HOVER_EXIT is generated when hovering
 * ends. Currently, it is not.
 */
TEST_F(CursorInputMapperUnitTest, HoverAndLeftButtonPress) {
    std::list<NotifyArgs> args;

    // Move the cursor a little
    args += process(EV_REL, REL_X, 10);
    args += process(EV_REL, REL_Y, 20);
    args += process(EV_SYN, SYN_REPORT, 0);
    ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));

    // Now click the mouse button
    args.clear();
    args += process(EV_KEY, BTN_LEFT, 1);
    args += process(EV_SYN, SYN_REPORT, 0);
    ASSERT_THAT(args,
                ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
                            VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));

    // Move some more.
    args.clear();
    args += process(EV_REL, REL_X, 10);
    args += process(EV_REL, REL_Y, 20);
    args += process(EV_SYN, SYN_REPORT, 0);
    ASSERT_THAT(args, ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE))));

    // Release the button
    args.clear();
    args += process(EV_KEY, BTN_LEFT, 0);
    args += process(EV_SYN, SYN_REPORT, 0);
    ASSERT_THAT(args,
                ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
                            VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
                            VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
}

} // namespace android
+68 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,74 @@


namespace android {
namespace android {


using testing::Return;

void InputMapperUnitTest::SetUp() {
    mFakePointerController = std::make_shared<FakePointerController>();
    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
    mFakePointerController->setPosition(400, 240);

    EXPECT_CALL(mMockInputReaderContext, getPointerController(DEVICE_ID))
            .WillRepeatedly(Return(mFakePointerController));

    EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub));
    InputDeviceIdentifier identifier;
    identifier.name = "device";
    identifier.location = "USB1";
    identifier.bus = 0;

    EXPECT_CALL(mMockEventHub, getDeviceIdentifier(EVENTHUB_ID)).WillRepeatedly(Return(identifier));
    mDevice = std::make_unique<InputDevice>(&mMockInputReaderContext, DEVICE_ID,
                                            /*generation=*/2, identifier);
    mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID);
}

void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max,
                                    int32_t resolution) {
    EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_))
            .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) {
                outAxisInfo->valid = valid;
                outAxisInfo->minValue = min;
                outAxisInfo->maxValue = max;
                outAxisInfo->flat = 0;
                outAxisInfo->fuzz = 0;
                outAxisInfo->resolution = resolution;
                return valid ? OK : -1;
            });
}

void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) {
    for (const auto& scanCode : scanCodes) {
        EXPECT_CALL(mMockEventHub, hasScanCode(EVENTHUB_ID, scanCode))
                .WillRepeatedly(testing::Return(present));
    }
}

void InputMapperUnitTest::setScanCodeState(KeyState state, std::set<int> scanCodes) {
    for (const auto& scanCode : scanCodes) {
        EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, scanCode))
                .WillRepeatedly(testing::Return(static_cast<int>(state)));
    }
}

void InputMapperUnitTest::setKeyCodeState(KeyState state, std::set<int> keyCodes) {
    for (const auto& keyCode : keyCodes) {
        EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, keyCode))
                .WillRepeatedly(testing::Return(static_cast<int>(state)));
    }
}

std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) {
    RawEvent event;
    event.when = systemTime(SYSTEM_TIME_MONOTONIC);
    event.readTime = event.when;
    event.deviceId = mMapper->getDeviceContext().getEventHubId();
    event.type = type;
    event.code = code;
    event.value = value;
    return mMapper->process(&event);
}

const char* InputMapperTest::DEVICE_NAME = "device";
const char* InputMapperTest::DEVICE_NAME = "device";
const char* InputMapperTest::DEVICE_LOCATION = "USB1";
const char* InputMapperTest::DEVICE_LOCATION = "USB1";
const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
+32 −0
Original line number Original line Diff line number Diff line
@@ -23,16 +23,48 @@
#include <InputMapper.h>
#include <InputMapper.h>
#include <NotifyArgs.h>
#include <NotifyArgs.h>
#include <ftl/flags.h>
#include <ftl/flags.h>
#include <gmock/gmock.h>
#include <utils/StrongPointer.h>
#include <utils/StrongPointer.h>


#include "FakeEventHub.h"
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
#include "FakeInputReaderPolicy.h"
#include "InstrumentedInputReader.h"
#include "InstrumentedInputReader.h"
#include "InterfaceMocks.h"
#include "TestConstants.h"
#include "TestConstants.h"
#include "TestInputListener.h"
#include "TestInputListener.h"


namespace android {
namespace android {


class InputMapperUnitTest : public testing::Test {
protected:
    static constexpr int32_t EVENTHUB_ID = 1;
    static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
    virtual void SetUp() override;

    void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution);

    void expectScanCodes(bool present, std::set<int> scanCodes);

    void setScanCodeState(KeyState state, std::set<int> scanCodes);

    void setKeyCodeState(KeyState state, std::set<int> keyCodes);

    std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value);

    MockEventHubInterface mMockEventHub;
    std::shared_ptr<FakePointerController> mFakePointerController;
    MockInputReaderContext mMockInputReaderContext;
    std::unique_ptr<InputDevice> mDevice;

    std::unique_ptr<InputDeviceContext> mDeviceContext;
    InputReaderConfiguration mReaderConfiguration;
    // The mapper should be created by the subclasses.
    std::unique_ptr<InputMapper> mMapper;
};

/**
 * Deprecated - use InputMapperUnitTest instead.
 */
class InputMapperTest : public testing::Test {
class InputMapperTest : public testing::Test {
protected:
protected:
    static const char* DEVICE_NAME;
    static const char* DEVICE_NAME;
Loading