From 95d20e6d8bb1ffaf3024af793daf789ee0b75727 Mon Sep 17 00:00:00 2001 From: Pascal Getreuer <50221757+getreuer@users.noreply.github.com> Date: Sun, 5 Jun 2022 00:14:02 -0700 Subject: Fix and add unit tests for Caps Word to work with Unicode Map, Auto Shift, Retro Shift. (#17284) * Fix Caps Word and Unicode Map * Tests for Caps Word + Auto Shift and Unicode Map. * Fix formatting * Add additional keyboard report expectation macros This commit defines five test utilities, EXPECT_REPORT, EXPECT_UNICODE, EXPECT_EMPTY_REPORT, EXPECT_ANY_REPORT and EXPECT_NO_REPORT for use with TestDriver. EXPECT_REPORT sets a gmock expectation that a given keyboard report will be sent. For instance, EXPECT_REPORT(driver, (KC_LSFT, KC_A)); is shorthand for EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); EXPECT_UNICODE sets a gmock expectation that a given Unicode code point will be sent using UC_LNX input mode. For instance for U+2013, EXPECT_UNICODE(driver, 0x2013); expects the sequence of keys: "Ctrl+Shift+U, 2, 0, 1, 3, space". EXPECT_EMPTY_REPORT sets a gmock expectation that a given keyboard report will be sent. For instance EXPECT_EMPTY_REPORT(driver); expects a single report without keypresses or modifiers. EXPECT_ANY_REPORT sets a gmock expectation that a arbitrary keyboard report will be sent, without matching its contents. For instance EXPECT_ANY_REPORT(driver).Times(1); expects a single arbitrary keyboard report will be sent. EXPECT_NO_REPORT sets a gmock expectation that no keyboard report will be sent at all. * Add tap_key() and tap_keys() to TestFixture. This commit adds a `tap_key(key)` method to TestFixture that taps a given KeymapKey, optionally with a specified delay between press and release. Similarly, the method `tap_keys(key_a, key_b, key_c)` taps a sequence of KeymapKeys. * Use EXPECT_REPORT, tap_keys, etc. in most tests. This commit uses EXPECT_REPORT, EXPECT_UNICODE, EXPECT_EMPTY_REPORT, EXPECT_NO_REPORT, tap_key() and tap_keys() test utilities from the previous two commits in most tests. Particularly the EXPECT_REPORT macro is frequently useful and makes a nice reduction in boilerplate needed to express many tests. Co-authored-by: David Kosorin --- tests/auto_shift/test_auto_shift.cpp | 16 +-- tests/basic/test_action_layer.cpp | 54 ++++----- tests/basic/test_keypress.cpp | 96 ++++++++-------- tests/basic/test_one_shot_keys.cpp | 36 +++--- tests/basic/test_tapping.cpp | 34 +++--- tests/caps_word/caps_word_autoshift/config.h | 22 ++++ tests/caps_word/caps_word_autoshift/test.mk | 18 +++ .../test_caps_word_autoshift.cpp | 101 +++++++++++++++++ tests/caps_word/caps_word_unicodemap/config.h | 20 ++++ tests/caps_word/caps_word_unicodemap/test.mk | 18 +++ .../test_caps_word_unicodemap.cpp | 121 +++++++++++++++++++++ tests/caps_word/test_caps_word.cpp | 68 +++++------- tests/secure/test_secure.cpp | 81 ++++++-------- .../default_mod_tap/test_tap_hold.cpp | 66 +++++------ .../ignore_mod_tap_interrupt/test_tap_hold.cpp | 18 +-- .../permissive_hold/test_one_shot_keys.cpp | 6 +- .../permissive_hold/test_tap_hold.cpp | 16 +-- .../test_tap_hold.cpp | 16 +-- .../retro_tapping/test_tap_hold.cpp | 4 +- .../retro_tapping/test_tapping.cpp | 10 +- .../tapping_force_hold/test_action_layer.cpp | 4 +- .../tapping_force_hold/test_tap_hold.cpp | 26 ++--- tests/test_common/test_driver.cpp | 35 ++++++ tests/test_common/test_driver.hpp | 62 ++++++++++- tests/test_common/test_fixture.cpp | 9 +- tests/test_common/test_fixture.hpp | 17 ++- 26 files changed, 679 insertions(+), 295 deletions(-) create mode 100644 tests/caps_word/caps_word_autoshift/config.h create mode 100644 tests/caps_word/caps_word_autoshift/test.mk create mode 100644 tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp create mode 100644 tests/caps_word/caps_word_unicodemap/config.h create mode 100644 tests/caps_word/caps_word_unicodemap/test.mk create mode 100644 tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp (limited to 'tests') diff --git a/tests/auto_shift/test_auto_shift.cpp b/tests/auto_shift/test_auto_shift.cpp index a19b5dfa82..a83f436c33 100644 --- a/tests/auto_shift/test_auto_shift.cpp +++ b/tests/auto_shift/test_auto_shift.cpp @@ -34,14 +34,14 @@ TEST_F(AutoShift, key_release_before_timeout) { set_keymap({regular_key}); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -55,16 +55,16 @@ TEST_F(AutoShift, key_release_after_timeout) { set_keymap({regular_key}); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); idle_for(AUTO_SHIFT_TIMEOUT); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/basic/test_action_layer.cpp b/tests/basic/test_action_layer.cpp index fe5c729f7c..fa339a3375 100644 --- a/tests/basic/test_action_layer.cpp +++ b/tests/basic/test_action_layer.cpp @@ -131,12 +131,12 @@ TEST_F(ActionLayer, MomentaryLayerDoesNothing) { set_keymap({layer_key}); /* Press and release MO, nothing should happen. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -151,28 +151,28 @@ TEST_F(ActionLayer, MomentaryLayerWithKeypress) { set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); /* Press MO. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Press key on layer 1 */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1); + EXPECT_REPORT(driver, (KC_B)).Times(1); regular_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Release key on layer 1 */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Release MO */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); @@ -188,14 +188,14 @@ TEST_F(ActionLayer, ToggleLayerDoesNothing) { set_keymap({layer_key}); /* Press TG. Layer state should not change as it's applied on release. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Release TG. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); @@ -212,26 +212,26 @@ TEST_F(ActionLayer, ToggleLayerUpAndDown) { set_keymap({toggle_layer_1_on_layer_0, toggle_layer_0_on_layer_1}); /* Toggle Layer 1. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); toggle_layer_1_on_layer_0.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); toggle_layer_1_on_layer_0.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Toggle Layer 0. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); toggle_layer_0_on_layer_1.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); toggle_layer_0_on_layer_1.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); @@ -247,13 +247,13 @@ TEST_F(ActionLayer, LayerTapToggleDoesNothing) { set_keymap({layer_key}); /* Press and release TT. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); @@ -271,25 +271,25 @@ TEST_F(ActionLayer, LayerTapToggleWithKeypress) { set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); /* Press TT. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1); + EXPECT_REPORT(driver, (KC_B)).Times(1); regular_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); @@ -307,7 +307,7 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); /* Tap TT five times . */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); @@ -346,13 +346,13 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1); + EXPECT_REPORT(driver, (KC_B)).Times(1); regular_key.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); @@ -370,7 +370,7 @@ TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) { set_keymap({layer_0_key_0, layer_1_key_1}); /* Press layer tap and wait for tapping term to switch to layer 1 */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + EXPECT_NO_REPORT(driver); layer_0_key_0.press(); idle_for(TAPPING_TERM); EXPECT_TRUE(layer_state_is(0)); @@ -378,23 +378,23 @@ TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) { /* Press key with layer 1 mapping, result basically expected * altough more reports are send then necessary. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT, KC_9))).Times(1); + EXPECT_REPORT(driver, (KC_RALT)).Times(1); + EXPECT_REPORT(driver, (KC_RALT, KC_9)).Times(1); layer_1_key_1.press(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(1)); testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer tap key, no report is send because key is still held. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_0_key_0.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); testing::Mock::VerifyAndClearExpectations(&driver); /* Unregister keycode and modifier. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_REPORT(driver, (KC_RALT)).Times(1); + EXPECT_EMPTY_REPORT(driver); layer_1_key_1.release(); run_one_scan_loop(); EXPECT_TRUE(layer_state_is(0)); diff --git a/tests/basic/test_keypress.cpp b/tests/basic/test_keypress.cpp index 044fc29378..bb68ced557 100644 --- a/tests/basic/test_keypress.cpp +++ b/tests/basic/test_keypress.cpp @@ -24,7 +24,7 @@ class KeyPress : public TestFixture {}; TEST_F(KeyPress, SendKeyboardIsNotCalledWhenNoKeyIsPressed) { TestDriver driver; - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); keyboard_task(); } @@ -35,11 +35,11 @@ TEST_F(KeyPress, CorrectKeyIsReportedWhenPressed) { set_keymap({key}); key.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key.report_code))); + EXPECT_REPORT(driver, (key.report_code)); keyboard_task(); key.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -50,7 +50,7 @@ TEST_F(KeyPress, ANonMappedKeyDoesNothing) { set_keymap({key}); key.press(); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); keyboard_task(); keyboard_task(); } @@ -66,19 +66,19 @@ TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) { key_c.press(); // Note that QMK only processes one key at a time // See issue #1476 for more information - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code))); + EXPECT_REPORT(driver, (key_b.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code, key_c.report_code))); + EXPECT_REPORT(driver, (key_b.report_code, key_c.report_code)); keyboard_task(); key_b.release(); key_c.release(); // Note that the first key released is the first one in the matrix order - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_c.report_code))); + EXPECT_REPORT(driver, (key_c.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -94,17 +94,17 @@ TEST_F(KeyPress, LeftShiftIsReportedCorrectly) { // Unfortunately modifiers are also processed in the wrong order // See issue #1476 for more information - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_a.report_code))); + EXPECT_REPORT(driver, (key_a.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_a.report_code, key_lsft.report_code))); + EXPECT_REPORT(driver, (key_a.report_code, key_lsft.report_code)); keyboard_task(); key_a.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code))); + EXPECT_REPORT(driver, (key_lsft.report_code)); keyboard_task(); key_lsft.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -120,19 +120,19 @@ TEST_F(KeyPress, PressLeftShiftAndControl) { // Unfortunately modifiers are also processed in the wrong order // See issue #1476 for more information - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code))); + EXPECT_REPORT(driver, (key_lsft.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code, key_lctrl.report_code))); + EXPECT_REPORT(driver, (key_lsft.report_code, key_lctrl.report_code)); keyboard_task(); key_lsft.release(); key_lctrl.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lctrl.report_code))); + EXPECT_REPORT(driver, (key_lctrl.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -147,19 +147,19 @@ TEST_F(KeyPress, LeftAndRightShiftCanBePressedAtTheSameTime) { key_rsft.press(); // Unfortunately modifiers are also processed in the wrong order // See issue #1476 for more information - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code))); + EXPECT_REPORT(driver, (key_lsft.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code, key_rsft.report_code))); + EXPECT_REPORT(driver, (key_lsft.report_code, key_rsft.report_code)); keyboard_task(); key_lsft.release(); key_rsft.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_rsft.report_code))); + EXPECT_REPORT(driver, (key_rsft.report_code)); keyboard_task(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -175,13 +175,13 @@ TEST_F(KeyPress, RightShiftLeftControlAndCharWithTheSameKey) { // The underlying cause is that we use only one bit to represent the right hand // modifiers. combo_key.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RIGHT_SHIFT, KC_RIGHT_CTRL))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RIGHT_SHIFT, KC_RIGHT_CTRL, KC_O))); + EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL)); + EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL, KC_O)); keyboard_task(); combo_key.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RIGHT_SHIFT, KC_RIGHT_CTRL))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_RIGHT_SHIFT, KC_RIGHT_CTRL)); + EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -194,24 +194,24 @@ TEST_F(KeyPress, PressPlusEqualReleaseBeforePress) { set_keymap({key_plus, key_eql}); key_plus.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL))); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_eql.report_code))); + EXPECT_REPORT(driver, (key_eql.report_code)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -225,25 +225,25 @@ TEST_F(KeyPress, PressPlusEqualDontReleaseBeforePress) { set_keymap({key_plus, key_eql}); key_plus.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL))); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQUAL))); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.release(); // BUG: Should really still return KC_EQUAL, but this is fine too - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.release(); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -257,24 +257,24 @@ TEST_F(KeyPress, PressEqualPlusReleaseBeforePress) { set_keymap({key_plus, key_eql}); key_eql.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQUAL))); + EXPECT_REPORT(driver, (KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL))); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -288,27 +288,27 @@ TEST_F(KeyPress, PressEqualPlusDontReleaseBeforePress) { set_keymap({key_plus, key_eql}); key_eql.press(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_EQUAL))); + EXPECT_REPORT(driver, (KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.press(); // BUG: The sequence is a bit strange, but it works, the end result is that // KC_PLUS is sent - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_EQUAL))); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, KC_EQUAL)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_eql.release(); // I guess it's fine to still report shift here - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); key_plus.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); } diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp index 43fc3e1ba3..bb14221140 100644 --- a/tests/basic/test_one_shot_keys.cpp +++ b/tests/basic/test_one_shot_keys.cpp @@ -31,7 +31,7 @@ TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) { set_keymap({osm_key}); /* Press and release OSM key*/ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osm_key.press(); run_one_scan_loop(); osm_key.release(); @@ -39,7 +39,7 @@ TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) { testing::Mock::VerifyAndClearExpectations(&driver); /* OSM are added when an actual report is send */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code))); + EXPECT_REPORT(driver, (osm_key.report_code)); send_keyboard_report(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -57,7 +57,7 @@ TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) { set_keymap({osm_key, regular_key}); /* Press and release OSM */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osm_key.press(); run_one_scan_loop(); osm_key.release(); @@ -65,13 +65,13 @@ TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(1); + EXPECT_REPORT(driver, (regular_key.report_code)).Times(1); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -87,7 +87,7 @@ TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) { set_keymap({osm_key, regular_key}); /* Press and release OSM */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osm_key.press(); run_one_scan_loop(); osm_key.release(); @@ -95,13 +95,13 @@ TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code, regular_key.report_code))).Times(1); + EXPECT_REPORT(driver, (osm_key.report_code, regular_key.report_code)).Times(1); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -117,26 +117,26 @@ TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypres set_keymap({osm_key, regular_key}); /* Press OSM */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osm_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release OSM */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code, osm_key.report_code))).Times(1); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_REPORT(driver, (regular_key.report_code, osm_key.report_code)).Times(1); + EXPECT_EMPTY_REPORT(driver); osm_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -169,26 +169,26 @@ TEST_F(OneShot, OSLWithAdditionalKeypress) { set_keymap({osl_key, regular_key}); /* Press OSL key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osl_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release OSL key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osl_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(1); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (regular_key.report_code)).Times(1); + EXPECT_EMPTY_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/basic/test_tapping.cpp b/tests/basic/test_tapping.cpp index e4a7e4a9f3..6ff9cfe22b 100644 --- a/tests/basic/test_tapping.cpp +++ b/tests/basic/test_tapping.cpp @@ -34,15 +34,15 @@ TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) { // Tapping keys does nothing on press key_shift_hold_p_tap.press(); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); run_one_scan_loop(); // First we get the key press key_shift_hold_p_tap.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); // Then the release - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); } @@ -56,13 +56,13 @@ TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) { mod_tap_hold_key.press(); // Tapping keys does nothing on press - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); idle_for(TAPPING_TERM); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); run_one_scan_loop(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); } @@ -77,36 +77,36 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { // Tapping keys does nothing on press key_shift_hold_p_tap.press(); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); run_one_scan_loop(); key_shift_hold_p_tap.release(); // First we get the key press - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); // Then the release - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); // This sends KC_P, even if it should do nothing key_shift_hold_p_tap.press(); // This test should not succed if everything works correctly - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); run_one_scan_loop(); key_shift_hold_p_tap.release(); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); idle_for(TAPPING_TERM + 1); // On the other hand, nothing is sent if we are outside the tapping term key_shift_hold_p_tap.press(); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); run_one_scan_loop(); key_shift_hold_p_tap.release(); // First we get the key press - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); // Then the release - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); idle_for(TAPPING_TERM + 1); // Now we are geting into strange territory, as the hold registers too early here @@ -114,10 +114,10 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { // If TAPPING_TERM + 1 above is changed to TAPPING_TERM or TAPPING_TERM + 2 it doesn't key_shift_hold_p_tap.press(); // Shouldn't be called here really - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).Times(1); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)).Times(1); idle_for(TAPPING_TERM); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); key_shift_hold_p_tap.release(); run_one_scan_loop(); -} \ No newline at end of file +} diff --git a/tests/caps_word/caps_word_autoshift/config.h b/tests/caps_word/caps_word_autoshift/config.h new file mode 100644 index 0000000000..b80f53b9dd --- /dev/null +++ b/tests/caps_word/caps_word_autoshift/config.h @@ -0,0 +1,22 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "test_common.h" + +#define TAPPING_TERM 200 +#define AUTO_SHIFT_TIMEOUT 150 +#define RETRO_SHIFT 500 diff --git a/tests/caps_word/caps_word_autoshift/test.mk b/tests/caps_word/caps_word_autoshift/test.mk new file mode 100644 index 0000000000..7f717d7fc1 --- /dev/null +++ b/tests/caps_word/caps_word_autoshift/test.mk @@ -0,0 +1,18 @@ +# Copyright 2022 Google LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +CAPS_WORD_ENABLE = yes +AUTO_SHIFT_ENABLE = yes + diff --git a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp b/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp new file mode 100644 index 0000000000..deb4d95766 --- /dev/null +++ b/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp @@ -0,0 +1,101 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::AnyOf; +using ::testing::InSequence; + +class CapsWord : public TestFixture { + public: + void SetUp() override { + caps_word_off(); + } +}; + +// Tests that with Auto Shift, letter keys are shifted by Caps Word +// regardless of whether they are released before AUTO_SHIFT_TIMEOUT. +TEST_F(CapsWord, AutoShiftKeys) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_spc(0, 1, 0, KC_SPC); + set_keymap({key_a, key_spc}); + + // Allow any number of reports with no keys or only KC_LSFT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + { // Expect: "A, A, space, a". + InSequence s; + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_SPC)); + EXPECT_REPORT(driver, (KC_A)); + } + + // Turn on Caps Word and type "A (quick tap), A (long press), space, A". + caps_word_on(); + + tap_key(key_a); // Tap A quickly. + tap_key(key_a, AUTO_SHIFT_TIMEOUT + 1); // Long press A. + tap_key(key_spc); + tap_key(key_a); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests that with tap-hold keys with Retro Shift, letter keys are shifted by +// Caps Word regardless of whether they are retroshifted. +TEST_F(CapsWord, RetroShiftKeys) { + TestDriver driver; + KeymapKey key_modtap_a(0, 0, 0, LCTL_T(KC_A)); + KeymapKey key_layertap_b(0, 1, 0, LT(1, KC_B)); + set_keymap({key_modtap_a, key_layertap_b}); + + // Allow any number of reports with no keys or only KC_LSFT. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + { // Expect: "B, A, B, A". + InSequence s; + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + } + + // Turn on Caps Word and type "B, A (long press), B (long press), A". + caps_word_on(); + + tap_key(key_layertap_b); // Tap B quickly. + tap_key(key_modtap_a, TAPPING_TERM + 1); // Long press A. + tap_key(key_layertap_b, TAPPING_TERM + 1); // Long press B. + tap_key(key_modtap_a); // Tap A quickly. + + EXPECT_EQ(is_caps_word_on(), true); + testing::Mock::VerifyAndClearExpectations(&driver); +} diff --git a/tests/caps_word/caps_word_unicodemap/config.h b/tests/caps_word/caps_word_unicodemap/config.h new file mode 100644 index 0000000000..89fd7924d4 --- /dev/null +++ b/tests/caps_word/caps_word_unicodemap/config.h @@ -0,0 +1,20 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "test_common.h" + +#define UNICODE_SELECTED_MODES UC_LNX diff --git a/tests/caps_word/caps_word_unicodemap/test.mk b/tests/caps_word/caps_word_unicodemap/test.mk new file mode 100644 index 0000000000..92bcba762c --- /dev/null +++ b/tests/caps_word/caps_word_unicodemap/test.mk @@ -0,0 +1,18 @@ +# Copyright 2022 Google LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +CAPS_WORD_ENABLE = yes +UNICODEMAP_ENABLE = yes + diff --git a/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp b/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp new file mode 100644 index 0000000000..fb8f9333bb --- /dev/null +++ b/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp @@ -0,0 +1,121 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::AnyOf; +using ::testing::InSequence; + +extern "C" { +enum unicode_names { + ENDASH, + EMDASH, + DELTA_LOWERCASE, + DELTA_UPPERCASE, +}; + +const uint32_t unicode_map[] PROGMEM = { + [ENDASH] = 0x2013, + [EMDASH] = 0x2014, + [DELTA_LOWERCASE] = 0x03b4, + [DELTA_UPPERCASE] = 0x0394, +}; + +#define U_DASH XP(ENDASH, EMDASH) +#define U_DELTA XP(DELTA_LOWERCASE, DELTA_UPPERCASE) + +bool caps_word_press_user(uint16_t keycode) { + switch (keycode) { + // Keycodes that continue Caps Word, with shift applied. + case U_DELTA: + add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key. + return true; + + // Keycodes that continue Caps Word, without shifting. + case U_DASH: + return true; + + default: + return false; // Deactivate Caps Word. + } +} +} // extern "C" + +class CapsWord : public TestFixture { + public: + void SetUp() override { + caps_word_off(); + } +}; + +// Tests that typing U_DELTA while Caps Word is on sends the uppercase Delta. +TEST_F(CapsWord, ShiftedUnicodeMapKey) { + TestDriver driver; + KeymapKey key_delta(0, 0, 0, U_DELTA); + KeymapKey key_spc(0, 1, 0, KC_SPC); + set_keymap({key_delta, key_spc}); + + // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT), + KeyboardReport(KC_LCTL, KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + { // Expect: "Uppercase Delta, space, lowercase delta". + InSequence s; + EXPECT_UNICODE(driver, unicode_map[DELTA_UPPERCASE]); + EXPECT_REPORT(driver, (KC_SPC)); + EXPECT_UNICODE(driver, unicode_map[DELTA_LOWERCASE]); + } + + // Turn on Caps Word and tap "delta, space, delta". + caps_word_on(); + tap_keys(key_delta, key_spc, key_delta); + + EXPECT_EQ(is_caps_word_on(), false); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests typing U_ENDASH while Caps Word is on. +TEST_F(CapsWord, UnshiftedUnicodeMapKey) { + TestDriver driver; + KeymapKey key_dash(0, 0, 0, U_DASH); + set_keymap({key_dash}); + + // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT), + KeyboardReport(KC_LCTL, KC_LSFT)))) + .Times(AnyNumber()); + // clang-format on + EXPECT_UNICODE(driver, unicode_map[ENDASH]); + + // Turn on Caps Word and tap U_DASH key. + caps_word_on(); + tap_key(key_dash); + + EXPECT_EQ(is_caps_word_on(), true); + testing::Mock::VerifyAndClearExpectations(&driver); +} diff --git a/tests/caps_word/test_caps_word.cpp b/tests/caps_word/test_caps_word.cpp index f611d4c104..0af4b0175d 100644 --- a/tests/caps_word/test_caps_word.cpp +++ b/tests/caps_word/test_caps_word.cpp @@ -30,22 +30,6 @@ class CapsWord : public TestFixture { void SetUp() override { caps_word_off(); } - - // Convenience function to tap `key`. - void TapKey(KeymapKey key) { - key.press(); - run_one_scan_loop(); - key.release(); - run_one_scan_loop(); - } - - // Taps in order each key in `keys`. - template - void TapKeys(Ts... keys) { - for (KeymapKey key : {keys...}) { - TapKey(key); - } - } }; // Tests caps_word_on(), _off(), and _toggle() functions. @@ -104,12 +88,12 @@ TEST_F(CapsWord, CapswrdKey) { set_keymap({key_capswrd}); // No keyboard reports should be sent. - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); - TapKey(key_capswrd); // Tap the CAPSWRD key. + tap_key(key_capswrd); // Tap the CAPSWRD key. EXPECT_EQ(is_caps_word_on(), true); - TapKey(key_capswrd); // Tap the CAPSWRD key again. + tap_key(key_capswrd); // Tap the CAPSWRD key again. EXPECT_EQ(is_caps_word_on(), false); testing::Mock::VerifyAndClearExpectations(&driver); @@ -130,11 +114,11 @@ TEST_F(CapsWord, IdleTimeout) { // clang-format on // Expect "Shift+A". - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); // Turn on Caps Word and tap "A". caps_word_on(); - TapKey(key_a); + tap_key(key_a); testing::Mock::VerifyAndClearExpectations(&driver); @@ -145,10 +129,10 @@ TEST_F(CapsWord, IdleTimeout) { EXPECT_EQ(is_caps_word_on(), false); EXPECT_EQ(get_mods() | get_weak_mods(), 0); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(AnyNumber()); + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); // Expect unshifted "A". - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))); - TapKey(key_a); + EXPECT_REPORT(driver, (KC_A)); + tap_key(key_a); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -170,15 +154,15 @@ TEST_F(CapsWord, ShiftsLettersButNotDigits) { { // Expect: "Shift+A, 4, Shift+A, 4". InSequence s; - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_4))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_4))); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_4)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_4)); } // Turn on Caps Word and tap "A, 4, A, 4". caps_word_on(); - TapKeys(key_a, key_4, key_a, key_4); + tap_keys(key_a, key_4, key_a, key_4); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -200,14 +184,14 @@ TEST_F(CapsWord, SpaceTurnsOffCapsWord) { { // Expect: "Shift+A, Space, A". InSequence seq; - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_SPC))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_SPC)); + EXPECT_REPORT(driver, (KC_A)); } // Turn on Caps Word and tap "A, Space, A". caps_word_on(); - TapKeys(key_a, key_spc, key_a); + tap_keys(key_a, key_spc, key_a); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -226,8 +210,8 @@ TEST_F(CapsWord, ShiftsAltGrSymbols) { KeyboardReport(KC_RALT), KeyboardReport(KC_LSFT, KC_RALT)))) .Times(AnyNumber()); - // Expect "Shift + AltGr + A, Space". - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_RALT, KC_A))); + // Expect "Shift + AltGr + A". + EXPECT_REPORT(driver, (KC_LSFT, KC_RALT, KC_A)); // clang-format on // Turn on Caps Word and type "AltGr + A". @@ -235,7 +219,7 @@ TEST_F(CapsWord, ShiftsAltGrSymbols) { key_altgr.press(); run_one_scan_loop(); - TapKeys(key_a); + tap_key(key_a); run_one_scan_loop(); key_altgr.release(); @@ -376,9 +360,9 @@ TEST_P(CapsWordDoubleTapShift, Activation) { EXPECT_EQ(is_caps_word_on(), false); // Tapping shift twice within the tapping term turns on Caps Word. - TapKey(left_shift); + tap_key(left_shift); idle_for(TAPPING_TERM - 10); - TapKey(left_shift); + tap_key(left_shift); EXPECT_EQ(is_caps_word_on(), true); @@ -403,13 +387,13 @@ TEST_P(CapsWordDoubleTapShift, Interrupted) { left_shift.press(); run_one_scan_loop(); - TapKey(key_a); // 'A' key interrupts the double tap. + tap_key(key_a); // 'A' key interrupts the double tap. left_shift.release(); run_one_scan_loop(); idle_for(TAPPING_TERM - 10); - TapKey(left_shift); + tap_key(left_shift); EXPECT_EQ(is_caps_word_on(), false); // Caps Word is still off. clear_oneshot_mods(); @@ -430,9 +414,9 @@ TEST_P(CapsWordDoubleTapShift, SlowTaps) { .Times(AnyNumber()); // clang-format on - TapKey(left_shift); + tap_key(left_shift); idle_for(TAPPING_TERM + 1); - TapKey(left_shift); + tap_key(left_shift); EXPECT_EQ(is_caps_word_on(), false); // Caps Word is still off. clear_oneshot_mods(); diff --git a/tests/secure/test_secure.cpp b/tests/secure/test_secure.cpp index b7c51b0bd2..6ca98d78f3 100644 --- a/tests/secure/test_secure.cpp +++ b/tests/secure/test_secure.cpp @@ -27,28 +27,13 @@ class Secure : public TestFixture { void SetUp() override { secure_lock(); } - // Convenience function to tap `key`. - void TapKey(KeymapKey key) { - key.press(); - run_one_scan_loop(); - key.release(); - run_one_scan_loop(); - } - - // Taps in order each key in `keys`. - template - void TapKeys(Ts... keys) { - for (KeymapKey key : {keys...}) { - TapKey(key); - } - } }; TEST_F(Secure, test_lock) { TestDriver driver; - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + // Don't allow empty reports. + EXPECT_NO_REPORT(driver); EXPECT_FALSE(secure_is_unlocked()); secure_unlock(); @@ -64,8 +49,8 @@ TEST_F(Secure, test_lock) { TEST_F(Secure, test_unlock_timeout) { TestDriver driver; - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + // Don't allow empty reports. + EXPECT_NO_REPORT(driver); EXPECT_FALSE(secure_is_unlocked()); secure_unlock(); @@ -86,13 +71,13 @@ TEST_F(Secure, test_unlock_request) { set_keymap({key_mo, key_a, key_b, key_c, key_d}); - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + // Don't allow empty reports. + EXPECT_NO_REPORT(driver); EXPECT_TRUE(secure_is_locked()); secure_request_unlock(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_b, key_c, key_d); + tap_keys(key_a, key_b, key_c, key_d); EXPECT_TRUE(secure_is_unlocked()); testing::Mock::VerifyAndClearExpectations(&driver); @@ -109,18 +94,18 @@ TEST_F(Secure, test_unlock_request_fail) { set_keymap({key_e, key_a, key_b, key_c, key_d}); // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(AnyNumber()); + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); { // Expect the following reports in this order. InSequence s; - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_C))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_D))); + EXPECT_REPORT(driver, (KC_A)); + EXPECT_REPORT(driver, (KC_B)); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_REPORT(driver, (KC_D)); } EXPECT_TRUE(secure_is_locked()); secure_request_unlock(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_e, key_a, key_b, key_c, key_d); + tap_keys(key_e, key_a, key_b, key_c, key_d); EXPECT_FALSE(secure_is_unlocked()); testing::Mock::VerifyAndClearExpectations(&driver); @@ -129,8 +114,8 @@ TEST_F(Secure, test_unlock_request_fail) { TEST_F(Secure, test_unlock_request_timeout) { TestDriver driver; - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + // Don't allow empty reports. + EXPECT_NO_REPORT(driver); EXPECT_FALSE(secure_is_unlocked()); secure_request_unlock(); @@ -153,16 +138,16 @@ TEST_F(Secure, test_unlock_request_fail_mid) { set_keymap({key_e, key_a, key_b, key_c, key_d}); // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(AnyNumber()); + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); { // Expect the following reports in this order. InSequence s; - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_C))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_D))); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_REPORT(driver, (KC_D)); } EXPECT_FALSE(secure_is_unlocked()); secure_request_unlock(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_b, key_e, key_c, key_d); + tap_keys(key_a, key_b, key_e, key_c, key_d); EXPECT_FALSE(secure_is_unlocking()); EXPECT_FALSE(secure_is_unlocked()); @@ -180,16 +165,16 @@ TEST_F(Secure, test_unlock_request_fail_out_of_order) { set_keymap({key_e, key_a, key_b, key_c, key_d}); // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(AnyNumber()); + EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); { // Expect the following reports in this order. InSequence s; - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_C))); + EXPECT_REPORT(driver, (KC_B)); + EXPECT_REPORT(driver, (KC_C)); } EXPECT_FALSE(secure_is_unlocked()); secure_request_unlock(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_d, key_b, key_c); + tap_keys(key_a, key_d, key_b, key_c); EXPECT_TRUE(secure_is_locked()); EXPECT_FALSE(secure_is_unlocking()); EXPECT_FALSE(secure_is_unlocked()); @@ -207,8 +192,8 @@ TEST_F(Secure, test_unlock_request_on_layer) { set_keymap({key_mo, key_a, key_b, key_c, key_d}); - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0); + // Don't allow empty reports. + EXPECT_NO_REPORT(driver); EXPECT_TRUE(secure_is_locked()); key_mo.press(); @@ -217,7 +202,7 @@ TEST_F(Secure, test_unlock_request_on_layer) { key_mo.release(); run_one_scan_loop(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_b, key_c, key_d); + tap_keys(key_a, key_b, key_c, key_d); EXPECT_TRUE(secure_is_unlocked()); EXPECT_FALSE(layer_state_is(1)); @@ -234,9 +219,8 @@ TEST_F(Secure, test_unlock_request_mid_stroke) { set_keymap({key_e, key_a, key_b, key_c, key_d}); - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_E))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_E)); + EXPECT_EMPTY_REPORT(driver); EXPECT_TRUE(secure_is_locked()); key_e.press(); run_one_scan_loop(); @@ -244,7 +228,7 @@ TEST_F(Secure, test_unlock_request_mid_stroke) { key_e.release(); run_one_scan_loop(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_b, key_c, key_d); + tap_keys(key_a, key_b, key_c, key_d); EXPECT_TRUE(secure_is_unlocked()); testing::Mock::VerifyAndClearExpectations(&driver); @@ -260,9 +244,8 @@ TEST_F(Secure, test_unlock_request_mods) { set_keymap({key_lsft, key_a, key_b, key_c, key_d}); - // Allow any number of empty reports. - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_lsft.report_code))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (key_lsft.report_code)); + EXPECT_EMPTY_REPORT(driver); EXPECT_TRUE(secure_is_locked()); key_lsft.press(); run_one_scan_loop(); @@ -270,7 +253,7 @@ TEST_F(Secure, test_unlock_request_mods) { key_lsft.release(); run_one_scan_loop(); EXPECT_TRUE(secure_is_unlocking()); - TapKeys(key_a, key_b, key_c, key_d); + tap_keys(key_a, key_b, key_c, key_d); EXPECT_TRUE(secure_is_unlocked()); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp index 90befcdffd..ecb79c2560 100644 --- a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp @@ -35,28 +35,28 @@ TEST_F(DefaultTapHold, tap_regular_key_while_mod_tap_key_is_held) { set_keymap({mod_tap_hold_key, regular_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_P, KC_A)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -75,28 +75,28 @@ TEST_F(DefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held) { set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); /* Press first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); first_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_P, KC_A)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); first_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -112,27 +112,27 @@ TEST_F(DefaultTapHold, tap_regular_key_while_layer_tap_key_is_held) { set_keymap({layer_tap_hold_key, regular_key, layer_key}); /* Press layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_P, KC_A)); + EXPECT_REPORT(driver, (KC_P)); EXPECT_CALL(driver, send_keyboard_mock(_)); layer_tap_hold_key.release(); run_one_scan_loop(); @@ -149,26 +149,26 @@ TEST_F(DefaultTapHold, tap_mod_tap_hold_key_two_times) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod-tap-hold key again. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); mod_tap_hold_key.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -184,26 +184,26 @@ TEST_F(DefaultTapHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod-tap-hold key again. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); mod_tap_hold_key.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -217,14 +217,14 @@ TEST_F(DefaultTapHold, tap_and_hold_mod_tap_hold_key) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); + EXPECT_REPORT(driver, (KC_LSHIFT)); mod_tap_hold_key.press(); idle_for(TAPPING_TERM + 1); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp index 1702d604d3..5ece124c1d 100644 --- a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp @@ -35,19 +35,19 @@ TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) { set_keymap({mod_tap_hold_key, regular_key}); /* Press mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -71,19 +71,19 @@ TEST_F(IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) { set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); /* Press first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); first_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -108,19 +108,19 @@ TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) { set_keymap({layer_tap_hold_key, regular_key, layer_key}); /* Press layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp index aa71ec397f..64a6ff58e6 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp @@ -32,13 +32,13 @@ TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypres set_keymap({osm_key, regular_key}); /* Press OSM */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); osm_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -73,4 +73,4 @@ INSTANTIATE_TEST_CASE_P( std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RALT), KC_RALT}, KeymapKey{0, 1, 1, KC_A}), std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RGUI), KC_RGUI}, KeymapKey{0, 1, 1, KC_A}) )); -// clang-format on \ No newline at end of file +// clang-format on diff --git a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp index 00c2b33cb7..28fb17ca66 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp @@ -34,13 +34,13 @@ TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) { set_keymap({mod_tap_hold_key, regular_key}); /* Press mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -69,13 +69,13 @@ TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) { set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); /* Press first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); first_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press second mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -105,13 +105,13 @@ TEST_F(PermissiveHold, tap_regular_key_while_layer_tap_key_is_held) { set_keymap({layer_tap_hold_key, regular_key, layer_key}); /* Press layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -124,8 +124,8 @@ TEST_F(PermissiveHold, tap_regular_key_while_layer_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp index 67706f80dc..f2d576e875 100644 --- a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp @@ -36,13 +36,13 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_i set_keymap({mod_tap_hold_key, regular_key}); /* Press mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -71,13 +71,13 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_i set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); /* Press first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); first_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -107,13 +107,13 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key set_keymap({layer_tap_hold_key, regular_key, layer_key}); /* Press layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -126,8 +126,8 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp index 59ae77f781..b3d4e520f6 100644 --- a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp @@ -35,7 +35,7 @@ TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); @@ -49,4 +49,4 @@ TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) { mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp index cf23df8317..cd73f1e784 100644 --- a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp +++ b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp @@ -32,7 +32,7 @@ TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) { set_keymap({mod_tap_hold_key}); - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); @@ -57,7 +57,7 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { set_keymap({key_shift_hold_p_tap}); /* Press mod_tap_hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); key_shift_hold_p_tap.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -82,7 +82,7 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod_tap_hold key again */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); key_shift_hold_p_tap.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -95,7 +95,7 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod_tap_hold key again */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); key_shift_hold_p_tap.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); @@ -109,4 +109,4 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { key_shift_hold_p_tap.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp index 54e7daa22c..a67c6629e0 100644 --- a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp +++ b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp @@ -32,7 +32,7 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { /* Tap TT five times . */ /* TODO: Tapping Force Hold breaks TT */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_key.press(); run_one_scan_loop(); @@ -77,4 +77,4 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { run_one_scan_loop(); expect_layer_state(0); testing::Mock::VerifyAndClearExpectations(&driver); -} \ No newline at end of file +} diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp index 3ae7c4ccfd..04e66a02d9 100644 --- a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp @@ -36,19 +36,19 @@ TEST_F(TappingForceHold, tap_regular_key_while_mod_tap_key_is_held) { set_keymap({mod_tap_hold_key, regular_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -76,19 +76,19 @@ TEST_F(TappingForceHold, tap_mod_tap_key_while_mod_tap_key_is_held) { set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); /* Press first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); first_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -117,19 +117,19 @@ TEST_F(TappingForceHold, tap_regular_key_while_layer_tap_key_is_held) { set_keymap({layer_tap_hold_key, regular_key, layer_key}); /* Press layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); layer_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -152,7 +152,7 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -165,7 +165,7 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod-tap-hold key again. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -186,7 +186,7 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -199,7 +199,7 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod-tap-hold key again. */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); mod_tap_hold_key.press(); idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/test_common/test_driver.cpp b/tests/test_common/test_driver.cpp index 68f1dfd17d..86644ab6bd 100644 --- a/tests/test_common/test_driver.cpp +++ b/tests/test_common/test_driver.cpp @@ -18,6 +18,19 @@ TestDriver* TestDriver::m_this = nullptr; +namespace { +// Given a hex digit between 0 and 15, returns the corresponding keycode. +uint8_t hex_digit_to_keycode(uint8_t digit) { + // clang-format off + static const uint8_t hex_keycodes[] = { + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F + }; + // clang-format on + return hex_keycodes[digit]; +} +} // namespace + TestDriver::TestDriver() : m_driver{&TestDriver::keyboard_leds, &TestDriver::send_keyboard, &TestDriver::send_mouse, &TestDriver::send_system, &TestDriver::send_consumer} { host_set_driver(&m_driver); m_this = this; @@ -47,3 +60,25 @@ void TestDriver::send_system(uint16_t data) { void TestDriver::send_consumer(uint16_t data) { m_this->send_consumer(data); } + +namespace internal { +void expect_unicode_code_point(TestDriver& driver, uint32_t code_point) { + testing::InSequence seq; + EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_U)); + + bool print_zero = false; + for (int i = 7; i >= 0; --i) { + if (i <= 3) { + print_zero = true; + } + + const uint8_t digit = (code_point >> (i * 4)) & 0xf; + if (digit || print_zero) { + EXPECT_REPORT(driver, (hex_digit_to_keycode(digit))); + print_zero = true; + } + } + + EXPECT_REPORT(driver, (KC_SPC)); +} +} // namespace internal diff --git a/tests/test_common/test_driver.hpp b/tests/test_common/test_driver.hpp index f9197b3634..b58cfd1ebc 100644 --- a/tests/test_common/test_driver.hpp +++ b/tests/test_common/test_driver.hpp @@ -26,7 +26,9 @@ class TestDriver { public: TestDriver(); ~TestDriver(); - void set_leds(uint8_t leds) { m_leds = leds; } + void set_leds(uint8_t leds) { + m_leds = leds; + } MOCK_METHOD1(send_keyboard_mock, void(report_keyboard_t&)); MOCK_METHOD1(send_mouse_mock, void(report_mouse_t&)); @@ -43,3 +45,61 @@ class TestDriver { uint8_t m_leds = 0; static TestDriver* m_this; }; + +/** + * @brief Sets gmock expectation that a keyboard report of `report` keys will be sent. + * For this macro to parse correctly, the `report` arg must be surrounded by + * parentheses ( ). For instance, + * + * // Expect that a report of "KC_LSFT + KC_A" is sent to the host. + * EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + * + * is shorthand for + * + * EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); + * + * It is possible to use .Times() and other gmock APIS with EXPECT_REPORT, for instance, + * allow only single report to be sent: + * + * EXPECT_REPORT(driver, (KC_LSFT, KC_A)).Times(1); + */ +#define EXPECT_REPORT(driver, report) EXPECT_CALL((driver), send_keyboard_mock(KeyboardReport report)) + +/** + * @brief Sets gmock expectation that Unicode `code_point` is sent with UC_LNX input + * mode. For instance for U+2013, + * + * EXPECT_UNICODE(driver, 0x2013); + * + * expects the sequence of keys: + * + * "Ctrl+Shift+U, 2, 0, 1, 3, space". + */ +#define EXPECT_UNICODE(driver, code_point) internal::expect_unicode_code_point((driver), (code_point)) + +/** + * @brief Sets gmock expectation that a empty keyboard report will be sent. + * It is possible to use .Times() and other gmock APIS with EXPECT_EMPTY_REPORT, for instance, + * allow any number of empty reports with: + * + * EXPECT_EMPTY_REPORT(driver).Times(AnyNumber()); + */ +#define EXPECT_EMPTY_REPORT(driver) EXPECT_REPORT(driver, ()) + +/** + * @brief Sets gmock expectation that a keyboard report will be sent, without matching its content. + * It is possible to use .Times() and other gmock APIS with EXPECT_ANY_REPORT, for instance, + * allow a single arbitrary report with: + * + * EXPECT_ANY_REPORT(driver).Times(1); + */ +#define EXPECT_ANY_REPORT(driver) EXPECT_CALL((driver), send_keyboard_mock(_)) + +/** + * @brief Sets gmock expectation that no keyboard report will be sent at all. + */ +#define EXPECT_NO_REPORT(driver) EXPECT_ANY_REPORT(driver).Times(0) + +namespace internal { +void expect_unicode_code_point(TestDriver& driver, uint32_t code_point); +} // namespace internal diff --git a/tests/test_common/test_fixture.cpp b/tests/test_common/test_fixture.cpp index c98a679554..5fc6964054 100644 --- a/tests/test_common/test_fixture.cpp +++ b/tests/test_common/test_fixture.cpp @@ -82,7 +82,7 @@ TestFixture::~TestFixture() { testing::Mock::VerifyAndClearExpectations(&driver); /* Verify that the matrix really is cleared */ - EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); + EXPECT_NO_REPORT(driver); idle_for(TAPPING_TERM * 10); testing::Mock::VerifyAndClearExpectations(&driver); @@ -101,6 +101,13 @@ void TestFixture::add_key(KeymapKey key) { this->keymap.push_back(key); } +void TestFixture::tap_key(KeymapKey key, unsigned delay_ms) { + key.press(); + idle_for(delay_ms); + key.release(); + run_one_scan_loop(); +} + void TestFixture::set_keymap(std::initializer_list keys) { this->keymap.clear(); for (auto& key : keys) { diff --git a/tests/test_common/test_fixture.hpp b/tests/test_common/test_fixture.hpp index 73b5d8d3e8..81906f76c7 100644 --- a/tests/test_common/test_fixture.hpp +++ b/tests/test_common/test_fixture.hpp @@ -36,7 +36,22 @@ class TestFixture : public testing::Test { void add_key(const KeymapKey key); const KeymapKey* find_key(const layer_t layer_t, const keypos_t position) const; - void get_keycode(const layer_t layer, const keypos_t position, uint16_t* result) const; + void get_keycode(const layer_t layer, const keypos_t position, uint16_t* result) const; + + /** + * @brief Taps `key` with `delay_ms` delay between press and release. + */ + void tap_key(KeymapKey key, unsigned delay_ms = 1); + + /** + * @brief Taps multiple KeymapKey keys in order, e.g. `tap_keys(key_a, key_b)`. + */ + template + void tap_keys(Ts... keys) { + for (KeymapKey key : {keys...}) { + tap_key(key); + } + } void run_one_scan_loop(); void idle_for(unsigned ms); -- cgit v1.2.3 From 4c48760558808bb42c99934a0e2c330679d6c6cf Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sun, 5 Jun 2022 21:06:05 +0200 Subject: Apply EXPECT_REPORT and EXPECT_EMPTY_REPORT (#17311) ...convenience macros to test cases that where missed during #17284 --- .../default_mod_tap/test_tap_hold.cpp | 2 +- .../ignore_mod_tap_interrupt/test_tap_hold.cpp | 24 ++++++------- .../permissive_hold/test_one_shot_keys.cpp | 6 ++-- .../permissive_hold/test_tap_hold.cpp | 20 +++++------ .../test_tap_hold.cpp | 20 +++++------ .../retro_tapping/test_tap_hold.cpp | 8 ++--- .../retro_tapping/test_tapping.cpp | 28 +++++++-------- .../tapping_force_hold/test_action_layer.cpp | 4 +-- .../tapping_force_hold/test_tap_hold.cpp | 40 +++++++++++----------- 9 files changed, 76 insertions(+), 76 deletions(-) (limited to 'tests') diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp index ecb79c2560..687a4e0318 100644 --- a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp @@ -133,7 +133,7 @@ TEST_F(DefaultTapHold, tap_regular_key_while_layer_tap_key_is_held) { EXPECT_REPORT(driver, (KC_P)); EXPECT_REPORT(driver, (KC_P, KC_A)); EXPECT_REPORT(driver, (KC_P)); - EXPECT_CALL(driver, send_keyboard_mock(_)); + EXPECT_EMPTY_REPORT(driver); layer_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp index 5ece124c1d..319de61070 100644 --- a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp @@ -53,10 +53,10 @@ TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_A, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -89,10 +89,10 @@ TEST_F(IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_A, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); first_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -126,10 +126,10 @@ TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, regular_key.report_code))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_P, regular_key.report_code)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); layer_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp index 64a6ff58e6..1328b5fc0f 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp @@ -44,14 +44,14 @@ TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypres testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code))).Times(2); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code, osm_key.report_code))).Times(1); + EXPECT_REPORT(driver, (osm_key.report_code)).Times(2); + EXPECT_REPORT(driver, (regular_key.report_code, osm_key.report_code)).Times(1); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release OSM */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver).Times(1); osm_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp index 28fb17ca66..ef8d9a9c7f 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp @@ -46,15 +46,15 @@ TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, regular_key.report_code))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); + EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LSHIFT, regular_key.report_code)); + EXPECT_REPORT(driver, (KC_LSHIFT)); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -81,15 +81,15 @@ TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release second mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, second_mod_tap_hold_key.report_code))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); + EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LSHIFT, second_mod_tap_hold_key.report_code)); + EXPECT_REPORT(driver, (KC_LSHIFT)); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); first_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -117,8 +117,8 @@ TEST_F(PermissiveHold, tap_regular_key_while_layer_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(layer_key.report_code))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (layer_key.report_code)); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp index f2d576e875..ee7e707c94 100644 --- a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp @@ -48,15 +48,15 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_i testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -83,15 +83,15 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_i testing::Mock::VerifyAndClearExpectations(&driver); /* Release second tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); first_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -119,8 +119,8 @@ TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_B)); + EXPECT_EMPTY_REPORT(driver); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp index b3d4e520f6..dc0de0e44d 100644 --- a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp @@ -42,10 +42,10 @@ TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) { /* Release mod-tap-hold key. */ /* TODO: Why is LSHIFT send at all? */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp index cd73f1e784..42139d50da 100644 --- a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp +++ b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp @@ -37,13 +37,13 @@ TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) { idle_for(TAPPING_TERM); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -63,20 +63,20 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod_tap_hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); key_shift_hold_p_tap.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Press mod_tap_hold key again */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); + EXPECT_REPORT(driver, (KC_P)); key_shift_hold_p_tap.press(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod_tap_hold key again */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_EMPTY_REPORT(driver); key_shift_hold_p_tap.release(); idle_for(TAPPING_TERM + 1); testing::Mock::VerifyAndClearExpectations(&driver); @@ -88,8 +88,8 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod_tap_hold key again */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); key_shift_hold_p_tap.release(); idle_for(TAPPING_TERM + 1); testing::Mock::VerifyAndClearExpectations(&driver); @@ -102,10 +102,10 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { /* Release mod_tap_hold key again */ /* TODO: Why is KC_LSFT send? */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); key_shift_hold_p_tap.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp index a67c6629e0..965c702d7a 100644 --- a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp +++ b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp @@ -66,13 +66,13 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))).Times(1); + EXPECT_REPORT(driver, (KC_A)).Times(1); regular_key.press(); run_one_scan_loop(); expect_layer_state(0); testing::Mock::VerifyAndClearExpectations(&driver); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); + EXPECT_EMPTY_REPORT(driver).Times(1); regular_key.release(); run_one_scan_loop(); expect_layer_state(0); diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp index 04e66a02d9..2671862f2d 100644 --- a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp @@ -54,15 +54,15 @@ TEST_F(TappingForceHold, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Idle for tapping term of mod tap hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); idle_for(TAPPING_TERM - 3); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -94,15 +94,15 @@ TEST_F(TappingForceHold, tap_mod_tap_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release first mod-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); + EXPECT_REPORT(driver, (KC_LSFT)); first_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); /* Idle for tapping term of first mod tap hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); idle_for(TAPPING_TERM - 3); testing::Mock::VerifyAndClearExpectations(&driver); } @@ -135,10 +135,10 @@ TEST_F(TappingForceHold, tap_regular_key_while_layer_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release layer-tap-hold key */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(_)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_A, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); layer_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -158,8 +158,8 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -171,8 +171,8 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -192,8 +192,8 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -205,8 +205,8 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT))); - EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); + EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); -- cgit v1.2.3 From 1706da9054f8c4aa77493062a8937a7b64970a9e Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Mon, 13 Jun 2022 22:12:55 +0200 Subject: tap-dance: Restructure code and document in more detail (#16394) --- tests/tapdance/config.h | 19 +++ tests/tapdance/examples.c | 199 ++++++++++++++++++++++++ tests/tapdance/examples.h | 33 ++++ tests/tapdance/test.mk | 22 +++ tests/tapdance/test_examples.cpp | 319 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 592 insertions(+) create mode 100644 tests/tapdance/config.h create mode 100644 tests/tapdance/examples.c create mode 100644 tests/tapdance/examples.h create mode 100644 tests/tapdance/test.mk create mode 100644 tests/tapdance/test_examples.cpp (limited to 'tests') diff --git a/tests/tapdance/config.h b/tests/tapdance/config.h new file mode 100644 index 0000000000..6aada3efd3 --- /dev/null +++ b/tests/tapdance/config.h @@ -0,0 +1,19 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "test_common.h" diff --git a/tests/tapdance/examples.c b/tests/tapdance/examples.c new file mode 100644 index 0000000000..4a5be41b08 --- /dev/null +++ b/tests/tapdance/examples.c @@ -0,0 +1,199 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "quantum.h" +#include "examples.h" + +// Example code from the tap dance documentation, adapted for testing + +// clang-format off + +// Example 1 + +void dance_egg(qk_tap_dance_state_t *state, void *user_data) { + if (state->count >= 100) { + // SEND_STRING("Safety dance!"); + tap_code(KC_C); + reset_tap_dance(state); + } +} + + +// Example 2 + +void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) { + switch (state->count) { + case 1: + register_code(KC_3); + break; + case 2: + register_code(KC_2); + break; + case 3: + register_code(KC_1); + break; + case 4: + unregister_code(KC_3); + // wait_ms(50); + unregister_code(KC_2); + // wait_ms(50); + unregister_code(KC_1); + } +} + +void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) { + if (state->count >= 4) { + // reset_keyboard(); + tap_code(KC_R); + } +} + +void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) { + unregister_code(KC_1); + // wait_ms(50); + unregister_code(KC_2); + // wait_ms(50); + unregister_code(KC_3); +} + + +// Example 3 + +typedef struct { + uint16_t tap; + uint16_t hold; + uint16_t held; +} tap_dance_tap_hold_t; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + qk_tap_dance_action_t *action; + + switch (keycode) { + case TD(CT_CLN): + action = &tap_dance_actions[TD_INDEX(keycode)]; + if (!record->event.pressed && action->state.count && !action->state.finished) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; + tap_code16(tap_hold->tap); + } + } + return true; +} + +void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; + + if (state->pressed) { + if (state->count == 1 +#ifndef PERMISSIVE_HOLD + && !state->interrupted +#endif + ) { + register_code16(tap_hold->hold); + tap_hold->held = tap_hold->hold; + } else { + register_code16(tap_hold->tap); + tap_hold->held = tap_hold->tap; + } + } +} + +void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; + + if (tap_hold->held) { + unregister_code16(tap_hold->held); + tap_hold->held = 0; + } +} + +#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \ + { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), } + + +// Example 4 + +typedef enum { + TD_NONE, + TD_UNKNOWN, + TD_SINGLE_TAP, + TD_SINGLE_HOLD, + TD_DOUBLE_TAP, + TD_DOUBLE_HOLD, + TD_DOUBLE_SINGLE_TAP, + TD_TRIPLE_TAP, + TD_TRIPLE_HOLD +} td_state_t; + +typedef struct { + bool is_press_action; + td_state_t state; +} td_tap_t; + +td_state_t cur_dance(qk_tap_dance_state_t *state) { + if (state->count == 1) { + if (state->interrupted || !state->pressed) return TD_SINGLE_TAP; + else return TD_SINGLE_HOLD; + } else if (state->count == 2) { + if (state->interrupted) return TD_DOUBLE_SINGLE_TAP; + else if (state->pressed) return TD_DOUBLE_HOLD; + else return TD_DOUBLE_TAP; + } + + if (state->count == 3) { + if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP; + else return TD_TRIPLE_HOLD; + } else return TD_UNKNOWN; +} + +static td_tap_t xtap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +void x_finished(qk_tap_dance_state_t *state, void *user_data) { + xtap_state.state = cur_dance(state); + switch (xtap_state.state) { + case TD_SINGLE_TAP: register_code(KC_X); break; + case TD_SINGLE_HOLD: register_code(KC_LCTL); break; + case TD_DOUBLE_TAP: register_code(KC_ESC); break; + case TD_DOUBLE_HOLD: register_code(KC_LALT); break; + case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X); + default: break; // Not present in documentation + } +} + +void x_reset(qk_tap_dance_state_t *state, void *user_data) { + switch (xtap_state.state) { + case TD_SINGLE_TAP: unregister_code(KC_X); break; + case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break; + case TD_DOUBLE_TAP: unregister_code(KC_ESC); break; + case TD_DOUBLE_HOLD: unregister_code(KC_LALT); + case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X); + default: break; // Not present in documentation + } + xtap_state.state = TD_NONE; +} + + +qk_tap_dance_action_t tap_dance_actions[] = { + [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), + [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg), + [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset), + [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN), + [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset) +}; + +// clang-format on diff --git a/tests/tapdance/examples.h b/tests/tapdance/examples.h new file mode 100644 index 0000000000..2622af6b2f --- /dev/null +++ b/tests/tapdance/examples.h @@ -0,0 +1,33 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + TD_ESC_CAPS, + CT_EGG, + CT_FLSH, + CT_CLN, + X_CTL, +}; + +#ifdef __cplusplus +} +#endif diff --git a/tests/tapdance/test.mk b/tests/tapdance/test.mk new file mode 100644 index 0000000000..041d9b4dc9 --- /dev/null +++ b/tests/tapdance/test.mk @@ -0,0 +1,22 @@ +# Copyright 2022 Jouke Witteveen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +TAP_DANCE_ENABLE = yes + +SRC += examples.c diff --git a/tests/tapdance/test_examples.cpp b/tests/tapdance/test_examples.cpp new file mode 100644 index 0000000000..e67e6cb907 --- /dev/null +++ b/tests/tapdance/test_examples.cpp @@ -0,0 +1,319 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "action_tapping.h" +#include "test_keymap_key.hpp" +#include "examples.h" + +using testing::_; +using testing::InSequence; + +class TapDance : public TestFixture {}; + +TEST_F(TapDance, DoubleTap) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + + set_keymap({key_esc_caps}); + + /* The tap dance key does nothing on the first press */ + key_esc_caps.press(); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_NO_REPORT(driver); + + /* We get the key press and the release on timeout */ + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap gets us the second key */ + tap_key(key_esc_caps); + EXPECT_NO_REPORT(driver); + key_esc_caps.press(); + EXPECT_REPORT(driver, (KC_CAPS)); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DoubleTapWithMod) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + auto key_shift = KeymapKey{0, 2, 0, KC_LSFT}; + + set_keymap({key_esc_caps, key_shift}); + + /* The tap dance key does nothing on the first press */ + key_shift.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + key_esc_caps.press(); + run_one_scan_loop(); + + key_esc_caps.release(); + key_shift.release(); + EXPECT_EMPTY_REPORT(driver); + + /* We get the key press and the release */ + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_ESC)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap gets us the second key */ + key_shift.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + tap_key(key_esc_caps); + EXPECT_NO_REPORT(driver); + key_shift.release(); + key_esc_caps.press(); + EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS)); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DoubleTapInterrupted) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({key_esc_caps, regular_key}); + + /* Interrupted double tap */ + tap_key(key_esc_caps); + regular_key.press(); + /* Immediate tap of the first key */ + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + /* Followed by the interrupting key */ + EXPECT_REPORT(driver, (KC_A)); + run_one_scan_loop(); + regular_key.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Second tap after being interrupted acts as a single tap */ + key_esc_caps.press(); + run_one_scan_loop(); + key_esc_caps.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DanceFn) { + TestDriver driver; + InSequence s; + auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG)); + + set_keymap({key_egg}); + + /* 99 taps do nothing */ + for (int i = 0; i < 99; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + + /* 100 taps trigger the action */ + for (int i = 0; i < 100; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* 250 taps act the same as 100 taps */ + /* Taps are counted in an uint8_t, so the count overflows after 255 taps */ + for (int i = 0; i < 250; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DanceFnAdvanced) { + TestDriver driver; + InSequence s; + auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH)); + + set_keymap({key_flsh}); + + /* Three taps don't trigger a reset */ + EXPECT_REPORT(driver, (KC_3)); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); + for (int i = 0; i < 3; i++) { + run_one_scan_loop(); + key_flsh.press(); + run_one_scan_loop(); + key_flsh.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Four taps trigger a reset */ + EXPECT_REPORT(driver, (KC_3)); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); + EXPECT_REPORT(driver, (KC_2, KC_1)); + EXPECT_REPORT(driver, (KC_1)); + EXPECT_EMPTY_REPORT(driver); + for (int i = 0; i < 4; i++) { + run_one_scan_loop(); + key_flsh.press(); + run_one_scan_loop(); + key_flsh.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, TapHold) { + TestDriver driver; + InSequence s; + auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)}; + + set_keymap({key_cln}); + + /* Short taps fire on release */ + key_cln.press(); + run_one_scan_loop(); + key_cln.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Holds immediate following a tap apply to the tap key */ + key_cln.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); + idle_for(TAPPING_TERM * 2); + key_cln.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Holds trigger the hold key */ + key_cln.press(); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + EXPECT_REPORT(driver, (KC_SCLN)); + run_one_scan_loop(); + key_cln.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, QuadFunction) { + TestDriver driver; + InSequence s; + auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)}; + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({key_quad, regular_key}); + + /* Single tap */ + key_quad.press(); + run_one_scan_loop(); + key_quad.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Single hold */ + key_quad.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LCTL)); + run_one_scan_loop(); + key_quad.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap */ + tap_key(key_quad); + key_quad.press(); + run_one_scan_loop(); + key_quad.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap and hold */ + tap_key(key_quad); + key_quad.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LALT)); + run_one_scan_loop(); + key_quad.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double single tap */ + tap_key(key_quad); + tap_key(key_quad); + regular_key.press(); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_A)); + run_one_scan_loop(); + regular_key.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} -- cgit v1.2.3 From 050fa9062f6a62ee2adefde17e6634edd79d92fc Mon Sep 17 00:00:00 2001 From: Jouke Witteveen Date: Thu, 16 Jun 2022 08:05:27 +0200 Subject: tap-dance: Rename tests so that tap_dance is used consistently (#17396) --- tests/tap_dance/config.h | 19 +++ tests/tap_dance/examples.c | 199 ++++++++++++++++++++++++ tests/tap_dance/examples.h | 33 ++++ tests/tap_dance/test.mk | 22 +++ tests/tap_dance/test_examples.cpp | 319 ++++++++++++++++++++++++++++++++++++++ tests/tapdance/config.h | 19 --- tests/tapdance/examples.c | 199 ------------------------ tests/tapdance/examples.h | 33 ---- tests/tapdance/test.mk | 22 --- tests/tapdance/test_examples.cpp | 319 -------------------------------------- 10 files changed, 592 insertions(+), 592 deletions(-) create mode 100644 tests/tap_dance/config.h create mode 100644 tests/tap_dance/examples.c create mode 100644 tests/tap_dance/examples.h create mode 100644 tests/tap_dance/test.mk create mode 100644 tests/tap_dance/test_examples.cpp delete mode 100644 tests/tapdance/config.h delete mode 100644 tests/tapdance/examples.c delete mode 100644 tests/tapdance/examples.h delete mode 100644 tests/tapdance/test.mk delete mode 100644 tests/tapdance/test_examples.cpp (limited to 'tests') diff --git a/tests/tap_dance/config.h b/tests/tap_dance/config.h new file mode 100644 index 0000000000..6aada3efd3 --- /dev/null +++ b/tests/tap_dance/config.h @@ -0,0 +1,19 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "test_common.h" diff --git a/tests/tap_dance/examples.c b/tests/tap_dance/examples.c new file mode 100644 index 0000000000..4a5be41b08 --- /dev/null +++ b/tests/tap_dance/examples.c @@ -0,0 +1,199 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "quantum.h" +#include "examples.h" + +// Example code from the tap dance documentation, adapted for testing + +// clang-format off + +// Example 1 + +void dance_egg(qk_tap_dance_state_t *state, void *user_data) { + if (state->count >= 100) { + // SEND_STRING("Safety dance!"); + tap_code(KC_C); + reset_tap_dance(state); + } +} + + +// Example 2 + +void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) { + switch (state->count) { + case 1: + register_code(KC_3); + break; + case 2: + register_code(KC_2); + break; + case 3: + register_code(KC_1); + break; + case 4: + unregister_code(KC_3); + // wait_ms(50); + unregister_code(KC_2); + // wait_ms(50); + unregister_code(KC_1); + } +} + +void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) { + if (state->count >= 4) { + // reset_keyboard(); + tap_code(KC_R); + } +} + +void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) { + unregister_code(KC_1); + // wait_ms(50); + unregister_code(KC_2); + // wait_ms(50); + unregister_code(KC_3); +} + + +// Example 3 + +typedef struct { + uint16_t tap; + uint16_t hold; + uint16_t held; +} tap_dance_tap_hold_t; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + qk_tap_dance_action_t *action; + + switch (keycode) { + case TD(CT_CLN): + action = &tap_dance_actions[TD_INDEX(keycode)]; + if (!record->event.pressed && action->state.count && !action->state.finished) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; + tap_code16(tap_hold->tap); + } + } + return true; +} + +void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; + + if (state->pressed) { + if (state->count == 1 +#ifndef PERMISSIVE_HOLD + && !state->interrupted +#endif + ) { + register_code16(tap_hold->hold); + tap_hold->held = tap_hold->hold; + } else { + register_code16(tap_hold->tap); + tap_hold->held = tap_hold->tap; + } + } +} + +void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) { + tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; + + if (tap_hold->held) { + unregister_code16(tap_hold->held); + tap_hold->held = 0; + } +} + +#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \ + { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), } + + +// Example 4 + +typedef enum { + TD_NONE, + TD_UNKNOWN, + TD_SINGLE_TAP, + TD_SINGLE_HOLD, + TD_DOUBLE_TAP, + TD_DOUBLE_HOLD, + TD_DOUBLE_SINGLE_TAP, + TD_TRIPLE_TAP, + TD_TRIPLE_HOLD +} td_state_t; + +typedef struct { + bool is_press_action; + td_state_t state; +} td_tap_t; + +td_state_t cur_dance(qk_tap_dance_state_t *state) { + if (state->count == 1) { + if (state->interrupted || !state->pressed) return TD_SINGLE_TAP; + else return TD_SINGLE_HOLD; + } else if (state->count == 2) { + if (state->interrupted) return TD_DOUBLE_SINGLE_TAP; + else if (state->pressed) return TD_DOUBLE_HOLD; + else return TD_DOUBLE_TAP; + } + + if (state->count == 3) { + if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP; + else return TD_TRIPLE_HOLD; + } else return TD_UNKNOWN; +} + +static td_tap_t xtap_state = { + .is_press_action = true, + .state = TD_NONE +}; + +void x_finished(qk_tap_dance_state_t *state, void *user_data) { + xtap_state.state = cur_dance(state); + switch (xtap_state.state) { + case TD_SINGLE_TAP: register_code(KC_X); break; + case TD_SINGLE_HOLD: register_code(KC_LCTL); break; + case TD_DOUBLE_TAP: register_code(KC_ESC); break; + case TD_DOUBLE_HOLD: register_code(KC_LALT); break; + case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X); + default: break; // Not present in documentation + } +} + +void x_reset(qk_tap_dance_state_t *state, void *user_data) { + switch (xtap_state.state) { + case TD_SINGLE_TAP: unregister_code(KC_X); break; + case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break; + case TD_DOUBLE_TAP: unregister_code(KC_ESC); break; + case TD_DOUBLE_HOLD: unregister_code(KC_LALT); + case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X); + default: break; // Not present in documentation + } + xtap_state.state = TD_NONE; +} + + +qk_tap_dance_action_t tap_dance_actions[] = { + [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), + [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg), + [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset), + [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN), + [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset) +}; + +// clang-format on diff --git a/tests/tap_dance/examples.h b/tests/tap_dance/examples.h new file mode 100644 index 0000000000..2622af6b2f --- /dev/null +++ b/tests/tap_dance/examples.h @@ -0,0 +1,33 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + TD_ESC_CAPS, + CT_EGG, + CT_FLSH, + CT_CLN, + X_CTL, +}; + +#ifdef __cplusplus +} +#endif diff --git a/tests/tap_dance/test.mk b/tests/tap_dance/test.mk new file mode 100644 index 0000000000..041d9b4dc9 --- /dev/null +++ b/tests/tap_dance/test.mk @@ -0,0 +1,22 @@ +# Copyright 2022 Jouke Witteveen +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# -------------------------------------------------------------------------------- +# Keep this file, even if it is empty, as a marker that this folder contains tests +# -------------------------------------------------------------------------------- + +TAP_DANCE_ENABLE = yes + +SRC += examples.c diff --git a/tests/tap_dance/test_examples.cpp b/tests/tap_dance/test_examples.cpp new file mode 100644 index 0000000000..e67e6cb907 --- /dev/null +++ b/tests/tap_dance/test_examples.cpp @@ -0,0 +1,319 @@ +/* Copyright 2022 Jouke Witteveen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "action_tapping.h" +#include "test_keymap_key.hpp" +#include "examples.h" + +using testing::_; +using testing::InSequence; + +class TapDance : public TestFixture {}; + +TEST_F(TapDance, DoubleTap) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + + set_keymap({key_esc_caps}); + + /* The tap dance key does nothing on the first press */ + key_esc_caps.press(); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_NO_REPORT(driver); + + /* We get the key press and the release on timeout */ + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap gets us the second key */ + tap_key(key_esc_caps); + EXPECT_NO_REPORT(driver); + key_esc_caps.press(); + EXPECT_REPORT(driver, (KC_CAPS)); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DoubleTapWithMod) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + auto key_shift = KeymapKey{0, 2, 0, KC_LSFT}; + + set_keymap({key_esc_caps, key_shift}); + + /* The tap dance key does nothing on the first press */ + key_shift.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + key_esc_caps.press(); + run_one_scan_loop(); + + key_esc_caps.release(); + key_shift.release(); + EXPECT_EMPTY_REPORT(driver); + + /* We get the key press and the release */ + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_ESC)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap gets us the second key */ + key_shift.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + tap_key(key_esc_caps); + EXPECT_NO_REPORT(driver); + key_shift.release(); + key_esc_caps.press(); + EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS)); + run_one_scan_loop(); + key_esc_caps.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DoubleTapInterrupted) { + TestDriver driver; + InSequence s; + auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({key_esc_caps, regular_key}); + + /* Interrupted double tap */ + tap_key(key_esc_caps); + regular_key.press(); + /* Immediate tap of the first key */ + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + /* Followed by the interrupting key */ + EXPECT_REPORT(driver, (KC_A)); + run_one_scan_loop(); + regular_key.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Second tap after being interrupted acts as a single tap */ + key_esc_caps.press(); + run_one_scan_loop(); + key_esc_caps.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DanceFn) { + TestDriver driver; + InSequence s; + auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG)); + + set_keymap({key_egg}); + + /* 99 taps do nothing */ + for (int i = 0; i < 99; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + + /* 100 taps trigger the action */ + for (int i = 0; i < 100; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* 250 taps act the same as 100 taps */ + /* Taps are counted in an uint8_t, so the count overflows after 255 taps */ + for (int i = 0; i < 250; i++) { + run_one_scan_loop(); + key_egg.press(); + run_one_scan_loop(); + key_egg.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_C)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, DanceFnAdvanced) { + TestDriver driver; + InSequence s; + auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH)); + + set_keymap({key_flsh}); + + /* Three taps don't trigger a reset */ + EXPECT_REPORT(driver, (KC_3)); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); + for (int i = 0; i < 3; i++) { + run_one_scan_loop(); + key_flsh.press(); + run_one_scan_loop(); + key_flsh.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Four taps trigger a reset */ + EXPECT_REPORT(driver, (KC_3)); + EXPECT_REPORT(driver, (KC_3, KC_2)); + EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); + EXPECT_REPORT(driver, (KC_2, KC_1)); + EXPECT_REPORT(driver, (KC_1)); + EXPECT_EMPTY_REPORT(driver); + for (int i = 0; i < 4; i++) { + run_one_scan_loop(); + key_flsh.press(); + run_one_scan_loop(); + key_flsh.release(); + } + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_R)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, TapHold) { + TestDriver driver; + InSequence s; + auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)}; + + set_keymap({key_cln}); + + /* Short taps fire on release */ + key_cln.press(); + run_one_scan_loop(); + key_cln.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Holds immediate following a tap apply to the tap key */ + key_cln.press(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); + idle_for(TAPPING_TERM * 2); + key_cln.release(); + EXPECT_REPORT(driver, (KC_LSFT)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Holds trigger the hold key */ + key_cln.press(); + idle_for(TAPPING_TERM); + run_one_scan_loop(); + EXPECT_REPORT(driver, (KC_SCLN)); + run_one_scan_loop(); + key_cln.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} + +TEST_F(TapDance, QuadFunction) { + TestDriver driver; + InSequence s; + auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)}; + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({key_quad, regular_key}); + + /* Single tap */ + key_quad.press(); + run_one_scan_loop(); + key_quad.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Single hold */ + key_quad.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LCTL)); + run_one_scan_loop(); + key_quad.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap */ + tap_key(key_quad); + key_quad.press(); + run_one_scan_loop(); + key_quad.release(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_ESC)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double tap and hold */ + tap_key(key_quad); + key_quad.press(); + run_one_scan_loop(); + idle_for(TAPPING_TERM); + EXPECT_REPORT(driver, (KC_LALT)); + run_one_scan_loop(); + key_quad.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + + /* Double single tap */ + tap_key(key_quad); + tap_key(key_quad); + regular_key.press(); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_X)); + EXPECT_EMPTY_REPORT(driver); + EXPECT_REPORT(driver, (KC_A)); + run_one_scan_loop(); + regular_key.release(); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); +} diff --git a/tests/tapdance/config.h b/tests/tapdance/config.h deleted file mode 100644 index 6aada3efd3..0000000000 --- a/tests/tapdance/config.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright 2022 Jouke Witteveen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "test_common.h" diff --git a/tests/tapdance/examples.c b/tests/tapdance/examples.c deleted file mode 100644 index 4a5be41b08..0000000000 --- a/tests/tapdance/examples.c +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright 2022 Jouke Witteveen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "quantum.h" -#include "examples.h" - -// Example code from the tap dance documentation, adapted for testing - -// clang-format off - -// Example 1 - -void dance_egg(qk_tap_dance_state_t *state, void *user_data) { - if (state->count >= 100) { - // SEND_STRING("Safety dance!"); - tap_code(KC_C); - reset_tap_dance(state); - } -} - - -// Example 2 - -void dance_flsh_each(qk_tap_dance_state_t *state, void *user_data) { - switch (state->count) { - case 1: - register_code(KC_3); - break; - case 2: - register_code(KC_2); - break; - case 3: - register_code(KC_1); - break; - case 4: - unregister_code(KC_3); - // wait_ms(50); - unregister_code(KC_2); - // wait_ms(50); - unregister_code(KC_1); - } -} - -void dance_flsh_finished(qk_tap_dance_state_t *state, void *user_data) { - if (state->count >= 4) { - // reset_keyboard(); - tap_code(KC_R); - } -} - -void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) { - unregister_code(KC_1); - // wait_ms(50); - unregister_code(KC_2); - // wait_ms(50); - unregister_code(KC_3); -} - - -// Example 3 - -typedef struct { - uint16_t tap; - uint16_t hold; - uint16_t held; -} tap_dance_tap_hold_t; - -bool process_record_user(uint16_t keycode, keyrecord_t *record) { - qk_tap_dance_action_t *action; - - switch (keycode) { - case TD(CT_CLN): - action = &tap_dance_actions[TD_INDEX(keycode)]; - if (!record->event.pressed && action->state.count && !action->state.finished) { - tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)action->user_data; - tap_code16(tap_hold->tap); - } - } - return true; -} - -void tap_dance_tap_hold_finished(qk_tap_dance_state_t *state, void *user_data) { - tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; - - if (state->pressed) { - if (state->count == 1 -#ifndef PERMISSIVE_HOLD - && !state->interrupted -#endif - ) { - register_code16(tap_hold->hold); - tap_hold->held = tap_hold->hold; - } else { - register_code16(tap_hold->tap); - tap_hold->held = tap_hold->tap; - } - } -} - -void tap_dance_tap_hold_reset(qk_tap_dance_state_t *state, void *user_data) { - tap_dance_tap_hold_t *tap_hold = (tap_dance_tap_hold_t *)user_data; - - if (tap_hold->held) { - unregister_code16(tap_hold->held); - tap_hold->held = 0; - } -} - -#define ACTION_TAP_DANCE_TAP_HOLD(tap, hold) \ - { .fn = {NULL, tap_dance_tap_hold_finished, tap_dance_tap_hold_reset}, .user_data = (void *)&((tap_dance_tap_hold_t){tap, hold, 0}), } - - -// Example 4 - -typedef enum { - TD_NONE, - TD_UNKNOWN, - TD_SINGLE_TAP, - TD_SINGLE_HOLD, - TD_DOUBLE_TAP, - TD_DOUBLE_HOLD, - TD_DOUBLE_SINGLE_TAP, - TD_TRIPLE_TAP, - TD_TRIPLE_HOLD -} td_state_t; - -typedef struct { - bool is_press_action; - td_state_t state; -} td_tap_t; - -td_state_t cur_dance(qk_tap_dance_state_t *state) { - if (state->count == 1) { - if (state->interrupted || !state->pressed) return TD_SINGLE_TAP; - else return TD_SINGLE_HOLD; - } else if (state->count == 2) { - if (state->interrupted) return TD_DOUBLE_SINGLE_TAP; - else if (state->pressed) return TD_DOUBLE_HOLD; - else return TD_DOUBLE_TAP; - } - - if (state->count == 3) { - if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP; - else return TD_TRIPLE_HOLD; - } else return TD_UNKNOWN; -} - -static td_tap_t xtap_state = { - .is_press_action = true, - .state = TD_NONE -}; - -void x_finished(qk_tap_dance_state_t *state, void *user_data) { - xtap_state.state = cur_dance(state); - switch (xtap_state.state) { - case TD_SINGLE_TAP: register_code(KC_X); break; - case TD_SINGLE_HOLD: register_code(KC_LCTL); break; - case TD_DOUBLE_TAP: register_code(KC_ESC); break; - case TD_DOUBLE_HOLD: register_code(KC_LALT); break; - case TD_DOUBLE_SINGLE_TAP: tap_code(KC_X); register_code(KC_X); - default: break; // Not present in documentation - } -} - -void x_reset(qk_tap_dance_state_t *state, void *user_data) { - switch (xtap_state.state) { - case TD_SINGLE_TAP: unregister_code(KC_X); break; - case TD_SINGLE_HOLD: unregister_code(KC_LCTL); break; - case TD_DOUBLE_TAP: unregister_code(KC_ESC); break; - case TD_DOUBLE_HOLD: unregister_code(KC_LALT); - case TD_DOUBLE_SINGLE_TAP: unregister_code(KC_X); - default: break; // Not present in documentation - } - xtap_state.state = TD_NONE; -} - - -qk_tap_dance_action_t tap_dance_actions[] = { - [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS), - [CT_EGG] = ACTION_TAP_DANCE_FN(dance_egg), - [CT_FLSH] = ACTION_TAP_DANCE_FN_ADVANCED(dance_flsh_each, dance_flsh_finished, dance_flsh_reset), - [CT_CLN] = ACTION_TAP_DANCE_TAP_HOLD(KC_COLN, KC_SCLN), - [X_CTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset) -}; - -// clang-format on diff --git a/tests/tapdance/examples.h b/tests/tapdance/examples.h deleted file mode 100644 index 2622af6b2f..0000000000 --- a/tests/tapdance/examples.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright 2022 Jouke Witteveen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - TD_ESC_CAPS, - CT_EGG, - CT_FLSH, - CT_CLN, - X_CTL, -}; - -#ifdef __cplusplus -} -#endif diff --git a/tests/tapdance/test.mk b/tests/tapdance/test.mk deleted file mode 100644 index 041d9b4dc9..0000000000 --- a/tests/tapdance/test.mk +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2022 Jouke Witteveen -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# -------------------------------------------------------------------------------- -# Keep this file, even if it is empty, as a marker that this folder contains tests -# -------------------------------------------------------------------------------- - -TAP_DANCE_ENABLE = yes - -SRC += examples.c diff --git a/tests/tapdance/test_examples.cpp b/tests/tapdance/test_examples.cpp deleted file mode 100644 index e67e6cb907..0000000000 --- a/tests/tapdance/test_examples.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* Copyright 2022 Jouke Witteveen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "keyboard_report_util.hpp" -#include "keycode.h" -#include "test_common.hpp" -#include "action_tapping.h" -#include "test_keymap_key.hpp" -#include "examples.h" - -using testing::_; -using testing::InSequence; - -class TapDance : public TestFixture {}; - -TEST_F(TapDance, DoubleTap) { - TestDriver driver; - InSequence s; - auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; - - set_keymap({key_esc_caps}); - - /* The tap dance key does nothing on the first press */ - key_esc_caps.press(); - run_one_scan_loop(); - key_esc_caps.release(); - EXPECT_NO_REPORT(driver); - - /* We get the key press and the release on timeout */ - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_ESC)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Double tap gets us the second key */ - tap_key(key_esc_caps); - EXPECT_NO_REPORT(driver); - key_esc_caps.press(); - EXPECT_REPORT(driver, (KC_CAPS)); - run_one_scan_loop(); - key_esc_caps.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, DoubleTapWithMod) { - TestDriver driver; - InSequence s; - auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; - auto key_shift = KeymapKey{0, 2, 0, KC_LSFT}; - - set_keymap({key_esc_caps, key_shift}); - - /* The tap dance key does nothing on the first press */ - key_shift.press(); - EXPECT_REPORT(driver, (KC_LSFT)); - run_one_scan_loop(); - key_esc_caps.press(); - run_one_scan_loop(); - - key_esc_caps.release(); - key_shift.release(); - EXPECT_EMPTY_REPORT(driver); - - /* We get the key press and the release */ - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_REPORT(driver, (KC_LSFT, KC_ESC)); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Double tap gets us the second key */ - key_shift.press(); - EXPECT_REPORT(driver, (KC_LSFT)); - run_one_scan_loop(); - tap_key(key_esc_caps); - EXPECT_NO_REPORT(driver); - key_shift.release(); - key_esc_caps.press(); - EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS)); - run_one_scan_loop(); - key_esc_caps.release(); - EXPECT_REPORT(driver, (KC_LSFT)); - run_one_scan_loop(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, DoubleTapInterrupted) { - TestDriver driver; - InSequence s; - auto key_esc_caps = KeymapKey{0, 1, 0, TD(TD_ESC_CAPS)}; - auto regular_key = KeymapKey(0, 2, 0, KC_A); - - set_keymap({key_esc_caps, regular_key}); - - /* Interrupted double tap */ - tap_key(key_esc_caps); - regular_key.press(); - /* Immediate tap of the first key */ - EXPECT_REPORT(driver, (KC_ESC)); - EXPECT_EMPTY_REPORT(driver); - /* Followed by the interrupting key */ - EXPECT_REPORT(driver, (KC_A)); - run_one_scan_loop(); - regular_key.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Second tap after being interrupted acts as a single tap */ - key_esc_caps.press(); - run_one_scan_loop(); - key_esc_caps.release(); - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_ESC)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, DanceFn) { - TestDriver driver; - InSequence s; - auto key_egg = KeymapKey(0, 1, 0, TD(CT_EGG)); - - set_keymap({key_egg}); - - /* 99 taps do nothing */ - for (int i = 0; i < 99; i++) { - run_one_scan_loop(); - key_egg.press(); - run_one_scan_loop(); - key_egg.release(); - } - idle_for(TAPPING_TERM); - EXPECT_NO_REPORT(driver); - run_one_scan_loop(); - - /* 100 taps trigger the action */ - for (int i = 0; i < 100; i++) { - run_one_scan_loop(); - key_egg.press(); - run_one_scan_loop(); - key_egg.release(); - } - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_C)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* 250 taps act the same as 100 taps */ - /* Taps are counted in an uint8_t, so the count overflows after 255 taps */ - for (int i = 0; i < 250; i++) { - run_one_scan_loop(); - key_egg.press(); - run_one_scan_loop(); - key_egg.release(); - } - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_C)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, DanceFnAdvanced) { - TestDriver driver; - InSequence s; - auto key_flsh = KeymapKey(0, 1, 0, TD(CT_FLSH)); - - set_keymap({key_flsh}); - - /* Three taps don't trigger a reset */ - EXPECT_REPORT(driver, (KC_3)); - EXPECT_REPORT(driver, (KC_3, KC_2)); - EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); - for (int i = 0; i < 3; i++) { - run_one_scan_loop(); - key_flsh.press(); - run_one_scan_loop(); - key_flsh.release(); - } - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_3, KC_2)); - EXPECT_REPORT(driver, (KC_3)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Four taps trigger a reset */ - EXPECT_REPORT(driver, (KC_3)); - EXPECT_REPORT(driver, (KC_3, KC_2)); - EXPECT_REPORT(driver, (KC_3, KC_2, KC_1)); - EXPECT_REPORT(driver, (KC_2, KC_1)); - EXPECT_REPORT(driver, (KC_1)); - EXPECT_EMPTY_REPORT(driver); - for (int i = 0; i < 4; i++) { - run_one_scan_loop(); - key_flsh.press(); - run_one_scan_loop(); - key_flsh.release(); - } - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_R)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, TapHold) { - TestDriver driver; - InSequence s; - auto key_cln = KeymapKey{0, 1, 0, TD(CT_CLN)}; - - set_keymap({key_cln}); - - /* Short taps fire on release */ - key_cln.press(); - run_one_scan_loop(); - key_cln.release(); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Holds immediate following a tap apply to the tap key */ - key_cln.press(); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_REPORT(driver, (KC_LSFT, KC_SCLN)); - idle_for(TAPPING_TERM * 2); - key_cln.release(); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Holds trigger the hold key */ - key_cln.press(); - idle_for(TAPPING_TERM); - run_one_scan_loop(); - EXPECT_REPORT(driver, (KC_SCLN)); - run_one_scan_loop(); - key_cln.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} - -TEST_F(TapDance, QuadFunction) { - TestDriver driver; - InSequence s; - auto key_quad = KeymapKey{0, 1, 0, TD(X_CTL)}; - auto regular_key = KeymapKey(0, 2, 0, KC_A); - - set_keymap({key_quad, regular_key}); - - /* Single tap */ - key_quad.press(); - run_one_scan_loop(); - key_quad.release(); - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_X)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Single hold */ - key_quad.press(); - run_one_scan_loop(); - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_LCTL)); - run_one_scan_loop(); - key_quad.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Double tap */ - tap_key(key_quad); - key_quad.press(); - run_one_scan_loop(); - key_quad.release(); - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_ESC)); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Double tap and hold */ - tap_key(key_quad); - key_quad.press(); - run_one_scan_loop(); - idle_for(TAPPING_TERM); - EXPECT_REPORT(driver, (KC_LALT)); - run_one_scan_loop(); - key_quad.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); - - /* Double single tap */ - tap_key(key_quad); - tap_key(key_quad); - regular_key.press(); - EXPECT_REPORT(driver, (KC_X)); - EXPECT_EMPTY_REPORT(driver); - EXPECT_REPORT(driver, (KC_X)); - EXPECT_EMPTY_REPORT(driver); - EXPECT_REPORT(driver, (KC_A)); - run_one_scan_loop(); - regular_key.release(); - EXPECT_EMPTY_REPORT(driver); - run_one_scan_loop(); -} -- cgit v1.2.3 From f27b617f36d55ac5469247016a1b79304f892366 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Sat, 6 Aug 2022 12:51:13 +0200 Subject: [Core] Process all changed keys in one scan loop, deprecate `QMK_KEYS_PER_SCAN` (#15292) --- tests/basic/test_keypress.cpp | 22 ---------------------- tests/tap_dance/test_examples.cpp | 3 +-- 2 files changed, 1 insertion(+), 24 deletions(-) (limited to 'tests') diff --git a/tests/basic/test_keypress.cpp b/tests/basic/test_keypress.cpp index bb68ced557..6d5b502a00 100644 --- a/tests/basic/test_keypress.cpp +++ b/tests/basic/test_keypress.cpp @@ -64,11 +64,7 @@ TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) { key_b.press(); key_c.press(); - // Note that QMK only processes one key at a time - // See issue #1476 for more information EXPECT_REPORT(driver, (key_b.report_code)); - keyboard_task(); - EXPECT_REPORT(driver, (key_b.report_code, key_c.report_code)); keyboard_task(); @@ -76,8 +72,6 @@ TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) { key_c.release(); // Note that the first key released is the first one in the matrix order EXPECT_REPORT(driver, (key_c.report_code)); - keyboard_task(); - EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -92,10 +86,7 @@ TEST_F(KeyPress, LeftShiftIsReportedCorrectly) { key_lsft.press(); key_a.press(); - // Unfortunately modifiers are also processed in the wrong order - // See issue #1476 for more information EXPECT_REPORT(driver, (key_a.report_code)); - keyboard_task(); EXPECT_REPORT(driver, (key_a.report_code, key_lsft.report_code)); keyboard_task(); @@ -118,11 +109,7 @@ TEST_F(KeyPress, PressLeftShiftAndControl) { key_lsft.press(); key_lctrl.press(); - // Unfortunately modifiers are also processed in the wrong order - // See issue #1476 for more information EXPECT_REPORT(driver, (key_lsft.report_code)); - keyboard_task(); - EXPECT_REPORT(driver, (key_lsft.report_code, key_lctrl.report_code)); keyboard_task(); @@ -130,8 +117,6 @@ TEST_F(KeyPress, PressLeftShiftAndControl) { key_lctrl.release(); EXPECT_REPORT(driver, (key_lctrl.report_code)); - keyboard_task(); - EXPECT_EMPTY_REPORT(driver); keyboard_task(); } @@ -145,20 +130,13 @@ TEST_F(KeyPress, LeftAndRightShiftCanBePressedAtTheSameTime) { key_lsft.press(); key_rsft.press(); - // Unfortunately modifiers are also processed in the wrong order - // See issue #1476 for more information EXPECT_REPORT(driver, (key_lsft.report_code)); - keyboard_task(); - EXPECT_REPORT(driver, (key_lsft.report_code, key_rsft.report_code)); keyboard_task(); key_lsft.release(); key_rsft.release(); - EXPECT_REPORT(driver, (key_rsft.report_code)); - keyboard_task(); - EXPECT_EMPTY_REPORT(driver); keyboard_task(); } diff --git a/tests/tap_dance/test_examples.cpp b/tests/tap_dance/test_examples.cpp index e67e6cb907..6dabc45513 100644 --- a/tests/tap_dance/test_examples.cpp +++ b/tests/tap_dance/test_examples.cpp @@ -92,10 +92,9 @@ TEST_F(TapDance, DoubleTapWithMod) { key_shift.release(); key_esc_caps.press(); EXPECT_REPORT(driver, (KC_LSFT, KC_CAPS)); + EXPECT_REPORT(driver, (KC_CAPS)); run_one_scan_loop(); key_esc_caps.release(); - EXPECT_REPORT(driver, (KC_LSFT)); - run_one_scan_loop(); EXPECT_EMPTY_REPORT(driver); run_one_scan_loop(); } -- cgit v1.2.3 From 6a0d90f81a9b9938591b32f9321530e68e5cea0b Mon Sep 17 00:00:00 2001 From: Pascal Getreuer <50221757+getreuer@users.noreply.github.com> Date: Sat, 13 Aug 2022 06:48:51 -0700 Subject: Fix Caps Word capitalization when used with Combos + Auto Shift. (#17549) --- .../test_caps_word_autoshift.cpp | 64 +++++-- tests/caps_word/caps_word_combo/config.h | 20 ++ tests/caps_word/caps_word_combo/test.mk | 19 ++ .../caps_word_combo/test_caps_word_combo.cpp | 212 +++++++++++++++++++++ tests/test_common/test_fixture.cpp | 16 ++ tests/test_common/test_fixture.hpp | 7 + 6 files changed, 324 insertions(+), 14 deletions(-) create mode 100644 tests/caps_word/caps_word_combo/config.h create mode 100644 tests/caps_word/caps_word_combo/test.mk create mode 100644 tests/caps_word/caps_word_combo/test_caps_word_combo.cpp (limited to 'tests') diff --git a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp b/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp index deb4d95766..ba21c527a6 100644 --- a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp +++ b/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp @@ -19,6 +19,14 @@ #include "test_fixture.hpp" #include "test_keymap_key.hpp" +// Allow reports with no keys or only KC_LSFT. +// clang-format off +#define EXPECT_EMPTY_OR_LSFT(driver) \ + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( \ + KeyboardReport(), \ + KeyboardReport(KC_LSFT)))) +// clang-format on + using ::testing::_; using ::testing::AnyNumber; using ::testing::AnyOf; @@ -39,13 +47,7 @@ TEST_F(CapsWord, AutoShiftKeys) { KeymapKey key_spc(0, 1, 0, KC_SPC); set_keymap({key_a, key_spc}); - // Allow any number of reports with no keys or only KC_LSFT. - // clang-format off - EXPECT_CALL(driver, send_keyboard_mock(AnyOf( - KeyboardReport(), - KeyboardReport(KC_LSFT)))) - .Times(AnyNumber()); - // clang-format on + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); { // Expect: "A, A, space, a". InSequence s; EXPECT_REPORT(driver, (KC_LSFT, KC_A)); @@ -65,6 +67,46 @@ TEST_F(CapsWord, AutoShiftKeys) { testing::Mock::VerifyAndClearExpectations(&driver); } +// Test Caps Word + Auto Shift where keys A and B are rolled. +TEST_F(CapsWord, AutoShiftRolledShiftedKeys) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_b(0, 0, 1, KC_B); + set_keymap({key_a, key_b}); + + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); + { // Expect: "A, B, A, B". + InSequence s; + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + } + + caps_word_on(); + + key_a.press(); // Overlapping taps: A down, B down, A up, B up. + run_one_scan_loop(); + key_b.press(); + run_one_scan_loop(); + key_a.release(); + run_one_scan_loop(); + key_b.release(); + run_one_scan_loop(); + + key_a.press(); // Nested taps: A down, B down, B up, A up. + run_one_scan_loop(); + key_b.press(); + run_one_scan_loop(); + key_b.release(); + run_one_scan_loop(); + key_a.release(); + run_one_scan_loop(); + + caps_word_off(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + // Tests that with tap-hold keys with Retro Shift, letter keys are shifted by // Caps Word regardless of whether they are retroshifted. TEST_F(CapsWord, RetroShiftKeys) { @@ -73,13 +115,7 @@ TEST_F(CapsWord, RetroShiftKeys) { KeymapKey key_layertap_b(0, 1, 0, LT(1, KC_B)); set_keymap({key_modtap_a, key_layertap_b}); - // Allow any number of reports with no keys or only KC_LSFT. - // clang-format off - EXPECT_CALL(driver, send_keyboard_mock(AnyOf( - KeyboardReport(), - KeyboardReport(KC_LSFT)))) - .Times(AnyNumber()); - // clang-format on + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); { // Expect: "B, A, B, A". InSequence s; EXPECT_REPORT(driver, (KC_LSFT, KC_B)); diff --git a/tests/caps_word/caps_word_combo/config.h b/tests/caps_word/caps_word_combo/config.h new file mode 100644 index 0000000000..92dbe045b2 --- /dev/null +++ b/tests/caps_word/caps_word_combo/config.h @@ -0,0 +1,20 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once + +#include "test_common.h" + +#define TAPPING_TERM 200 diff --git a/tests/caps_word/caps_word_combo/test.mk b/tests/caps_word/caps_word_combo/test.mk new file mode 100644 index 0000000000..9f2e157189 --- /dev/null +++ b/tests/caps_word/caps_word_combo/test.mk @@ -0,0 +1,19 @@ +# Copyright 2022 Google LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +CAPS_WORD_ENABLE = yes +COMBO_ENABLE = yes +AUTO_SHIFT_ENABLE = yes + diff --git a/tests/caps_word/caps_word_combo/test_caps_word_combo.cpp b/tests/caps_word/caps_word_combo/test_caps_word_combo.cpp new file mode 100644 index 0000000000..3a0530b854 --- /dev/null +++ b/tests/caps_word/caps_word_combo/test_caps_word_combo.cpp @@ -0,0 +1,212 @@ +// Copyright 2022 Google LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// Test Caps Word + Combos, with and without Auto Shift. + +#include +#include +#include + +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +// Allow reports with no keys or only KC_LSFT. +// clang-format off +#define EXPECT_EMPTY_OR_LSFT(driver) \ + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( \ + KeyboardReport(), \ + KeyboardReport(KC_LSFT)))) +// clang-format on + +using ::testing::AnyNumber; +using ::testing::AnyOf; +using ::testing::InSequence; +using ::testing::TestParamInfo; + +extern "C" { +// Define some combos to use for the test, including overlapping combos and +// combos that chord tap-hold keys. +enum combo_events { AB_COMBO, BC_COMBO, AD_COMBO, DE_COMBO, FGHI_COMBO, COMBO_LENGTH }; +uint16_t COMBO_LEN = COMBO_LENGTH; + +const uint16_t ab_combo[] PROGMEM = {KC_A, KC_B, COMBO_END}; +const uint16_t bc_combo[] PROGMEM = {KC_B, KC_C, COMBO_END}; +const uint16_t ad_combo[] PROGMEM = {KC_A, LCTL_T(KC_D), COMBO_END}; +const uint16_t de_combo[] PROGMEM = {LCTL_T(KC_D), LT(1, KC_E), COMBO_END}; +const uint16_t fghi_combo[] PROGMEM = {KC_F, KC_G, KC_H, KC_I, COMBO_END}; + +// clang-format off +combo_t key_combos[] = { + [AB_COMBO] = COMBO(ab_combo, KC_SPC), // KC_A + KC_B = KC_SPC + [BC_COMBO] = COMBO(bc_combo, KC_X), // KC_B + KC_C = KC_X + [AD_COMBO] = COMBO(ad_combo, KC_Y), // KC_A + LCTL_T(KC_D) = KC_Y + [DE_COMBO] = COMBO(de_combo, KC_Z), // LCTL_T(KC_D) + LT(1, KC_E) = KC_Z + [FGHI_COMBO] = COMBO(fghi_combo, KC_W) // KC_F + KC_G + KC_H + KC_I = KC_W +}; +// clang-format on +} // extern "C" + +namespace { + +// To test combos thorougly, we test them with pressing the chord keys with +// a few different orders and timings. +struct TestParams { + std::string name; + bool autoshift_on; + + static const std::string& GetName(const TestParamInfo& info) { + return info.param.name; + } +}; + +class CapsWord : public ::testing::WithParamInterface, public TestFixture { + public: + void SetUp() override { + caps_word_off(); + if (GetParam().autoshift_on) { + autoshift_enable(); + } else { + autoshift_disable(); + } + } +}; + +// Test pressing the keys in a combo with different orders and timings. +TEST_P(CapsWord, SingleCombo) { + TestDriver driver; + KeymapKey key_b(0, 0, 1, KC_B); + KeymapKey key_c(0, 0, 2, KC_C); + set_keymap({key_b, key_c}); + + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); + EXPECT_REPORT(driver, (KC_LSFT, KC_X)); + + caps_word_on(); + tap_combo({key_b, key_c}); + + EXPECT_TRUE(is_caps_word_on()); + caps_word_off(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Test a longer 4-key combo. +TEST_P(CapsWord, LongerCombo) { + TestDriver driver; + KeymapKey key_f(0, 0, 0, KC_F); + KeymapKey key_g(0, 0, 1, KC_G); + KeymapKey key_h(0, 0, 2, KC_H); + KeymapKey key_i(0, 0, 3, KC_I); + set_keymap({key_f, key_g, key_h, key_i}); + + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); + EXPECT_REPORT(driver, (KC_LSFT, KC_W)); + + caps_word_on(); + tap_combo({key_f, key_g, key_h, key_i}); + + EXPECT_TRUE(is_caps_word_on()); + caps_word_off(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Test with two overlapping combos on regular keys: +// KC_A + KC_B = KC_SPC, +// KC_B + KC_C = KC_X. +TEST_P(CapsWord, ComboRegularKeys) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_b(0, 0, 1, KC_B); + KeymapKey key_c(0, 0, 2, KC_C); + KeymapKey key_1(0, 0, 3, KC_1); + set_keymap({key_a, key_b, key_c, key_1}); + + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); + { // Expect: "A, B, 1, X, 1, C, space, a". + InSequence s; + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + EXPECT_REPORT(driver, (KC_1)); + EXPECT_REPORT(driver, (KC_LSFT, KC_X)); + EXPECT_REPORT(driver, (KC_1)); + EXPECT_REPORT(driver, (KC_LSFT, KC_C)); + EXPECT_REPORT(driver, (KC_SPC)); + EXPECT_REPORT(driver, (KC_A)); + } + + caps_word_on(); + tap_key(key_a); + tap_key(key_b); + tap_key(key_1); + tap_combo({key_b, key_c}); // BC combo types "x". + tap_key(key_1); + tap_key(key_c); + tap_combo({key_a, key_b}); // AB combo types space. + tap_key(key_a); + + EXPECT_FALSE(is_caps_word_on()); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Test where combo chords involve tap-hold keys: +// KC_A + LCTL_T(KC_D) = KC_Y, +// LCTL_T(KC_D) + LT(1, KC_E) = KC_Z, +TEST_P(CapsWord, ComboModTapKey) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_modtap_d(0, 0, 1, LCTL_T(KC_D)); + KeymapKey key_layertap_e(0, 0, 2, LT(1, KC_E)); + set_keymap({key_a, key_modtap_d, key_layertap_e}); + + EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber()); + { // Expect: "A, D, E, Y, Z". + InSequence s; + EXPECT_REPORT(driver, (KC_LSFT, KC_A)); + EXPECT_REPORT(driver, (KC_LSFT, KC_D)); + EXPECT_REPORT(driver, (KC_LSFT, KC_E)); + EXPECT_REPORT(driver, (KC_LSFT, KC_Y)); + EXPECT_REPORT(driver, (KC_LSFT, KC_Z)); + } + + caps_word_on(); + tap_key(key_a); + tap_key(key_modtap_d); + tap_key(key_layertap_e); + tap_combo({key_a, key_modtap_d}); // AD combo types "y". + tap_combo({key_modtap_d, key_layertap_e}); // DE combo types "z". + + EXPECT_TRUE(is_caps_word_on()); + caps_word_off(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P( + Combos, + CapsWord, + ::testing::Values( + TestParams{"AutoshiftDisabled", false}, + TestParams{"AutoshiftEnabled", true} + ), + TestParams::GetName + ); +// clang-format on + +} // namespace diff --git a/tests/test_common/test_fixture.cpp b/tests/test_common/test_fixture.cpp index 5fc6964054..44694cd390 100644 --- a/tests/test_common/test_fixture.cpp +++ b/tests/test_common/test_fixture.cpp @@ -108,6 +108,22 @@ void TestFixture::tap_key(KeymapKey key, unsigned delay_ms) { run_one_scan_loop(); } +void TestFixture::tap_combo(const std::vector& chord_keys, unsigned delay_ms) { + for (KeymapKey key : chord_keys) { // Press each key. + key.press(); + run_one_scan_loop(); + } + + if (delay_ms > 1) { + idle_for(delay_ms - 1); + } + + for (KeymapKey key : chord_keys) { // Release each key. + key.release(); + run_one_scan_loop(); + } +} + void TestFixture::set_keymap(std::initializer_list keys) { this->keymap.clear(); for (auto& key : keys) { diff --git a/tests/test_common/test_fixture.hpp b/tests/test_common/test_fixture.hpp index 81906f76c7..2590acd006 100644 --- a/tests/test_common/test_fixture.hpp +++ b/tests/test_common/test_fixture.hpp @@ -53,6 +53,13 @@ class TestFixture : public testing::Test { } } + /** + * @brief Taps a combo with `delay_ms` delay between press and release. + * + * Example: `tap_combo({key_a, key_b})` to tap the chord A + B. + */ + void tap_combo(const std::vector& chord_keys, unsigned delay_ms = 1); + void run_one_scan_loop(); void idle_for(unsigned ms); -- cgit v1.2.3 From 95c43a275984fb57cdf6e5afd02190700e0205bc Mon Sep 17 00:00:00 2001 From: Pascal Getreuer <50221757+getreuer@users.noreply.github.com> Date: Sun, 14 Aug 2022 12:25:32 -0700 Subject: Fix Caps Word to treat mod-taps more consistently. (#17463) * Fix Caps Word to treat mod-taps more consistently. Previously, holding any mod-tap key while Caps Word is active stops Caps Word, and this happens regardless of `caps_word_press_user()`. Yet for regular mod keys, AltGr (KC_RALT) is ignored, Shift keys are passed to `caps_word_press_user()` to determine whether to continue, and similarly, a key `RSFT(KC_RALT)` representing Right Shift + Alt is passed to `caps_word_press_user()` to determine whether to continue. This commit makes held mod-tap keys consistent with regular mod keys: * Holding a `RALT_T` mod-tap is ignored. * When holding a shift mod-tap key, `KC_LSFT` or `KC_RSFT` is passed to `caps_word_press_user()` to determine whether to continue. * When holding a Right Shift + Alt (`RSA_T`) mod-tap, `RSFT(KC_RALT)` is passed to `caps_word_press_user()`. Particularly, with this fix a user may choose to continue Caps Word when a shift mod-tap key is held by adding `KC_LSFT` and `KC_RSFT` cases in `caps_word_press_user()`. For instance as ``` bool caps_word_press_user(uint16_t keycode) { switch (keycode) { // Keycodes that continue Caps Word, with shift applied. case KC_A ... KC_Z: case KC_MINS: add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key. return true; // Keycodes that continue Caps Word, without shifting. case KC_1 ... KC_0: case KC_BSPC: case KC_DEL: case KC_UNDS: case KC_LSFT: // <<< Added here. case KC_RSFT: return true; default: return false; // Deactivate Caps Word. } } ``` * Fix Caps Word to treat mod-taps more consistently. Previously, holding any mod-tap key while Caps Word is active stops Caps Word, and this happens regardless of `caps_word_press_user()`. Yet for regular mod keys, AltGr (KC_RALT) is ignored, Shift keys are passed to `caps_word_press_user()` to determine whether to continue, and similarly, a key `RSFT(KC_RALT)` representing Right Shift + Alt is passed to `caps_word_press_user()` to determine whether to continue. This commit makes held mod-tap keys consistent with regular mod keys: * Holding a `RALT_T` mod-tap is ignored. * When holding a shift mod-tap key, `KC_LSFT` or `KC_RSFT` is passed to `caps_word_press_user()` to determine whether to continue. * When holding a Right Shift + Alt (`RSA_T`) mod-tap, `RSFT(KC_RALT)` is passed to `caps_word_press_user()`. Particularly, with this fix a user may choose to continue Caps Word when a shift mod-tap key is held by adding `KC_LSFT` and `KC_RSFT` cases in `caps_word_press_user()`. For instance as ``` bool caps_word_press_user(uint16_t keycode) { switch (keycode) { // Keycodes that continue Caps Word, with shift applied. case KC_A ... KC_Z: case KC_MINS: add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key. return true; // Keycodes that continue Caps Word, without shifting. case KC_1 ... KC_0: case KC_BSPC: case KC_DEL: case KC_UNDS: case KC_LSFT: // <<< Added here. case KC_RSFT: return true; default: return false; // Deactivate Caps Word. } } ``` * Update quantum/process_keycode/process_caps_word.c Co-authored-by: Joel Challis --- tests/caps_word/test_caps_word.cpp | 159 +++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) (limited to 'tests') diff --git a/tests/caps_word/test_caps_word.cpp b/tests/caps_word/test_caps_word.cpp index 0af4b0175d..3f59ed3744 100644 --- a/tests/caps_word/test_caps_word.cpp +++ b/tests/caps_word/test_caps_word.cpp @@ -25,10 +25,47 @@ using ::testing::AnyOf; using ::testing::InSequence; using ::testing::TestParamInfo; +namespace { + +bool press_user_default(uint16_t keycode) { + switch (keycode) { + // Keycodes that continue Caps Word, with shift applied. + case KC_A ... KC_Z: + case KC_MINS: + add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key. + return true; + + // Keycodes that continue Caps Word, without shifting. + case KC_1 ... KC_0: + case KC_BSPC: + case KC_DEL: + case KC_UNDS: + return true; + + default: + return false; // Deactivate Caps Word. + } +} + +uint16_t passed_keycode; +bool press_user_save_passed_keycode(uint16_t keycode) { + passed_keycode = keycode; + return true; +} + +bool (*press_user_fun)(uint16_t) = press_user_default; + +extern "C" { +bool caps_word_press_user(uint16_t keycode) { + return press_user_fun(keycode); +} +} // extern "C" + class CapsWord : public TestFixture { public: void SetUp() override { caps_word_off(); + press_user_fun = press_user_default; } }; @@ -226,6 +263,126 @@ TEST_F(CapsWord, ShiftsAltGrSymbols) { testing::Mock::VerifyAndClearExpectations(&driver); } +// Tests typing "AltGr + A" using a mod-tap key. +TEST_F(CapsWord, ShiftsModTapAltGrSymbols) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_altgr_t(0, 1, 0, RALT_T(KC_B)); + set_keymap({key_a, key_altgr_t}); + + // Allow any number of reports with no keys or only modifiers. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_RALT), + KeyboardReport(KC_LSFT, KC_RALT)))) + .Times(AnyNumber()); + // Expect "Shift + AltGr + A". + EXPECT_REPORT(driver, (KC_LSFT, KC_RALT, KC_A)); + // clang-format on + + // Turn on Caps Word and type "AltGr + A". + caps_word_on(); + + key_altgr_t.press(); + idle_for(TAPPING_TERM + 1); + tap_key(key_a); + run_one_scan_loop(); + key_altgr_t.release(); + + EXPECT_TRUE(is_caps_word_on()); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +struct CapsWordPressUserParams { + std::string name; + uint16_t keycode; + uint16_t delay_ms; + uint16_t expected_passed_keycode; + bool continues_caps_word; + + static const std::string& GetName(const TestParamInfo& info) { + return info.param.name; + } +}; + +class CapsWordPressUser : public ::testing::WithParamInterface, public CapsWord { + void SetUp() override { + caps_word_on(); + passed_keycode = KC_NO; + press_user_fun = press_user_save_passed_keycode; + } +}; + +// Tests keycodes passed to caps_word_press_user() function for various keys. +TEST_P(CapsWordPressUser, KeyCode) { + TestDriver driver; + KeymapKey key(0, 0, 0, GetParam().keycode); + set_keymap({key}); + + EXPECT_ANY_REPORT(driver).Times(AnyNumber()); + tap_key(key, GetParam().delay_ms); + + EXPECT_EQ(passed_keycode, GetParam().expected_passed_keycode); + EXPECT_EQ(is_caps_word_on(), GetParam().continues_caps_word); + clear_oneshot_mods(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +const uint16_t LT_1_KC_A = LT(1, KC_A); +// clang-format off +INSTANTIATE_TEST_CASE_P( + PressUser, + CapsWordPressUser, + ::testing::Values( + CapsWordPressUserParams{ + "KC_A", KC_A, 1, KC_A, true}, + CapsWordPressUserParams{ + "KC_HASH", KC_HASH, 1, KC_HASH, true}, + CapsWordPressUserParams{ + "KC_LSFT", KC_LSFT, 1, KC_LSFT, true}, + CapsWordPressUserParams{ + "KC_RSFT", KC_RSFT, 1, KC_RSFT, true}, + CapsWordPressUserParams{ + "LSFT_T_tapped", LSFT_T(KC_A), 1, KC_A, true}, + CapsWordPressUserParams{ + "LSFT_T_held", LSFT_T(KC_A), TAPPING_TERM + 1, KC_LSFT, true}, + CapsWordPressUserParams{ + "RSFT_T_held", RSFT_T(KC_A), TAPPING_TERM + 1, KC_RSFT, true}, + CapsWordPressUserParams{ + "RSA_T_held", RSA_T(KC_A), TAPPING_TERM + 1, RSFT(KC_RALT), true}, + // Holding a mod-tap other than Shift or AltGr stops Caps Word. + CapsWordPressUserParams{ + "LCTL_T_held", LCTL_T(KC_A), TAPPING_TERM + 1, KC_NO, false}, + CapsWordPressUserParams{ + "LALT_T_held", LALT_T(KC_A), TAPPING_TERM + 1, KC_NO, false}, + CapsWordPressUserParams{ + "LGUI_T_held", LGUI_T(KC_A), TAPPING_TERM + 1, KC_NO, false}, + // Layer keys are ignored and continue Caps Word. + CapsWordPressUserParams{ + "MO", MO(1), 1, KC_NO, true}, + CapsWordPressUserParams{ + "TO", TO(1), 1, KC_NO, true}, + CapsWordPressUserParams{ + "TG", TG(1), 1, KC_NO, true}, + CapsWordPressUserParams{ + "TT", TT(1), 1, KC_NO, true}, + CapsWordPressUserParams{ + "OSL", OSL(1), 1, KC_NO, true}, + CapsWordPressUserParams{ + "LT_held", LT_1_KC_A, TAPPING_TERM + 1, KC_NO, true}, + // AltGr keys are ignored and continue Caps Word. + CapsWordPressUserParams{ + "KC_RALT", KC_RALT, 1, KC_NO, true}, + CapsWordPressUserParams{ + "OSM_MOD_RALT", OSM(MOD_RALT), 1, KC_NO, true}, + CapsWordPressUserParams{ + "RALT_T_held", RALT_T(KC_A), TAPPING_TERM + 1, KC_NO, true} + ), + CapsWordPressUserParams::GetName + ); +// clang-format on + struct CapsWordBothShiftsParams { std::string name; uint16_t left_shift_keycode; @@ -435,3 +592,5 @@ INSTANTIATE_TEST_CASE_P( CapsWordDoubleTapShiftParams::GetName ); // clang-format on + +} // namespace -- cgit v1.2.3 From 8ce946b5c8e7026b5d7337becf4719e2795af9bb Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Mon, 15 Aug 2022 16:40:51 +0200 Subject: [Bug] Add key event check to `is_tap_record` and remove `is_tap_key` (#18063) --- tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'tests') diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp index 687a4e0318..e798265623 100644 --- a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp @@ -140,8 +140,6 @@ TEST_F(DefaultTapHold, tap_regular_key_while_layer_tap_key_is_held) { } TEST_F(DefaultTapHold, tap_mod_tap_hold_key_two_times) { - GTEST_SKIP() << "TODO:Holding a modtap key results in out of bounds access to the keymap, this is a bug in QMK."; - TestDriver driver; InSequence s; auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); @@ -175,8 +173,6 @@ TEST_F(DefaultTapHold, tap_mod_tap_hold_key_two_times) { } TEST_F(DefaultTapHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { - GTEST_SKIP() << "TODO:Holding a modtap key results in out of bounds access to the keymap, this is a bug in QMK."; - TestDriver driver; InSequence s; auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); -- cgit v1.2.3 From 456d6f33426946d632ed52a3278b5fcd0c398644 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 20 Sep 2022 07:52:43 +0100 Subject: Remove legacy keycodes from unit tests (#18430) --- .../default_mod_tap/test_tap_hold.cpp | 2 +- .../permissive_hold/test_tap_hold.cpp | 12 ++++++------ .../tap_hold_configurations/retro_tapping/test_tap_hold.cpp | 2 +- .../tapping_force_hold/test_tap_hold.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp index e798265623..b70efe4aed 100644 --- a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp @@ -213,7 +213,7 @@ TEST_F(DefaultTapHold, tap_and_hold_mod_tap_hold_key) { set_keymap({mod_tap_hold_key}); /* Press mod-tap-hold key. */ - EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); mod_tap_hold_key.press(); idle_for(TAPPING_TERM + 1); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp index ef8d9a9c7f..74e81f347f 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp @@ -46,9 +46,9 @@ TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release regular key */ - EXPECT_REPORT(driver, (KC_LSHIFT)); - EXPECT_REPORT(driver, (KC_LSHIFT, regular_key.report_code)); - EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, regular_key.report_code)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); regular_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); @@ -81,9 +81,9 @@ TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release second mod-tap-hold key */ - EXPECT_REPORT(driver, (KC_LSHIFT)); - EXPECT_REPORT(driver, (KC_LSHIFT, second_mod_tap_hold_key.report_code)); - EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT, second_mod_tap_hold_key.report_code)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); second_mod_tap_hold_key.release(); run_one_scan_loop(); testing::Mock::VerifyAndClearExpectations(&driver); diff --git a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp index dc0de0e44d..e08c600dbd 100644 --- a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp @@ -42,7 +42,7 @@ TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) { /* Release mod-tap-hold key. */ /* TODO: Why is LSHIFT send at all? */ - EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); EXPECT_EMPTY_REPORT(driver); EXPECT_REPORT(driver, (KC_P)); EXPECT_EMPTY_REPORT(driver); diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp index 2671862f2d..604f9a4a54 100644 --- a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp @@ -205,7 +205,7 @@ TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { testing::Mock::VerifyAndClearExpectations(&driver); /* Release mod-tap-hold key. */ - EXPECT_REPORT(driver, (KC_LSHIFT)); + EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); EXPECT_EMPTY_REPORT(driver); mod_tap_hold_key.release(); run_one_scan_loop(); -- cgit v1.2.3