#include "gtest/gtest.h" #define FASTMOUSE_IMPL #include "fastmouse.h" #undef FASTMOUSE_IMPL #include // Wrappers to avoid specifying params we do not use here. static void input_emit() { fastmouse_input_emit(nullptr); } static void input_event(movement_type m, const int value) { input_event_fastmouse_log(nullptr, EV_REL, m, value); } class FastmouseTest : public ::testing::Test { protected: void SetUp() override { static auto fp = fastmouse; static auto mp = movement; fastmouse = fp; movement = mp; } }; TEST_F(FastmouseTest, test_noop) { EXPECT_EQ(movement.x, 0); EXPECT_EQ(movement.y, 0); input_event(REL_X, 1); input_event(REL_Y, 1); input_emit(); EXPECT_EQ(movement.x, 1); EXPECT_EQ(movement.y, 1); } TEST_F(FastmouseTest, simple_division) { fastmouse.division = 2; input_event(REL_X, 1); input_emit(); EXPECT_EQ(movement.x, 0); EXPECT_EQ(movement.y, 0); // 'Loss of 'precision' shows immediately here, it's not a big issue that the first // two dots do not emit an event, it only occurs again after the next INT_MAX dots. // All tests will exhibit this behaviour where the first division dots do not emit an event // as expected unless INT_MAX % division == 0. // We do not actually lose precision, it's just that we can only emit events in // discreet intervals. input_event(REL_X, 2); input_emit(); EXPECT_EQ(movement.x, 1); EXPECT_EQ(movement.y, 0); input_event(REL_Y, 3); input_emit(); EXPECT_EQ(movement.x, 1); EXPECT_EQ(movement.y, 1); } TEST_F(FastmouseTest, high_division) { fastmouse.division = 20; for (auto i = 0; i < 20; ++i) { input_event(REL_X, 1); input_emit(); EXPECT_EQ(movement.x, 0); EXPECT_EQ(movement.y, 0); } input_event(REL_X, 1); input_emit(); EXPECT_EQ(movement.x, 1); } TEST_F(FastmouseTest, different_axis_division) { fastmouse.division = 10; input_event(REL_X, 201); input_event(REL_Y, 51); input_emit(); EXPECT_EQ(movement.x, 20); EXPECT_EQ(movement.y, 5); } TEST_F(FastmouseTest, simple_rotation) { // scripts/set_rotation.sh 45 fastmouse.rise = 1518500249; fastmouse.run = 1518500249; input_event(REL_X, 10'000); input_emit(); EXPECT_EQ(movement.x, 7071); EXPECT_EQ(movement.y, 7071); // It's important we do not add distance when calculating rotation! EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 9999); } TEST_F(FastmouseTest, simple_y_rotation) { // scripts/set_rotation.sh 45 fastmouse.rise = 1518500249; fastmouse.run = 1518500249; input_event(REL_Y, 10'000); input_emit(); EXPECT_EQ(movement.x, -7071); EXPECT_EQ(movement.y, 7071); EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 9999); } TEST_F(FastmouseTest, negative_rotation) { // scripts/set_rotation.sh -120 fastmouse.rise = -1859775393; fastmouse.run = -1073741824; input_event(REL_X, 500); input_emit(); EXPECT_EQ(movement.x, -250); EXPECT_EQ(movement.y, -433); EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 499); } TEST_F(FastmouseTest, inversion_rotation) { // scripts/set_rotation.sh 180 fastmouse.rise = 0; fastmouse.run = -2147483648; input_event(REL_X, 500); input_emit(); EXPECT_EQ(movement.x, -500); EXPECT_EQ(movement.y, 0); EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 500); } TEST_F(FastmouseTest, sideways_rotation) { // scripts/set_rotation.sh 90 fastmouse.rise = 2147483647; fastmouse.run = 0; input_event(REL_X, 500); input_emit(); EXPECT_EQ(movement.x, 0); EXPECT_EQ(movement.y, 500); EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 500); } TEST_F(FastmouseTest, rotation_with_division) { fastmouse.division = 10; // scripts/set_rotation.sh 10 fastmouse.rise = 372906621; fastmouse.run = 2114858545; input_event(REL_X, 100'000); input_emit(); EXPECT_EQ(movement.x, 9848); EXPECT_EQ(movement.y, 1736); EXPECT_EQ(static_cast(std::sqrt(movement.x * movement.x + movement.y * movement.y)), 9999); }