Initial InputMappers for evdev input HAL.
The previous design of the InputHost wrapper classes made it very
painful to do testing, so this change also reverts to a more classical
C++ pattern for non-copyable objects. The InputHost classes still simply
call through to the input_host_t and callbacks as before.
Updated unittests to use gmock for mocking the InputHost interactions.
Change-Id: I4b70df2c89ed48af77446b8f5b87a4bde94510bf
diff --git a/tests/input/evdev/Android.mk b/tests/input/evdev/Android.mk
index 544e5a8..a79de34 100644
--- a/tests/input/evdev/Android.mk
+++ b/tests/input/evdev/Android.mk
@@ -2,13 +2,17 @@
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += hardware/libhardware/modules/input/evdev
+LOCAL_C_INCLUDES += $(TOP)/external/gmock/include
LOCAL_SRC_FILES:= \
InputDevice_test.cpp \
InputHub_test.cpp \
InputMocks.cpp \
+ SwitchInputMapper_test.cpp \
TestHelpers.cpp
+LOCAL_STATIC_LIBRARIES := libgmock
+
LOCAL_SHARED_LIBRARIES := \
libinput_evdev \
liblog \
diff --git a/tests/input/evdev/InputDevice_test.cpp b/tests/input/evdev/InputDevice_test.cpp
index 123f2b8..bed05b8 100644
--- a/tests/input/evdev/InputDevice_test.cpp
+++ b/tests/input/evdev/InputDevice_test.cpp
@@ -26,9 +26,9 @@
#include <utils/Timers.h>
#include "InputDevice.h"
-#include "InputHost.h"
#include "InputHub.h"
#include "InputMocks.h"
+#include "MockInputHost.h"
// # of milliseconds to allow for timing measurements
#define TIMING_TOLERANCE_MS 25
@@ -36,26 +36,41 @@
#define MSC_ANDROID_TIME_SEC 0x6
#define MSC_ANDROID_TIME_USEC 0x7
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnNull;
+
namespace android {
namespace tests {
class EvdevDeviceTest : public ::testing::Test {
protected:
- virtual void SetUp() override {
- mMockHost.reset(new MockInputHost());
- }
+ virtual void SetUp() {
+ // Creating device identifiers and definitions should always happen.
+ EXPECT_CALL(mHost, createDeviceIdentifier(_, _, _, _, _))
+ .WillOnce(ReturnNull());
+ EXPECT_CALL(mHost, createDeviceDefinition())
+ .WillOnce(Return(&mDeviceDef));
+ // InputMappers may cause any of these to be called, but we are not
+ // testing these here.
+ ON_CALL(mHost, createInputReportDefinition())
+ .WillByDefault(Return(&mReportDef));
+ ON_CALL(mHost, createOutputReportDefinition())
+ .WillByDefault(Return(&mReportDef));
+ ON_CALL(mHost, registerDevice(_, _))
+ .WillByDefault(ReturnNull());
+ }
- virtual void TearDown() override {
- ASSERT_TRUE(mMockHost->checkAllocations());
- }
-
- std::unique_ptr<MockInputHost> mMockHost;
+ MockInputHost mHost;
+ // Ignore uninteresting calls on the report definitions by using NiceMocks.
+ NiceMock<MockInputReportDefinition> mReportDef;
+ NiceMock<MockInputDeviceDefinition> mDeviceDef;
};
TEST_F(EvdevDeviceTest, testOverrideTime) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
ASSERT_TRUE(device != nullptr);
// Send two timestamp override events before an input event.
@@ -83,9 +98,8 @@
}
TEST_F(EvdevDeviceTest, testWrongClockCorrection) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
ASSERT_TRUE(device != nullptr);
auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -100,9 +114,8 @@
}
TEST_F(EvdevDeviceTest, testClockCorrectionOk) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::make_shared<MockInputDeviceNode>();
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
ASSERT_TRUE(device != nullptr);
auto now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -118,68 +131,70 @@
}
TEST_F(EvdevDeviceTest, testN7v2Touchscreen) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getElanTouchscreen());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_TOUCH|INPUT_DEVICE_CLASS_TOUCH_MT,
device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testN7v2ButtonJack) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getButtonJack());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testN7v2HeadsetJack) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
+ // Eventually these mock device tests will all expect these calls. For now
+ // only the SwitchInputMapper has been implemented.
+ // TODO: move this expectation out to a common function
+ EXPECT_CALL(mHost, createInputReportDefinition());
+ EXPECT_CALL(mHost, registerDevice(_, _));
+
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getHeadsetJack());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_SWITCH, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testN7v2H2wButton) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getH2wButton());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testN7v2GpioKeys) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getGpioKeys());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testNexusPlayerGpioKeys) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getGpioKeys());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testNexusPlayerMidPowerBtn) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getMidPowerBtn());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testNexusRemote) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getNexusRemote());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
TEST_F(EvdevDeviceTest, testAsusGamepad) {
- InputHost host = {mMockHost.get(), kTestCallbacks};
auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getAsusGamepad());
- auto device = std::make_unique<EvdevDevice>(host, node);
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
EXPECT_EQ(INPUT_DEVICE_CLASS_JOYSTICK|INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}
+TEST_F(EvdevDeviceTest, testMocks) {
+ auto node = std::make_shared<MockInputDeviceNode>();
+ auto device = std::make_unique<EvdevDevice>(&mHost, node);
+}
+
} // namespace tests
} // namespace android
diff --git a/tests/input/evdev/InputMocks.cpp b/tests/input/evdev/InputMocks.cpp
index c316075..f4a341a 100644
--- a/tests/input/evdev/InputMocks.cpp
+++ b/tests/input/evdev/InputMocks.cpp
@@ -1,104 +1,7 @@
#include "InputMocks.h"
-// Private test definitions of opaque HAL structs
-
-// Not used
-struct input_property_map {};
-
-// Holds the key and value from the mock host's PropertyMap
-struct input_property {
- android::String8 key;
- android::String8 value;
-};
-
namespace android {
-bool MockInputHost::checkAllocations() const {
- bool ret = true;
- if (mMapAllocations != 0) {
- ALOGE("Leaked %d device property map allocations", mMapAllocations);
- ret = false;
- }
- for (auto entry : mPropertyAllocations) {
- if (entry.second != 0) {
- ALOGE("Leaked %d property allocation for %s", entry.second, entry.first.c_str());
- ret = false;
- }
- }
- return ret;
-}
-
-input_device_identifier_t* MockInputHost::createDeviceIdentifier(
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id) {
- mDeviceId.reset(new input_device_identifier_t{
- .name = name,
- .productId = product_id,
- .vendorId = vendor_id,
- .bus = bus,
- .uniqueId = unique_id
- });
- // Just return the raw pointer. We don't have a method for deallocating
- // device identifiers yet, and they should exist throughout the lifetime of
- // the input process for now.
- return mDeviceId.get();
-}
-
-input_property_map_t* MockInputHost::getDevicePropertyMap(input_device_identifier_t* id) {
- mMapAllocations++;
- // Handled in the MockInputHost.
- return nullptr;
-}
-
-input_property_t* MockInputHost::getDeviceProperty(input_property_map_t* map, const char* key) {
- mPropertyAllocations[key]++;
- return new input_property_t{.key = String8(key)};
-}
-
-const char* MockInputHost::getPropertyKey(input_property_t* property) {
- return property->key.string();
-}
-
-const char* MockInputHost::getPropertyValue(input_property_t* property) {
- if (!mDevicePropertyMap.tryGetProperty(property->key, property->value)) {
- return nullptr;
- }
- return property->value.string();
-}
-
-void MockInputHost::freeDeviceProperty(input_property_t* property) {
- if (property != nullptr) {
- mPropertyAllocations[property->key.string()]--;
- delete property;
- }
-}
-
-void MockInputHost::freeDevicePropertyMap(input_property_map_t* map) {
- mMapAllocations--;
-}
-
-input_host_callbacks_t kTestCallbacks = {
- .create_device_identifier = create_device_identifier,
- .create_device_definition = create_device_definition,
- .create_input_report_definition = create_input_report_definition,
- .create_output_report_definition = create_output_report_definition,
- .input_device_definition_add_report = input_device_definition_add_report,
- .input_report_definition_add_collection = input_report_definition_add_collection,
- .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
- .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
- .register_device = register_device,
- .input_allocate_report = input_allocate_report,
- .input_report_set_usage_int = input_report_set_usage_int,
- .input_report_set_usage_bool = input_report_set_usage_bool,
- .report_event = report_event,
- .input_get_device_property_map = input_get_device_property_map,
- .input_get_device_property = input_get_device_property,
- .input_get_property_key = input_get_property_key,
- .input_get_property_value = input_get_property_value,
- .input_free_device_property = input_free_device_property,
- .input_free_device_property_map = input_free_device_property_map,
-};
-
bool MockInputDeviceNode::hasKeyInRange(int32_t startKey, int32_t endKey) const {
auto iter = mKeys.lower_bound(startKey);
if (iter == mKeys.end()) return false;
@@ -321,86 +224,4 @@
} // namespace MockNexusPlayer
-::input_device_identifier_t* create_device_identifier(input_host_t* host,
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
-}
-
-input_device_definition_t* create_device_definition(input_host_t* host) {
- return nullptr;
-}
-
-input_report_definition_t* create_input_report_definition(input_host_t* host) {
- return nullptr;
-}
-
-input_report_definition_t* create_output_report_definition(input_host_t* host) {
- return nullptr;
-}
-
-void input_device_definition_add_report(input_host_t* host,
- input_device_definition_t* d, input_report_definition_t* r) { }
-
-void input_report_definition_add_collection(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id, int32_t arity) { }
-
-void input_report_definition_declare_usage_int(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t usage, int32_t min, int32_t max, float resolution) { }
-
-void input_report_definition_declare_usages_bool(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t* usage, size_t usage_count) { }
-
-
-input_device_handle_t* register_device(input_host_t* host,
- input_device_identifier_t* id, input_device_definition_t* d) {
- return nullptr;
-}
-
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
- return nullptr;
-}
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
-
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
-
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) { }
-
-input_property_map_t* input_get_device_property_map(input_host_t* host,
- input_device_identifier_t* id) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->getDevicePropertyMap(id);
-}
-
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
- const char* key) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->getDeviceProperty(map, key);
-}
-
-const char* input_get_property_key(input_host_t* host, input_property_t* property) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->getPropertyKey(property);
-}
-
-const char* input_get_property_value(input_host_t* host, input_property_t* property) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->getPropertyValue(property);
-}
-
-void input_free_device_property(input_host_t* host, input_property_t* property) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->freeDeviceProperty(property);
-}
-
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
- auto mockHost = static_cast<MockInputHost*>(host);
- return mockHost->freeDevicePropertyMap(map);
-}
-
} // namespace android
diff --git a/tests/input/evdev/InputMocks.h b/tests/input/evdev/InputMocks.h
index 5c6eb80..78e0279 100644
--- a/tests/input/evdev/InputMocks.h
+++ b/tests/input/evdev/InputMocks.h
@@ -18,72 +18,15 @@
#define ANDROID_INPUT_MOCKS_H_
#include <map>
-#include <memory>
#include <set>
#include <string>
-#include <unordered_map>
#include <linux/input.h>
-#include <hardware/input.h>
-#include <utils/PropertyMap.h>
-
#include "InputHub.h"
-// Test definitions of opaque HAL structs
-struct input_host {};
-struct input_device_identifier {
- const char* name;
- const char* uniqueId;
- input_bus_t bus;
- int32_t vendorId;
- int32_t productId;
- int32_t version;
-};
-
-
namespace android {
-extern input_host_callbacks_t kTestCallbacks;
-
-class MockInputHost : public ::input_host_t {
-public:
- virtual ~MockInputHost() = default;
-
- void addDeviceProperty(const std::string& key, const std::string& value) {
- mDevicePropertyMap.addProperty(String8(key.c_str()), String8(value.c_str()));
- }
-
- /**
- * Call this at the end of a test to verify that any allocations made
- * during the test were freed.
- */
- bool checkAllocations() const;
-
- // Callbacks
- input_device_identifier_t* createDeviceIdentifier(
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id);
-
- input_property_map_t* getDevicePropertyMap(input_device_identifier_t* id);
-
- input_property_t* getDeviceProperty(input_property_map_t* map, const char* key);
-
- const char* getPropertyKey(input_property_t* property);
-
- const char* getPropertyValue(input_property_t* property);
-
- void freeDeviceProperty(input_property_t* property);
-
- void freeDevicePropertyMap(input_property_map_t* map);
-
-private:
- PropertyMap mDevicePropertyMap;
- std::unique_ptr<input_device_identifier_t> mDeviceId;
- int32_t mMapAllocations = 0;
- std::unordered_map<std::string, int32_t> mPropertyAllocations;
-};
-
class MockInputDeviceNode : public InputDeviceNode {
public:
MockInputDeviceNode() = default;
@@ -194,63 +137,6 @@
MockInputDeviceNode* getAsusGamepad();
} // namespace MockNexusPlayer
-// HAL method prototypes used in mock callbacks
-extern "C" {
-input_device_identifier_t* create_device_identifier(input_host_t* host,
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id);
-
-input_device_definition_t* create_device_definition(input_host_t* host);
-
-input_report_definition_t* create_input_report_definition(input_host_t* host);
-
-input_report_definition_t* create_output_report_definition(input_host_t* host);
-
-void input_device_definition_add_report(input_host_t* host,
- input_device_definition_t* d, input_report_definition_t* r);
-
-void input_report_definition_add_collection(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id, int32_t arity);
-
-void input_report_definition_declare_usage_int(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t usage, int32_t min, int32_t max, float resolution);
-
-void input_report_definition_declare_usages_bool(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t* usage, size_t usage_count);
-
-
-input_device_handle_t* register_device(input_host_t* host,
- input_device_identifier_t* id, input_device_definition_t* d);
-
-void unregister_device(input_host_t* host, input_device_handle_t* handle);
-
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r);
-
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index);
-
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index);
-
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report);
-
-input_property_map_t* input_get_device_property_map(input_host_t* host,
- input_device_identifier_t* id);
-
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
- const char* key);
-
-const char* input_get_property_key(input_host_t* host, input_property_t* property);
-
-const char* input_get_property_value(input_host_t* host, input_property_t* property);
-
-void input_free_device_property(input_host_t* host, input_property_t* property);
-
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map);
-} // extern "C"
-
} // namespace android
#endif // ANDROID_INPUT_MOCKS_H_
diff --git a/tests/input/evdev/MockInputHost.h b/tests/input/evdev/MockInputHost.h
new file mode 100644
index 0000000..a91f95c
--- /dev/null
+++ b/tests/input/evdev/MockInputHost.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MOCK_INPUT_HOST_H_
+#define ANDROID_MOCK_INPUT_HOST_H_
+
+#include "gmock/gmock.h"
+
+#include "InputHost.h"
+
+namespace android {
+namespace tests {
+
+class MockInputReport : public InputReport {
+public:
+ MockInputReport() : InputReport(nullptr, {}, nullptr) {}
+ MOCK_METHOD4(setIntUsage, void(InputCollectionId id, InputUsage usage, int32_t value,
+ int32_t arityIndex));
+ MOCK_METHOD4(setBoolUsage, void(InputCollectionId id, InputUsage usage, bool value,
+ int32_t arityIndex));
+ MOCK_METHOD1(reportEvent, void(InputDeviceHandle* d));
+};
+
+class MockInputReportDefinition : public InputReportDefinition {
+public:
+ MockInputReportDefinition() : InputReportDefinition(nullptr, {}, nullptr) {}
+ MOCK_METHOD2(addCollection, void(InputCollectionId id, int32_t arity));
+ MOCK_METHOD5(declareUsage, void(InputCollectionId id, InputUsage usage, int32_t min,
+ int32_t max, float resolution));
+ MOCK_METHOD3(declareUsages, void(InputCollectionId id, InputUsage* usage, size_t usageCount));
+ MOCK_METHOD0(allocateReport, InputReport*());
+};
+
+class MockInputDeviceDefinition : public InputDeviceDefinition {
+public:
+ MockInputDeviceDefinition() : InputDeviceDefinition(nullptr, {}, nullptr) {}
+ MOCK_METHOD1(addReport, void(InputReportDefinition* r));
+};
+
+class MockInputProperty : public InputProperty {
+public:
+ MockInputProperty() : InputProperty(nullptr, {}, nullptr) {}
+ virtual ~MockInputProperty() {}
+ MOCK_CONST_METHOD0(getKey, const char*());
+ MOCK_CONST_METHOD0(getValue, const char*());
+};
+
+class MockInputPropertyMap : public InputPropertyMap {
+public:
+ MockInputPropertyMap() : InputPropertyMap(nullptr, {}, nullptr) {}
+ virtual ~MockInputPropertyMap() {}
+ MOCK_CONST_METHOD1(getDeviceProperty, InputProperty*(const char* key));
+ MOCK_CONST_METHOD1(freeDeviceProperty, void(InputProperty* property));
+};
+
+class MockInputHost : public InputHostInterface {
+public:
+ MOCK_METHOD5(createDeviceIdentifier, InputDeviceIdentifier*(
+ const char* name, int32_t productId, int32_t vendorId, InputBus bus,
+ const char* uniqueId));
+ MOCK_METHOD0(createDeviceDefinition, InputDeviceDefinition*());
+ MOCK_METHOD0(createInputReportDefinition, InputReportDefinition*());
+ MOCK_METHOD0(createOutputReportDefinition, InputReportDefinition*());
+ MOCK_METHOD1(freeReportDefinition, void(InputReportDefinition* reportDef));
+ MOCK_METHOD2(registerDevice, InputDeviceHandle*(InputDeviceIdentifier* id,
+ InputDeviceDefinition* d));
+ MOCK_METHOD1(unregisterDevice, void(InputDeviceHandle* handle));
+ MOCK_METHOD1(getDevicePropertyMap, InputPropertyMap*(InputDeviceIdentifier* id));
+ MOCK_METHOD1(freeDevicePropertyMap, void(InputPropertyMap* propertyMap));
+};
+
+} // namespace tests
+} // namespace android
+
+#endif // ANDROID_MOCK_INPUT_HOST_H_
diff --git a/tests/input/evdev/SwitchInputMapper_test.cpp b/tests/input/evdev/SwitchInputMapper_test.cpp
new file mode 100644
index 0000000..f93041b
--- /dev/null
+++ b/tests/input/evdev/SwitchInputMapper_test.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 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 <memory>
+
+#include <linux/input.h>
+
+#include <gtest/gtest.h>
+
+#include "InputMocks.h"
+#include "MockInputHost.h"
+#include "SwitchInputMapper.h"
+
+using ::testing::_;
+using ::testing::Args;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::UnorderedElementsAre;
+
+namespace android {
+namespace tests {
+
+class SwitchInputMapperTest : public ::testing::Test {
+protected:
+ virtual void SetUp() override {
+ mMapper = std::make_unique<SwitchInputMapper>();
+ }
+
+ MockInputHost mHost;
+ std::unique_ptr<SwitchInputMapper> mMapper;
+};
+
+TEST_F(SwitchInputMapperTest, testConfigureDevice) {
+ MockInputReportDefinition reportDef;
+ MockInputDeviceNode deviceNode;
+ deviceNode.addSwitch(SW_LID);
+ deviceNode.addSwitch(SW_CAMERA_LENS_COVER);
+
+ EXPECT_CALL(reportDef, addCollection(INPUT_COLLECTION_ID_SWITCH, 1));
+ EXPECT_CALL(reportDef, declareUsages(INPUT_COLLECTION_ID_SWITCH, _, 2))
+ .With(Args<1,2>(UnorderedElementsAre(INPUT_USAGE_SWITCH_LID,
+ INPUT_USAGE_SWITCH_CAMERA_LENS_COVER)));
+
+ mMapper->configureInputReport(&deviceNode, &reportDef);
+}
+
+TEST_F(SwitchInputMapperTest, testConfigureDevice_noSwitches) {
+ MockInputReportDefinition reportDef;
+ MockInputDeviceNode deviceNode;
+
+ EXPECT_CALL(reportDef, addCollection(_, _)).Times(0);
+ EXPECT_CALL(reportDef, declareUsages(_, _, _)).Times(0);
+
+ mMapper->configureInputReport(&deviceNode, &reportDef);
+}
+
+TEST_F(SwitchInputMapperTest, testProcessInput) {
+ MockInputReportDefinition reportDef;
+ MockInputDeviceNode deviceNode;
+ deviceNode.addSwitch(SW_LID);
+
+ EXPECT_CALL(reportDef, addCollection(_, _));
+ EXPECT_CALL(reportDef, declareUsages(_, _, _));
+
+ mMapper->configureInputReport(&deviceNode, &reportDef);
+
+ MockInputReport report;
+ EXPECT_CALL(reportDef, allocateReport())
+ .WillOnce(Return(&report));
+
+ {
+ // Test two switch events in order
+ InSequence s;
+ EXPECT_CALL(report, setBoolUsage(INPUT_COLLECTION_ID_SWITCH, INPUT_USAGE_SWITCH_LID, 1, 0));
+ EXPECT_CALL(report, reportEvent(_));
+ EXPECT_CALL(report, setBoolUsage(INPUT_COLLECTION_ID_SWITCH, INPUT_USAGE_SWITCH_LID, 0, 0));
+ EXPECT_CALL(report, reportEvent(_));
+ }
+
+ InputEvent events[] = {
+ {0, EV_SW, SW_LID, 1},
+ {1, EV_SYN, SYN_REPORT, 0},
+ {2, EV_SW, SW_LID, 0},
+ {3, EV_SYN, SYN_REPORT, 0},
+ };
+ for (auto e : events) {
+ mMapper->process(e);
+ }
+}
+
+} // namespace tests
+} // namespace android
+