diff options
29 files changed, 917 insertions, 0 deletions
diff --git a/builddefs/build_full_test.mk b/builddefs/build_full_test.mk index 63f9fea915..5cae327c6c 100644 --- a/builddefs/build_full_test.mk +++ b/builddefs/build_full_test.mk | |||
| @@ -21,8 +21,10 @@ $(TEST_OUTPUT)_SRC := \ | |||
| 21 | $(SRC) \ | 21 | $(SRC) \ |
| 22 | $(QUANTUM_PATH)/keymap_introspection.c \ | 22 | $(QUANTUM_PATH)/keymap_introspection.c \ |
| 23 | tests/test_common/matrix.c \ | 23 | tests/test_common/matrix.c \ |
| 24 | tests/test_common/pointing_device_driver.c \ | ||
| 24 | tests/test_common/test_driver.cpp \ | 25 | tests/test_common/test_driver.cpp \ |
| 25 | tests/test_common/keyboard_report_util.cpp \ | 26 | tests/test_common/keyboard_report_util.cpp \ |
| 27 | tests/test_common/mouse_report_util.cpp \ | ||
| 26 | tests/test_common/keycode_util.cpp \ | 28 | tests/test_common/keycode_util.cpp \ |
| 27 | tests/test_common/keycode_table.cpp \ | 29 | tests/test_common/keycode_table.cpp \ |
| 28 | tests/test_common/test_fixture.cpp \ | 30 | tests/test_common/test_fixture.cpp \ |
diff --git a/tests/mousekeys/config.h b/tests/mousekeys/config.h new file mode 100644 index 0000000000..76bbbe8dae --- /dev/null +++ b/tests/mousekeys/config.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
diff --git a/tests/mousekeys/test.mk b/tests/mousekeys/test.mk new file mode 100644 index 0000000000..6c605daecf --- /dev/null +++ b/tests/mousekeys/test.mk | |||
| @@ -0,0 +1 @@ | |||
| MOUSEKEY_ENABLE = yes | |||
diff --git a/tests/mousekeys/test_mousekeys.cpp b/tests/mousekeys/test_mousekeys.cpp new file mode 100644 index 0000000000..a1b8e06cf7 --- /dev/null +++ b/tests/mousekeys/test_mousekeys.cpp | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | |||
| 8 | using testing::_; | ||
| 9 | |||
| 10 | struct MouseKeyExpectations { | ||
| 11 | int16_t x; | ||
| 12 | int16_t y; | ||
| 13 | int16_t h; | ||
| 14 | int16_t v; | ||
| 15 | uint16_t button_mask; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Mousekey : public TestFixture {}; | ||
| 19 | class MousekeyParametrized : public ::testing::WithParamInterface<std::pair<KeymapKey, MouseKeyExpectations>>, public Mousekey {}; | ||
| 20 | |||
| 21 | TEST_F(Mousekey, SendMouseNotCalledWhenNoKeyIsPressed) { | ||
| 22 | TestDriver driver; | ||
| 23 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 24 | run_one_scan_loop(); | ||
| 25 | } | ||
| 26 | |||
| 27 | TEST_F(Mousekey, PressAndHoldCursorUpIsCorrectlyReported) { | ||
| 28 | TestDriver driver; | ||
| 29 | KeymapKey mouse_key = KeymapKey{0, 0, 0, QK_MOUSE_CURSOR_UP}; | ||
| 30 | |||
| 31 | set_keymap({mouse_key}); | ||
| 32 | |||
| 33 | EXPECT_MOUSE_REPORT(driver, (0, -8, 0, 0, 0)); | ||
| 34 | mouse_key.press(); | ||
| 35 | run_one_scan_loop(); | ||
| 36 | |||
| 37 | EXPECT_MOUSE_REPORT(driver, (0, -2, 0, 0, 0)); | ||
| 38 | idle_for(MOUSEKEY_INTERVAL); | ||
| 39 | |||
| 40 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 41 | mouse_key.release(); | ||
| 42 | run_one_scan_loop(); | ||
| 43 | |||
| 44 | VERIFY_AND_CLEAR(driver); | ||
| 45 | } | ||
| 46 | |||
| 47 | TEST_F(Mousekey, PressAndHoldButtonOneCorrectlyReported) { | ||
| 48 | TestDriver driver; | ||
| 49 | KeymapKey mouse_key = KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_1}; | ||
| 50 | |||
| 51 | set_keymap({mouse_key}); | ||
| 52 | |||
| 53 | EXPECT_MOUSE_REPORT(driver, (0, 0, 0, 0, 1)); | ||
| 54 | mouse_key.press(); | ||
| 55 | run_one_scan_loop(); | ||
| 56 | |||
| 57 | idle_for(MOUSEKEY_INTERVAL); | ||
| 58 | |||
| 59 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 60 | mouse_key.release(); | ||
| 61 | run_one_scan_loop(); | ||
| 62 | |||
| 63 | VERIFY_AND_CLEAR(driver); | ||
| 64 | } | ||
| 65 | |||
| 66 | TEST_P(MousekeyParametrized, PressAndReleaseIsCorrectlyReported) { | ||
| 67 | TestDriver driver; | ||
| 68 | KeymapKey mouse_key = GetParam().first; | ||
| 69 | MouseKeyExpectations expectations = GetParam().second; | ||
| 70 | |||
| 71 | set_keymap({mouse_key}); | ||
| 72 | |||
| 73 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, expectations.button_mask)); | ||
| 74 | mouse_key.press(); | ||
| 75 | run_one_scan_loop(); | ||
| 76 | |||
| 77 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 78 | mouse_key.release(); | ||
| 79 | run_one_scan_loop(); | ||
| 80 | |||
| 81 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 82 | run_one_scan_loop(); | ||
| 83 | |||
| 84 | VERIFY_AND_CLEAR(driver); | ||
| 85 | } | ||
| 86 | // clang-format off | ||
| 87 | INSTANTIATE_TEST_CASE_P( | ||
| 88 | Keys, | ||
| 89 | MousekeyParametrized, | ||
| 90 | ::testing::Values( | ||
| 91 | // Key , X, Y, H, V, Buttons Mask | ||
| 92 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_1}, MouseKeyExpectations{ 0, 0, 0, 0, 1}), | ||
| 93 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_2}, MouseKeyExpectations{ 0, 0, 0, 0, 2}), | ||
| 94 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_3}, MouseKeyExpectations{ 0, 0, 0, 0, 4}), | ||
| 95 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_4}, MouseKeyExpectations{ 0, 0, 0, 0, 8}), | ||
| 96 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_5}, MouseKeyExpectations{ 0, 0, 0, 0, 16}), | ||
| 97 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_6}, MouseKeyExpectations{ 0, 0, 0, 0, 32}), | ||
| 98 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_7}, MouseKeyExpectations{ 0, 0, 0, 0, 64}), | ||
| 99 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_8}, MouseKeyExpectations{ 0, 0, 0, 0, 128}), | ||
| 100 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_CURSOR_UP}, MouseKeyExpectations{ 0,-8, 0, 0, 0}), | ||
| 101 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_CURSOR_DOWN}, MouseKeyExpectations{ 0, 8, 0, 0, 0}), | ||
| 102 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_CURSOR_LEFT}, MouseKeyExpectations{-8, 0, 0, 0, 0}), | ||
| 103 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_CURSOR_RIGHT}, MouseKeyExpectations{ 8, 0, 0, 0, 0}), | ||
| 104 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_WHEEL_UP}, MouseKeyExpectations{ 0, 0, 0, 1, 0}), | ||
| 105 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_WHEEL_DOWN}, MouseKeyExpectations{ 0, 0, 0,-1, 0}), | ||
| 106 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_WHEEL_LEFT}, MouseKeyExpectations{ 0, 0,-1, 0, 0}), | ||
| 107 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_WHEEL_RIGHT}, MouseKeyExpectations{ 0, 0, 1, 0, 0}) | ||
| 108 | )); | ||
| 109 | // clang-format on | ||
diff --git a/tests/pointing/config.h b/tests/pointing/config.h new file mode 100644 index 0000000000..76bbbe8dae --- /dev/null +++ b/tests/pointing/config.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
diff --git a/tests/pointing/invertandrotate/config.h b/tests/pointing/invertandrotate/config.h new file mode 100644 index 0000000000..a3f3df7a54 --- /dev/null +++ b/tests/pointing/invertandrotate/config.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
| 7 | |||
| 8 | #define POINTING_DEVICE_INVERT_X | ||
| 9 | #define POINTING_DEVICE_ROTATION_90 | ||
diff --git a/tests/pointing/invertandrotate/test.mk b/tests/pointing/invertandrotate/test.mk new file mode 100644 index 0000000000..ba224d74f0 --- /dev/null +++ b/tests/pointing/invertandrotate/test.mk | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | POINTING_DEVICE_DRIVER = custom | ||
diff --git a/tests/pointing/invertandrotate/test_invertandrotate.cpp b/tests/pointing/invertandrotate/test_invertandrotate.cpp new file mode 100644 index 0000000000..b47739f415 --- /dev/null +++ b/tests/pointing/invertandrotate/test_invertandrotate.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | |||
| 9 | using testing::_; | ||
| 10 | |||
| 11 | struct SimpleReport { | ||
| 12 | int16_t x; | ||
| 13 | int16_t y; | ||
| 14 | int16_t h; | ||
| 15 | int16_t v; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Pointing : public TestFixture {}; | ||
| 19 | class PointingInvertAndRotateParametrized : public ::testing::WithParamInterface<std::pair<SimpleReport, SimpleReport>>, public Pointing {}; | ||
| 20 | |||
| 21 | TEST_P(PointingInvertAndRotateParametrized, PointingInvertAndRotateOrder) { | ||
| 22 | TestDriver driver; | ||
| 23 | SimpleReport input = GetParam().first; | ||
| 24 | SimpleReport expectations = GetParam().second; | ||
| 25 | |||
| 26 | pd_set_x(input.x); | ||
| 27 | pd_set_y(input.y); | ||
| 28 | pd_set_h(input.h); | ||
| 29 | pd_set_v(input.v); | ||
| 30 | |||
| 31 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, 0)); | ||
| 32 | run_one_scan_loop(); | ||
| 33 | |||
| 34 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 35 | pd_clear_movement(); | ||
| 36 | run_one_scan_loop(); | ||
| 37 | |||
| 38 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 39 | run_one_scan_loop(); | ||
| 40 | |||
| 41 | VERIFY_AND_CLEAR(driver); | ||
| 42 | } | ||
| 43 | // clang-format off | ||
| 44 | INSTANTIATE_TEST_CASE_P( | ||
| 45 | InvertAndRotate, | ||
| 46 | PointingInvertAndRotateParametrized, | ||
| 47 | ::testing::Values( | ||
| 48 | // Input Expected // Actual Result - Rotate 90 then Invert X | ||
| 49 | std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}), // LEFT - DOWN | ||
| 50 | std::make_pair(SimpleReport{ 0, -1, 0, 0}, SimpleReport{ 1, 0, 0, 0}), // UP - RIGHT | ||
| 51 | std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0, -1, 0, 0}), // RIGHT - UP | ||
| 52 | std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{ -1, 0, 0, 0}) // DOWN - LEFT | ||
| 53 | // Input Expected // Invert X then Rotate 90 | ||
| 54 | // std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0, -1, 0, 0}), // LEFT - UP | ||
| 55 | // std::make_pair(SimpleReport{ 0, -1, 0, 0}, SimpleReport{ -1, 0, 0, 0}), // UP - LEFT | ||
| 56 | // std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}), // RIGHT - DOWN | ||
| 57 | // std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{ 1, 0, 0, 0}) // DOWN - RIGHT | ||
| 58 | )); | ||
| 59 | // clang-format on | ||
diff --git a/tests/pointing/invertxy/config.h b/tests/pointing/invertxy/config.h new file mode 100644 index 0000000000..6b29185d37 --- /dev/null +++ b/tests/pointing/invertxy/config.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
| 7 | |||
| 8 | #define POINTING_DEVICE_INVERT_X | ||
| 9 | #define POINTING_DEVICE_INVERT_Y | ||
diff --git a/tests/pointing/invertxy/test.mk b/tests/pointing/invertxy/test.mk new file mode 100644 index 0000000000..ba224d74f0 --- /dev/null +++ b/tests/pointing/invertxy/test.mk | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | POINTING_DEVICE_DRIVER = custom | ||
diff --git a/tests/pointing/invertxy/test_invertxy.cpp b/tests/pointing/invertxy/test_invertxy.cpp new file mode 100644 index 0000000000..014f6f3cd0 --- /dev/null +++ b/tests/pointing/invertxy/test_invertxy.cpp | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | |||
| 9 | using testing::_; | ||
| 10 | |||
| 11 | struct SimpleReport { | ||
| 12 | int16_t x; | ||
| 13 | int16_t y; | ||
| 14 | int16_t h; | ||
| 15 | int16_t v; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Pointing : public TestFixture {}; | ||
| 19 | class PointingInvertXYParametrized : public ::testing::WithParamInterface<std::pair<SimpleReport, SimpleReport>>, public Pointing {}; | ||
| 20 | |||
| 21 | TEST_P(PointingInvertXYParametrized, PointingInvertXY) { | ||
| 22 | TestDriver driver; | ||
| 23 | SimpleReport input = GetParam().first; | ||
| 24 | SimpleReport expectations = GetParam().second; | ||
| 25 | |||
| 26 | pd_set_x(input.x); | ||
| 27 | pd_set_y(input.y); | ||
| 28 | pd_set_h(input.h); | ||
| 29 | pd_set_v(input.v); | ||
| 30 | |||
| 31 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, 0)); | ||
| 32 | run_one_scan_loop(); | ||
| 33 | |||
| 34 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 35 | pd_clear_movement(); | ||
| 36 | run_one_scan_loop(); | ||
| 37 | |||
| 38 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 39 | run_one_scan_loop(); | ||
| 40 | |||
| 41 | VERIFY_AND_CLEAR(driver); | ||
| 42 | } | ||
| 43 | // clang-format off | ||
| 44 | INSTANTIATE_TEST_CASE_P( | ||
| 45 | X_Y_XY, | ||
| 46 | PointingInvertXYParametrized, | ||
| 47 | ::testing::Values( | ||
| 48 | // Input Expected | ||
| 49 | std::make_pair(SimpleReport{ 33, 0, 0, 0}, SimpleReport{ -33, 0, 0, 0}), | ||
| 50 | std::make_pair(SimpleReport{ 0, -127, 0, 0}, SimpleReport{ 0, 127, 0, 0}), | ||
| 51 | std::make_pair(SimpleReport{ 10, -20, 0, 0}, SimpleReport{ -10, 20, 0, 0}) | ||
| 52 | )); | ||
| 53 | // clang-format on | ||
diff --git a/tests/pointing/rotate180/config.h b/tests/pointing/rotate180/config.h new file mode 100644 index 0000000000..a80f5482fd --- /dev/null +++ b/tests/pointing/rotate180/config.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
| 7 | |||
| 8 | #define POINTING_DEVICE_ROTATION_180 | ||
diff --git a/tests/pointing/rotate180/test.mk b/tests/pointing/rotate180/test.mk new file mode 100644 index 0000000000..ba224d74f0 --- /dev/null +++ b/tests/pointing/rotate180/test.mk | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | POINTING_DEVICE_DRIVER = custom | ||
diff --git a/tests/pointing/rotate180/test_rotate180.cpp b/tests/pointing/rotate180/test_rotate180.cpp new file mode 100644 index 0000000000..736cf9ea25 --- /dev/null +++ b/tests/pointing/rotate180/test_rotate180.cpp | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | |||
| 9 | using testing::_; | ||
| 10 | |||
| 11 | struct SimpleReport { | ||
| 12 | int16_t x; | ||
| 13 | int16_t y; | ||
| 14 | int16_t h; | ||
| 15 | int16_t v; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Pointing : public TestFixture {}; | ||
| 19 | class PointingRotateParametrized : public ::testing::WithParamInterface<std::pair<SimpleReport, SimpleReport>>, public Pointing {}; | ||
| 20 | |||
| 21 | TEST_P(PointingRotateParametrized, PointingRotateXY) { | ||
| 22 | TestDriver driver; | ||
| 23 | SimpleReport input = GetParam().first; | ||
| 24 | SimpleReport expectations = GetParam().second; | ||
| 25 | |||
| 26 | pd_set_x(input.x); | ||
| 27 | pd_set_y(input.y); | ||
| 28 | pd_set_h(input.h); | ||
| 29 | pd_set_v(input.v); | ||
| 30 | |||
| 31 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, 0)); | ||
| 32 | run_one_scan_loop(); | ||
| 33 | |||
| 34 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 35 | pd_clear_movement(); | ||
| 36 | run_one_scan_loop(); | ||
| 37 | |||
| 38 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 39 | run_one_scan_loop(); | ||
| 40 | |||
| 41 | VERIFY_AND_CLEAR(driver); | ||
| 42 | } | ||
| 43 | // clang-format off | ||
| 44 | INSTANTIATE_TEST_CASE_P( | ||
| 45 | Rotate180, | ||
| 46 | PointingRotateParametrized, | ||
| 47 | ::testing::Values( | ||
| 48 | // Input Expected | ||
| 49 | // Rotate Clockwise | ||
| 50 | std::make_pair(SimpleReport{ 0,-1, 0, 0}, SimpleReport{ 0, 1, 0, 0}), // UP - DOWN | ||
| 51 | std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{ 0,-1, 0, 0}), // DOWN - UP | ||
| 52 | std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{-1, 0, 0, 0}), // RIGHT - LEFT | ||
| 53 | std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 1, 0, 0, 0}) // LEFT - RIGHT | ||
| 54 | )); | ||
| 55 | // clang-format on | ||
diff --git a/tests/pointing/rotate270/config.h b/tests/pointing/rotate270/config.h new file mode 100644 index 0000000000..3977dd95e6 --- /dev/null +++ b/tests/pointing/rotate270/config.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
| 7 | |||
| 8 | #define POINTING_DEVICE_ROTATION_270 | ||
diff --git a/tests/pointing/rotate270/test.mk b/tests/pointing/rotate270/test.mk new file mode 100644 index 0000000000..ba224d74f0 --- /dev/null +++ b/tests/pointing/rotate270/test.mk | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | POINTING_DEVICE_DRIVER = custom | ||
diff --git a/tests/pointing/rotate270/test_rotate270.cpp b/tests/pointing/rotate270/test_rotate270.cpp new file mode 100644 index 0000000000..6735f06248 --- /dev/null +++ b/tests/pointing/rotate270/test_rotate270.cpp | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | |||
| 9 | using testing::_; | ||
| 10 | |||
| 11 | struct SimpleReport { | ||
| 12 | int16_t x; | ||
| 13 | int16_t y; | ||
| 14 | int16_t h; | ||
| 15 | int16_t v; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Pointing : public TestFixture {}; | ||
| 19 | class PointingRotateParametrized : public ::testing::WithParamInterface<std::pair<SimpleReport, SimpleReport>>, public Pointing {}; | ||
| 20 | |||
| 21 | TEST_P(PointingRotateParametrized, PointingRotateXY) { | ||
| 22 | TestDriver driver; | ||
| 23 | SimpleReport input = GetParam().first; | ||
| 24 | SimpleReport expectations = GetParam().second; | ||
| 25 | |||
| 26 | pd_set_x(input.x); | ||
| 27 | pd_set_y(input.y); | ||
| 28 | pd_set_h(input.h); | ||
| 29 | pd_set_v(input.v); | ||
| 30 | |||
| 31 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, 0)); | ||
| 32 | run_one_scan_loop(); | ||
| 33 | |||
| 34 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 35 | pd_clear_movement(); | ||
| 36 | run_one_scan_loop(); | ||
| 37 | |||
| 38 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 39 | run_one_scan_loop(); | ||
| 40 | |||
| 41 | VERIFY_AND_CLEAR(driver); | ||
| 42 | } | ||
| 43 | // clang-format off | ||
| 44 | INSTANTIATE_TEST_CASE_P( | ||
| 45 | Rotate270, | ||
| 46 | PointingRotateParametrized, | ||
| 47 | ::testing::Values( | ||
| 48 | // Input Expected | ||
| 49 | // Actual Result - Rotate Anticlockwise | ||
| 50 | std::make_pair(SimpleReport{ 0,-1, 0, 0}, SimpleReport{ 1, 0, 0, 0}), // UP - RIGHT | ||
| 51 | std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{-1, 0, 0, 0}), // DOWN - LEFT | ||
| 52 | std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}), // RIGHT - DOWN | ||
| 53 | std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0,-1, 0, 0}) // LEFT - UP | ||
| 54 | // Rotate Clockwise | ||
| 55 | // std::make_pair(SimpleReport{ 0,-1, 0, 0}, SimpleReport{-1, 0, 0, 0}), // UP - LEFT | ||
| 56 | // std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{ 1, 0, 0, 0}), // DOWN - RIGHT | ||
| 57 | // std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0,-1, 0, 0}), // RIGHT - UP | ||
| 58 | // std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}) // LEFT - DOWN | ||
| 59 | )); | ||
| 60 | // clang-format on | ||
diff --git a/tests/pointing/rotate90/config.h b/tests/pointing/rotate90/config.h new file mode 100644 index 0000000000..3a18ec92e9 --- /dev/null +++ b/tests/pointing/rotate90/config.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "test_common.h" | ||
| 7 | |||
| 8 | #define POINTING_DEVICE_ROTATION_90 | ||
diff --git a/tests/pointing/rotate90/test.mk b/tests/pointing/rotate90/test.mk new file mode 100644 index 0000000000..ba224d74f0 --- /dev/null +++ b/tests/pointing/rotate90/test.mk | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | POINTING_DEVICE_DRIVER = custom | ||
diff --git a/tests/pointing/rotate90/test_rotate90.cpp b/tests/pointing/rotate90/test_rotate90.cpp new file mode 100644 index 0000000000..5c44faad0a --- /dev/null +++ b/tests/pointing/rotate90/test_rotate90.cpp | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | |||
| 9 | using testing::_; | ||
| 10 | |||
| 11 | struct SimpleReport { | ||
| 12 | int16_t x; | ||
| 13 | int16_t y; | ||
| 14 | int16_t h; | ||
| 15 | int16_t v; | ||
| 16 | }; | ||
| 17 | |||
| 18 | class Pointing : public TestFixture {}; | ||
| 19 | class PointingRotateParametrized : public ::testing::WithParamInterface<std::pair<SimpleReport, SimpleReport>>, public Pointing {}; | ||
| 20 | |||
| 21 | TEST_P(PointingRotateParametrized, PointingRotateXY) { | ||
| 22 | TestDriver driver; | ||
| 23 | SimpleReport input = GetParam().first; | ||
| 24 | SimpleReport expectations = GetParam().second; | ||
| 25 | |||
| 26 | pd_set_x(input.x); | ||
| 27 | pd_set_y(input.y); | ||
| 28 | pd_set_h(input.h); | ||
| 29 | pd_set_v(input.v); | ||
| 30 | |||
| 31 | EXPECT_MOUSE_REPORT(driver, (expectations.x, expectations.y, expectations.h, expectations.v, 0)); | ||
| 32 | run_one_scan_loop(); | ||
| 33 | |||
| 34 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 35 | pd_clear_movement(); | ||
| 36 | run_one_scan_loop(); | ||
| 37 | |||
| 38 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 39 | run_one_scan_loop(); | ||
| 40 | |||
| 41 | VERIFY_AND_CLEAR(driver); | ||
| 42 | } | ||
| 43 | // clang-format off | ||
| 44 | INSTANTIATE_TEST_CASE_P( | ||
| 45 | Rotate90, | ||
| 46 | PointingRotateParametrized, | ||
| 47 | ::testing::Values( | ||
| 48 | // Input Expected | ||
| 49 | // Actual Result - Rotate Anticlockwise | ||
| 50 | std::make_pair(SimpleReport{ 0,-1, 0, 0}, SimpleReport{-1, 0, 0, 0}), // UP - LEFT | ||
| 51 | std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{ 1, 0, 0, 0}), // DOWN - RIGHT | ||
| 52 | std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0,-1, 0, 0}), // RIGHT - UP | ||
| 53 | std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}) // LEFT - DOWN | ||
| 54 | // Rotate Clockwise | ||
| 55 | // std::make_pair(SimpleReport{ 0,-1, 0, 0}, SimpleReport{ 1, 0, 0, 0}), // UP - RIGHT | ||
| 56 | // std::make_pair(SimpleReport{ 0, 1, 0, 0}, SimpleReport{-1, 0, 0, 0}), // DOWN - LEFT | ||
| 57 | // std::make_pair(SimpleReport{ 1, 0, 0, 0}, SimpleReport{ 0,-1, 0, 0}), // RIGHT - DOWN | ||
| 58 | // std::make_pair(SimpleReport{ -1, 0, 0, 0}, SimpleReport{ 0, 1, 0, 0}) // LEFT - UP | ||
| 59 | )); | ||
| 60 | // clang-format on | ||
diff --git a/tests/pointing/test.mk b/tests/pointing/test.mk new file mode 100644 index 0000000000..95fde21cb9 --- /dev/null +++ b/tests/pointing/test.mk | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | POINTING_DEVICE_ENABLE = yes | ||
| 2 | MOUSEKEY_ENABLE = no | ||
| 3 | POINTING_DEVICE_DRIVER = custom | ||
| 4 | |||
diff --git a/tests/pointing/test_pointing.cpp b/tests/pointing/test_pointing.cpp new file mode 100644 index 0000000000..d59d014925 --- /dev/null +++ b/tests/pointing/test_pointing.cpp | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "gtest/gtest.h" | ||
| 5 | #include "mouse_report_util.hpp" | ||
| 6 | #include "test_common.hpp" | ||
| 7 | #include "test_pointing_device_driver.h" | ||
| 8 | #include "mousekey.h" | ||
| 9 | |||
| 10 | using testing::_; | ||
| 11 | |||
| 12 | class Pointing : public TestFixture {}; | ||
| 13 | class PointingButtonsViaMousekeysParametrized : public ::testing::WithParamInterface<std::pair<KeymapKey, uint8_t>>, public Pointing {}; | ||
| 14 | |||
| 15 | TEST_F(Pointing, SendMouseIsNotCalledWithNoInput) { | ||
| 16 | TestDriver driver; | ||
| 17 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 18 | run_one_scan_loop(); | ||
| 19 | } | ||
| 20 | |||
| 21 | TEST_F(Pointing, Xnegative) { | ||
| 22 | TestDriver driver; | ||
| 23 | |||
| 24 | pd_set_x(-10); | ||
| 25 | EXPECT_MOUSE_REPORT(driver, (-10, 0, 0, 0, 0)); | ||
| 26 | run_one_scan_loop(); | ||
| 27 | |||
| 28 | pd_clear_movement(); | ||
| 29 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 30 | run_one_scan_loop(); | ||
| 31 | |||
| 32 | VERIFY_AND_CLEAR(driver); | ||
| 33 | } | ||
| 34 | |||
| 35 | TEST_F(Pointing, Xpositive) { | ||
| 36 | TestDriver driver; | ||
| 37 | |||
| 38 | pd_set_x(10); | ||
| 39 | EXPECT_MOUSE_REPORT(driver, (10, 0, 0, 0, 0)); | ||
| 40 | run_one_scan_loop(); | ||
| 41 | |||
| 42 | pd_clear_movement(); | ||
| 43 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 44 | run_one_scan_loop(); | ||
| 45 | |||
| 46 | VERIFY_AND_CLEAR(driver); | ||
| 47 | } | ||
| 48 | |||
| 49 | TEST_F(Pointing, Ynegative) { | ||
| 50 | TestDriver driver; | ||
| 51 | |||
| 52 | pd_set_y(-20); | ||
| 53 | EXPECT_MOUSE_REPORT(driver, (0, -20, 0, 0, 0)); | ||
| 54 | run_one_scan_loop(); | ||
| 55 | |||
| 56 | pd_clear_movement(); | ||
| 57 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 58 | run_one_scan_loop(); | ||
| 59 | |||
| 60 | VERIFY_AND_CLEAR(driver); | ||
| 61 | } | ||
| 62 | |||
| 63 | TEST_F(Pointing, Ypositive) { | ||
| 64 | TestDriver driver; | ||
| 65 | |||
| 66 | pd_set_y(20); | ||
| 67 | EXPECT_MOUSE_REPORT(driver, (0, 20, 0, 0, 0)); | ||
| 68 | run_one_scan_loop(); | ||
| 69 | |||
| 70 | pd_clear_movement(); | ||
| 71 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 72 | run_one_scan_loop(); | ||
| 73 | |||
| 74 | VERIFY_AND_CLEAR(driver); | ||
| 75 | } | ||
| 76 | |||
| 77 | TEST_F(Pointing, XandY) { | ||
| 78 | TestDriver driver; | ||
| 79 | |||
| 80 | pd_set_x(-50); | ||
| 81 | pd_set_y(100); | ||
| 82 | EXPECT_MOUSE_REPORT(driver, (-50, 100, 0, 0, 0)); | ||
| 83 | run_one_scan_loop(); | ||
| 84 | |||
| 85 | pd_clear_movement(); | ||
| 86 | // EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 87 | run_one_scan_loop(); | ||
| 88 | |||
| 89 | VERIFY_AND_CLEAR(driver); | ||
| 90 | } | ||
| 91 | |||
| 92 | TEST_F(Pointing, CorrectButtonIsReportedWhenPressed) { | ||
| 93 | TestDriver driver; | ||
| 94 | |||
| 95 | EXPECT_MOUSE_REPORT(driver, (0, 0, 0, 0, 1)); | ||
| 96 | pd_press_button(POINTING_DEVICE_BUTTON1); | ||
| 97 | run_one_scan_loop(); | ||
| 98 | |||
| 99 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 100 | pd_release_button(POINTING_DEVICE_BUTTON1); | ||
| 101 | run_one_scan_loop(); | ||
| 102 | |||
| 103 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 104 | run_one_scan_loop(); | ||
| 105 | |||
| 106 | pd_clear_all_buttons(); | ||
| 107 | run_one_scan_loop(); | ||
| 108 | |||
| 109 | VERIFY_AND_CLEAR(driver); | ||
| 110 | } | ||
| 111 | |||
| 112 | TEST_F(Pointing, CorrectButtonIsReportedWhenKeyPressed) { | ||
| 113 | TestDriver driver; | ||
| 114 | auto key = KeymapKey(0, 0, 0, KC_MS_BTN1); | ||
| 115 | set_keymap({key}); | ||
| 116 | |||
| 117 | EXPECT_MOUSE_REPORT(driver, (0, 0, 0, 0, 1)); | ||
| 118 | key.press(); | ||
| 119 | run_one_scan_loop(); | ||
| 120 | |||
| 121 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 122 | key.release(); | ||
| 123 | run_one_scan_loop(); | ||
| 124 | |||
| 125 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 126 | run_one_scan_loop(); | ||
| 127 | |||
| 128 | VERIFY_AND_CLEAR(driver); | ||
| 129 | } | ||
| 130 | |||
| 131 | TEST_P(PointingButtonsViaMousekeysParametrized, MouseKeysViaPointingDriver) { | ||
| 132 | TestDriver driver; | ||
| 133 | KeymapKey mouse_key = GetParam().first; | ||
| 134 | uint8_t button_mask = GetParam().second; | ||
| 135 | |||
| 136 | set_keymap({mouse_key}); | ||
| 137 | |||
| 138 | EXPECT_MOUSE_REPORT(driver, (0, 0, 0, 0, button_mask)); | ||
| 139 | mouse_key.press(); | ||
| 140 | run_one_scan_loop(); | ||
| 141 | |||
| 142 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 143 | mouse_key.release(); | ||
| 144 | run_one_scan_loop(); | ||
| 145 | |||
| 146 | EXPECT_NO_MOUSE_REPORT(driver); | ||
| 147 | run_one_scan_loop(); | ||
| 148 | |||
| 149 | VERIFY_AND_CLEAR(driver); | ||
| 150 | } | ||
| 151 | // clang-format off | ||
| 152 | INSTANTIATE_TEST_CASE_P( | ||
| 153 | ButtonsOneToEight, | ||
| 154 | PointingButtonsViaMousekeysParametrized, | ||
| 155 | ::testing::Values( | ||
| 156 | // Key , Buttons Mask | ||
| 157 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_1}, 1), | ||
| 158 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_2}, 2), | ||
| 159 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_3}, 4), | ||
| 160 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_4}, 8), | ||
| 161 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_5}, 16), | ||
| 162 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_6}, 32), | ||
| 163 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_7}, 64), | ||
| 164 | std::make_pair(KeymapKey{0, 0, 0, QK_MOUSE_BUTTON_8}, 128) | ||
| 165 | )); | ||
| 166 | // clang-format on | ||
diff --git a/tests/test_common/mouse_report_util.cpp b/tests/test_common/mouse_report_util.cpp new file mode 100644 index 0000000000..60cdeced24 --- /dev/null +++ b/tests/test_common/mouse_report_util.cpp | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "mouse_report_util.hpp" | ||
| 18 | #include <cstdint> | ||
| 19 | #include <vector> | ||
| 20 | #include <algorithm> | ||
| 21 | |||
| 22 | using namespace testing; | ||
| 23 | |||
| 24 | bool operator==(const report_mouse_t& lhs, const report_mouse_t& rhs) { | ||
| 25 | return lhs.x == rhs.x && lhs.y == rhs.y && lhs.h == rhs.h && lhs.v == rhs.v && lhs.buttons == rhs.buttons; | ||
| 26 | } | ||
| 27 | |||
| 28 | std::ostream& operator<<(std::ostream& os, const report_mouse_t& report) { | ||
| 29 | os << std::setw(10) << std::left << "mouse report: "; | ||
| 30 | |||
| 31 | if (report.x == 0 && report.y == 0 && report.h == 0 && report.v == 0 && report.buttons == 0) { | ||
| 32 | return os << "empty" << std::endl; | ||
| 33 | } | ||
| 34 | |||
| 35 | os << "(X:" << (int)report.x << ", Y:" << (int)report.y << ", H:" << (int)report.h << ", V:" << (int)report.v << ", B:" << (int)report.buttons << ")"; | ||
| 36 | return os << std::endl; | ||
| 37 | } | ||
| 38 | |||
| 39 | MouseReportMatcher::MouseReportMatcher(int16_t x, int16_t y, int8_t h, int8_t v, uint8_t button_mask) { | ||
| 40 | memset(&m_report, 0, sizeof(report_mouse_t)); | ||
| 41 | m_report.x = x; | ||
| 42 | m_report.y = y; | ||
| 43 | m_report.h = h; | ||
| 44 | m_report.v = v; | ||
| 45 | m_report.buttons = button_mask; | ||
| 46 | } | ||
| 47 | |||
| 48 | bool MouseReportMatcher::MatchAndExplain(report_mouse_t& report, MatchResultListener* listener) const { | ||
| 49 | return m_report == report; | ||
| 50 | } | ||
| 51 | |||
| 52 | void MouseReportMatcher::DescribeTo(::std::ostream* os) const { | ||
| 53 | *os << "is equal to " << m_report; | ||
| 54 | } | ||
| 55 | |||
| 56 | void MouseReportMatcher::DescribeNegationTo(::std::ostream* os) const { | ||
| 57 | *os << "is not equal to " << m_report; | ||
| 58 | } | ||
diff --git a/tests/test_common/mouse_report_util.hpp b/tests/test_common/mouse_report_util.hpp new file mode 100644 index 0000000000..645f6aa58c --- /dev/null +++ b/tests/test_common/mouse_report_util.hpp | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #pragma once | ||
| 18 | #include "report.h" | ||
| 19 | #include <ostream> | ||
| 20 | #include "gmock/gmock.h" | ||
| 21 | |||
| 22 | bool operator==(const report_mouse_t& lhs, const report_mouse_t& rhs); | ||
| 23 | std::ostream& operator<<(std::ostream& stream, const report_mouse_t& value); | ||
| 24 | |||
| 25 | class MouseReportMatcher : public testing::MatcherInterface<report_mouse_t&> { | ||
| 26 | public: | ||
| 27 | MouseReportMatcher(int16_t x, int16_t y, int8_t h, int8_t v, uint8_t button_mask); | ||
| 28 | virtual bool MatchAndExplain(report_mouse_t& report, testing::MatchResultListener* listener) const override; | ||
| 29 | virtual void DescribeTo(::std::ostream* os) const override; | ||
| 30 | virtual void DescribeNegationTo(::std::ostream* os) const override; | ||
| 31 | |||
| 32 | private: | ||
| 33 | report_mouse_t m_report; | ||
| 34 | }; | ||
| 35 | |||
| 36 | inline testing::Matcher<report_mouse_t&> MouseReport(int16_t x, int16_t y, int8_t h, int8_t v, uint8_t button_mask) { | ||
| 37 | return testing::MakeMatcher(new MouseReportMatcher(x, y, h, v, button_mask)); | ||
| 38 | } | ||
diff --git a/tests/test_common/pointing_device_driver.c b/tests/test_common/pointing_device_driver.c new file mode 100644 index 0000000000..b64dbad506 --- /dev/null +++ b/tests/test_common/pointing_device_driver.c | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "report.h" | ||
| 5 | #include "test_pointing_device_driver.h" | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | typedef struct { | ||
| 9 | bool pressed; | ||
| 10 | bool dirty; | ||
| 11 | } pd_button_state_t; | ||
| 12 | |||
| 13 | typedef struct { | ||
| 14 | int16_t x; | ||
| 15 | int16_t y; | ||
| 16 | int16_t h; | ||
| 17 | int16_t v; | ||
| 18 | pd_button_state_t button_state[8]; | ||
| 19 | uint16_t cpi; | ||
| 20 | bool initiated; | ||
| 21 | } pd_config_t; | ||
| 22 | |||
| 23 | static pd_config_t pd_config = {0}; | ||
| 24 | |||
| 25 | void pointing_device_driver_init(void) { | ||
| 26 | pd_set_init(true); | ||
| 27 | } | ||
| 28 | |||
| 29 | report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { | ||
| 30 | for (uint8_t i = 0; i < 8; i++) { | ||
| 31 | if (pd_config.button_state[i].dirty) { | ||
| 32 | pd_config.button_state[i].dirty = false; | ||
| 33 | if (pd_config.button_state[i].pressed) { | ||
| 34 | mouse_report.buttons |= 1 << (i); | ||
| 35 | } else { | ||
| 36 | mouse_report.buttons &= ~(1 << (i)); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | mouse_report.x = pd_config.x; | ||
| 41 | mouse_report.y = pd_config.y; | ||
| 42 | mouse_report.h = pd_config.h; | ||
| 43 | mouse_report.v = pd_config.v; | ||
| 44 | return mouse_report; | ||
| 45 | } | ||
| 46 | |||
| 47 | __attribute__((weak)) uint16_t pointing_device_driver_get_cpi(void) { | ||
| 48 | return pd_config.cpi; | ||
| 49 | } | ||
| 50 | |||
| 51 | __attribute__((weak)) void pointing_device_driver_set_cpi(uint16_t cpi) { | ||
| 52 | pd_config.cpi = cpi; | ||
| 53 | } | ||
| 54 | |||
| 55 | void pd_press_button(uint8_t btn) { | ||
| 56 | pd_config.button_state[btn].dirty = true; | ||
| 57 | pd_config.button_state[btn].pressed = true; | ||
| 58 | } | ||
| 59 | void pd_release_button(uint8_t btn) { | ||
| 60 | pd_config.button_state[btn].dirty = true; | ||
| 61 | pd_config.button_state[btn].pressed = false; | ||
| 62 | } | ||
| 63 | |||
| 64 | void pd_clear_all_buttons(void) { | ||
| 65 | for (uint8_t i = 0; i < 8; i++) { | ||
| 66 | pd_config.button_state[i].dirty = true; | ||
| 67 | pd_config.button_state[i].pressed = false; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | void pd_set_x(int16_t x) { | ||
| 72 | pd_config.x = x; | ||
| 73 | } | ||
| 74 | |||
| 75 | void pd_clear_x(void) { | ||
| 76 | pd_set_x(0); | ||
| 77 | } | ||
| 78 | |||
| 79 | void pd_set_y(int16_t y) { | ||
| 80 | pd_config.y = y; | ||
| 81 | } | ||
| 82 | void pd_clear_y(void) { | ||
| 83 | pd_set_y(0); | ||
| 84 | } | ||
| 85 | |||
| 86 | void pd_set_h(int16_t h) { | ||
| 87 | pd_config.h = h; | ||
| 88 | } | ||
| 89 | void pd_clear_h(void) { | ||
| 90 | pd_set_h(0); | ||
| 91 | } | ||
| 92 | |||
| 93 | void pd_set_v(int16_t v) { | ||
| 94 | pd_config.v = v; | ||
| 95 | } | ||
| 96 | void pd_clear_v(void) { | ||
| 97 | pd_set_v(0); | ||
| 98 | } | ||
| 99 | |||
| 100 | void pd_clear_movement(void) { | ||
| 101 | pd_set_x(0); | ||
| 102 | pd_set_y(0); | ||
| 103 | pd_set_h(0); | ||
| 104 | pd_set_v(0); | ||
| 105 | } | ||
| 106 | |||
| 107 | void pd_set_init(bool success) { | ||
| 108 | pd_config.initiated = success; | ||
| 109 | } | ||
diff --git a/tests/test_common/test_driver.cpp b/tests/test_common/test_driver.cpp index d410b225f9..70b920ac86 100644 --- a/tests/test_common/test_driver.cpp +++ b/tests/test_common/test_driver.cpp | |||
| @@ -54,6 +54,7 @@ void TestDriver::send_nkro(report_nkro_t* report) { | |||
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | void TestDriver::send_mouse(report_mouse_t* report) { | 56 | void TestDriver::send_mouse(report_mouse_t* report) { |
| 57 | test_logger.trace() << std::setw(10) << std::left << "send_mouse: (X:" << (int)report->x << ", Y:" << (int)report->y << ", H:" << (int)report->h << ", V:" << (int)report->v << ", B:" << (int)report->buttons << ")" << std::endl; | ||
| 57 | m_this->send_mouse_mock(*report); | 58 | m_this->send_mouse_mock(*report); |
| 58 | } | 59 | } |
| 59 | 60 | ||
diff --git a/tests/test_common/test_driver.hpp b/tests/test_common/test_driver.hpp index ec75d3fff2..fea8225953 100644 --- a/tests/test_common/test_driver.hpp +++ b/tests/test_common/test_driver.hpp | |||
| @@ -67,6 +67,25 @@ class TestDriver { | |||
| 67 | #define EXPECT_REPORT(driver, report) EXPECT_CALL((driver), send_keyboard_mock(KeyboardReport report)) | 67 | #define EXPECT_REPORT(driver, report) EXPECT_CALL((driver), send_keyboard_mock(KeyboardReport report)) |
| 68 | 68 | ||
| 69 | /** | 69 | /** |
| 70 | * @brief Sets gmock expectation that a mouse report of `report` will be sent. | ||
| 71 | * For this macro to parse correctly, the `report` arg must be surrounded by | ||
| 72 | * parentheses ( ). For instance, | ||
| 73 | * | ||
| 74 | * // Expect that a report of "X:-10 Y:0 H:0 V:10 BTN:1 " is sent to the host. | ||
| 75 | * EXPECT_REPORT(driver, (-10, 0, 0, 0, 1)); | ||
| 76 | * | ||
| 77 | * is shorthand for | ||
| 78 | * | ||
| 79 | * EXPECT_CALL(driver, send_mouse_mock(MouseReport(-10, 0, 0, 0, 1))); | ||
| 80 | * | ||
| 81 | * It is possible to use .Times() and other gmock APIS with EXPECT_REPORT, for instance, | ||
| 82 | * allow only single report to be sent: | ||
| 83 | * | ||
| 84 | * EXPECT_REPORT(driver, (-10, 0, 0, 0, 1)).Times(1); | ||
| 85 | */ | ||
| 86 | #define EXPECT_MOUSE_REPORT(driver, report) EXPECT_CALL((driver), send_mouse_mock(MouseReport report)) | ||
| 87 | |||
| 88 | /** | ||
| 70 | * @brief Sets gmock expectation that Unicode `code_point` is sent with UNICODE_MODE_LINUX input | 89 | * @brief Sets gmock expectation that Unicode `code_point` is sent with UNICODE_MODE_LINUX input |
| 71 | * mode. For instance for U+2013, | 90 | * mode. For instance for U+2013, |
| 72 | * | 91 | * |
| @@ -88,6 +107,15 @@ class TestDriver { | |||
| 88 | #define EXPECT_EMPTY_REPORT(driver) EXPECT_REPORT(driver, ()) | 107 | #define EXPECT_EMPTY_REPORT(driver) EXPECT_REPORT(driver, ()) |
| 89 | 108 | ||
| 90 | /** | 109 | /** |
| 110 | * @brief Sets gmock expectation that a empty keyboard report will be sent. | ||
| 111 | * It is possible to use .Times() and other gmock APIS with EXPECT_EMPTY_MOUSE_REPORT, for instance, | ||
| 112 | * allow any number of empty reports with: | ||
| 113 | * | ||
| 114 | * EXPECT_EMPTY_MOUSE_REPORT(driver).Times(AnyNumber()); | ||
| 115 | */ | ||
| 116 | #define EXPECT_EMPTY_MOUSE_REPORT(driver) EXPECT_MOUSE_REPORT(driver, (0, 0, 0, 0, 0)) | ||
| 117 | |||
| 118 | /** | ||
| 91 | * @brief Sets gmock expectation that a keyboard report will be sent, without matching its content. | 119 | * @brief Sets gmock expectation that a keyboard report will be sent, without matching its content. |
| 92 | * It is possible to use .Times() and other gmock APIS with EXPECT_ANY_REPORT, for instance, | 120 | * It is possible to use .Times() and other gmock APIS with EXPECT_ANY_REPORT, for instance, |
| 93 | * allow a single arbitrary report with: | 121 | * allow a single arbitrary report with: |
| @@ -97,10 +125,24 @@ class TestDriver { | |||
| 97 | #define EXPECT_ANY_REPORT(driver) EXPECT_CALL((driver), send_keyboard_mock(_)) | 125 | #define EXPECT_ANY_REPORT(driver) EXPECT_CALL((driver), send_keyboard_mock(_)) |
| 98 | 126 | ||
| 99 | /** | 127 | /** |
| 128 | * @brief Sets gmock expectation that a mouse report will be sent, without matching its content. | ||
| 129 | * It is possible to use .Times() and other gmock APIS with EXPECT_ANY_MOUSE_REPORT, for instance, | ||
| 130 | * allow a single arbitrary report with: | ||
| 131 | * | ||
| 132 | * EXPECT_ANY_MOUSE_REPORT(driver).Times(1); | ||
| 133 | */ | ||
| 134 | #define EXPECT_ANY_MOUSE_REPORT(driver) EXPECT_CALL((driver), send_mouse_mock(_)) | ||
| 135 | |||
| 136 | /** | ||
| 100 | * @brief Sets gmock expectation that no keyboard report will be sent at all. | 137 | * @brief Sets gmock expectation that no keyboard report will be sent at all. |
| 101 | */ | 138 | */ |
| 102 | #define EXPECT_NO_REPORT(driver) EXPECT_ANY_REPORT(driver).Times(0) | 139 | #define EXPECT_NO_REPORT(driver) EXPECT_ANY_REPORT(driver).Times(0) |
| 103 | 140 | ||
| 141 | /** | ||
| 142 | * @brief Sets gmock expectation that no keyboard report will be sent at all. | ||
| 143 | */ | ||
| 144 | #define EXPECT_NO_MOUSE_REPORT(driver) EXPECT_ANY_MOUSE_REPORT(driver).Times(0) | ||
| 145 | |||
| 104 | /** @brief Tests whether keycode `actual` is equal to `expected`. */ | 146 | /** @brief Tests whether keycode `actual` is equal to `expected`. */ |
| 105 | #define EXPECT_KEYCODE_EQ(actual, expected) EXPECT_THAT((actual), KeycodeEq((expected))) | 147 | #define EXPECT_KEYCODE_EQ(actual, expected) EXPECT_THAT((actual), KeycodeEq((expected))) |
| 106 | 148 | ||
diff --git a/tests/test_common/test_fixture.cpp b/tests/test_common/test_fixture.cpp index 3cfb2cb4c2..81806b0e6d 100644 --- a/tests/test_common/test_fixture.cpp +++ b/tests/test_common/test_fixture.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "gmock/gmock.h" | 7 | #include "gmock/gmock.h" |
| 8 | #include "gtest/gtest.h" | 8 | #include "gtest/gtest.h" |
| 9 | #include "keyboard_report_util.hpp" | 9 | #include "keyboard_report_util.hpp" |
| 10 | #include "mouse_report_util.hpp" | ||
| 10 | #include "keycode.h" | 11 | #include "keycode.h" |
| 11 | #include "test_driver.hpp" | 12 | #include "test_driver.hpp" |
| 12 | #include "test_logger.hpp" | 13 | #include "test_logger.hpp" |
| @@ -69,6 +70,9 @@ TestFixture::~TestFixture() { | |||
| 69 | /* Reset keyboard state. */ | 70 | /* Reset keyboard state. */ |
| 70 | clear_all_keys(); | 71 | clear_all_keys(); |
| 71 | 72 | ||
| 73 | #ifdef MOUSEKEY_ENABLE | ||
| 74 | EXPECT_EMPTY_MOUSE_REPORT(driver); | ||
| 75 | #endif | ||
| 72 | clear_keyboard(); | 76 | clear_keyboard(); |
| 73 | 77 | ||
| 74 | clear_oneshot_mods(); | 78 | clear_oneshot_mods(); |
diff --git a/tests/test_common/test_pointing_device_driver.h b/tests/test_common/test_pointing_device_driver.h new file mode 100644 index 0000000000..ae136b21cd --- /dev/null +++ b/tests/test_common/test_pointing_device_driver.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2024 Dasky (@daskygit) | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #ifdef __cplusplus | ||
| 7 | extern "C" { | ||
| 8 | #endif | ||
| 9 | |||
| 10 | void pd_press_button(uint8_t btn); | ||
| 11 | void pd_release_button(uint8_t btn); | ||
| 12 | void pd_clear_all_buttons(void); | ||
| 13 | |||
| 14 | void pd_set_x(int16_t x); | ||
| 15 | void clear_x(void); | ||
| 16 | |||
| 17 | void pd_set_y(int16_t y); | ||
| 18 | void pd_clear_y(void); | ||
| 19 | |||
| 20 | void pd_set_h(int16_t h); | ||
| 21 | void pd_clear_h(void); | ||
| 22 | |||
| 23 | void pd_set_v(int16_t v); | ||
| 24 | void pd_clear_v(void); | ||
| 25 | |||
| 26 | void pd_clear_movement(void); | ||
| 27 | |||
| 28 | void pd_set_init(bool success); | ||
| 29 | |||
| 30 | #ifdef __cplusplus | ||
| 31 | } | ||
| 32 | #endif | ||
