From 4ae75259233a45583b6a0d73f1f7224cb50e0398 Mon Sep 17 00:00:00 2001 From: Felix Kuehling <67731127+fxkuehl@users.noreply.github.com> Date: Mon, 28 Nov 2022 03:16:38 -0500 Subject: Bug17281 - Retain momentary layers until the end of tapping (#17282) * Make process_tapping more readable Move most #ifdefs into conditionally defined macros to make the logic easier to follow. * Retain momentary layers until the end of tapping This allows mod-tap and layer-tap keys on layers to behave as expected. Bug: https://github.com/qmk/qmk_firmware/issues/17281 * Add tests for delayed mod/layer release while tapping Mods and layer key release is delayed while tapping is in progress to ensure that the tap is registered with the modifier state and on the layer where the key was first pressed. Signed-off-by: Felix Kuehling --- tests/basic/test_tapping.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'tests') diff --git a/tests/basic/test_tapping.cpp b/tests/basic/test_tapping.cpp index 6ff9cfe22b..faf9b9fe91 100644 --- a/tests/basic/test_tapping.cpp +++ b/tests/basic/test_tapping.cpp @@ -121,3 +121,72 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { key_shift_hold_p_tap.release(); run_one_scan_loop(); } + +TEST_F(Tapping, TapA_CTL_T_KeyWhileReleasingShift) { + TestDriver driver; + InSequence s; + auto shift_key = KeymapKey(0, 7, 0, KC_LSFT); + auto mod_tap_hold_key = KeymapKey(0, 8, 0, CTL_T(KC_P)); + + set_keymap({shift_key, mod_tap_hold_key}); + + shift_key.press(); + // Shift is reported + EXPECT_REPORT(driver, (KC_LSFT)); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + mod_tap_hold_key.press(); + // Tapping keys does nothing on press + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + + shift_key.release(); + // Releasing shift is delayed while tapping is in progress + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + mod_tap_hold_key.release(); + // Releasing mod-tap key reports the tap and releases shift + EXPECT_REPORT(driver, (KC_LSFT, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(Tapping, TapA_CTL_T_KeyWhileReleasingLayer) { + TestDriver driver; + InSequence s; + auto layer_key = KeymapKey(0, 7, 0, MO(1)); + auto trans_key = KeymapKey(1, 7, 0, KC_TRNS); + auto mod_tap_hold_key0 = KeymapKey(0, 8, 0, CTL_T(KC_P)); + auto mod_tap_hold_key1 = KeymapKey(1, 8, 0, CTL_T(KC_Q)); + + set_keymap({layer_key, trans_key, mod_tap_hold_key0, mod_tap_hold_key1}); + + layer_key.press(); + // Pressing the layer key does nothing + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + + mod_tap_hold_key1.press(); + // Tapping layer 1 mod-tap key does nothing on press + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + + layer_key.release(); + // Releasing layer is delayed while tapping is in progress + EXPECT_NO_REPORT(driver); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + mod_tap_hold_key1.release(); + // Releasing mod-tap key reports the tap of the layer 1 key + // If delayed layer release is broken, this reports the layer 0 key + EXPECT_REPORT(driver, (KC_Q)); + EXPECT_EMPTY_REPORT(driver); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} -- cgit v1.2.3 From cbabc8dbe6a8476d3082e8bc649d330f87e7b904 Mon Sep 17 00:00:00 2001 From: Albert Y <76888457+filterpaper@users.noreply.github.com> Date: Mon, 12 Dec 2022 23:52:22 +0800 Subject: [Core] Replace Tapping Force Hold feature with Quick Tap Term (#17007) * Replace Tapping Force Hold feature with Quick Tap Term * Replace keyboard level TAPPING_FORCE_HOLD with QUICK_TAP_TERM 0 * Deprecate force hold in info_config.json * Before and after quick tap term unit tests * Quick tap unit tests iteration * Keymap config.h correction * Remove TAPPING_FORCE_HOLD_PER_KEY macros that were missed * Add two more test cases for quick tap * Replace TAPPING_FORCE_HOLD with QUICK_TAP_TERM in configs #2 * Replace TAPPING_FORCE_HOLD_PER_KEY with QUICK_TAP_TERM_PER_KEY in configs #2 * Add function declaration for get_quick_tap_term Co-authored-by: Stefan Kerkmann --- tests/tap_hold_configurations/quick_tap/config.h | 21 ++ tests/tap_hold_configurations/quick_tap/test.mk | 18 ++ .../quick_tap/test_action_layer.cpp | 82 ++++++ .../quick_tap/test_quick_tap.cpp | 291 +++++++++++++++++++++ .../tapping_force_hold/config.h | 21 -- .../tapping_force_hold/test.mk | 18 -- .../tapping_force_hold/test_action_layer.cpp | 80 ------ .../tapping_force_hold/test_tap_hold.cpp | 213 --------------- 8 files changed, 412 insertions(+), 332 deletions(-) create mode 100644 tests/tap_hold_configurations/quick_tap/config.h create mode 100644 tests/tap_hold_configurations/quick_tap/test.mk create mode 100644 tests/tap_hold_configurations/quick_tap/test_action_layer.cpp create mode 100644 tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp delete mode 100644 tests/tap_hold_configurations/tapping_force_hold/config.h delete mode 100644 tests/tap_hold_configurations/tapping_force_hold/test.mk delete mode 100644 tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp delete mode 100644 tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp (limited to 'tests') diff --git a/tests/tap_hold_configurations/quick_tap/config.h b/tests/tap_hold_configurations/quick_tap/config.h new file mode 100644 index 0000000000..cd82d3b5a5 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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 QUICK_TAP_TERM 100 diff --git a/tests/tap_hold_configurations/quick_tap/test.mk b/tests/tap_hold_configurations/quick_tap/test.mk new file mode 100644 index 0000000000..efecca2c22 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test.mk @@ -0,0 +1,18 @@ +# Copyright 2021 Stefan Kerkmann +# +# 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 +# -------------------------------------------------------------------------------- diff --git a/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp b/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp new file mode 100644 index 0000000000..9c3b38050a --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test_action_layer.cpp @@ -0,0 +1,82 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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 "test_common.hpp" + +using testing::_; +using testing::InSequence; + +class ActionLayer : public TestFixture {}; + +TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { + TestDriver driver; + KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)}; + + /* These keys must have the same position in the matrix, only the layer is different. */ + KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; + set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); + + /* Tap TT five times . */ + /* TODO: Tapping Force Hold breaks TT */ + EXPECT_NO_REPORT(driver); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + idle_for(QUICK_TAP_TERM + 10); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + layer_key.press(); + run_one_scan_loop(); + layer_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + + testing::Mock::VerifyAndClearExpectations(&driver); + + EXPECT_REPORT(driver, (KC_A)).Times(1); + regular_key.press(); + run_one_scan_loop(); + expect_layer_state(0); + testing::Mock::VerifyAndClearExpectations(&driver); + + EXPECT_EMPTY_REPORT(driver).Times(1); + regular_key.release(); + run_one_scan_loop(); + expect_layer_state(0); + testing::Mock::VerifyAndClearExpectations(&driver); +} diff --git a/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp new file mode 100644 index 0000000000..be43f8e6c4 --- /dev/null +++ b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp @@ -0,0 +1,291 @@ +/* Copyright 2021 Stefan Kerkmann + * + * 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 "config.h" +#include "keyboard_report_util.hpp" +#include "keycode.h" +#include "test_common.hpp" +#include "action_tapping.h" +#include "test_fixture.hpp" +#include "test_keymap_key.hpp" + +using testing::_; +using testing::InSequence; + +class QuickTap : public TestFixture {}; + +TEST_F(QuickTap, tap_regular_key_while_mod_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + + set_keymap({mod_tap_key, regular_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release regular key. */ + EXPECT_NO_REPORT(driver); + regular_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_LSFT)); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Idle for tapping term of mod tap hold key. */ + 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); +} + +TEST_F(QuickTap, tap_mod_tap_key_while_mod_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto first_mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + auto second_mod_tap_key = KeymapKey(0, 2, 0, RSFT_T(KC_A)); + + set_keymap({first_mod_tap_key, second_mod_tap_key}); + + /* Press first mod-tap key */ + EXPECT_NO_REPORT(driver); + first_mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press second mod-tap key */ + EXPECT_NO_REPORT(driver); + second_mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release second tap-hold key */ + EXPECT_NO_REPORT(driver); + second_mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release first mod-tap key */ + EXPECT_REPORT(driver, (KC_LSFT)); + first_mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Idle for tapping term of first mod-tap key. */ + 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); +} + +TEST_F(QuickTap, tap_regular_key_while_layer_tap_key_is_held) { + TestDriver driver; + InSequence s; + auto layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_P)); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + auto layer_key = KeymapKey(1, 2, 0, KC_B); + + set_keymap({layer_tap_key, regular_key, layer_key}); + + /* Press layer-tap key */ + EXPECT_NO_REPORT(driver); + layer_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press regular key */ + EXPECT_NO_REPORT(driver); + regular_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release regular key */ + EXPECT_NO_REPORT(driver); + regular_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release layer-tap key */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_REPORT(driver, (KC_A, KC_P)); + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + layer_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_tap_again_before_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM - 10); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and tap mod-tap key again. */ + EXPECT_REPORT(driver, (KC_P)); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_hold_again_before_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM - 10); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and hold mod-tap key again. */ + EXPECT_REPORT(driver, (KC_P)); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Wait until tapping term expired */ + EXPECT_NO_REPORT(driver); + idle_for(TAPPING_TERM); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + + +TEST_F(QuickTap, tap_key_and_tap_again_after_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM + 10); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press mod-tap key again. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} + +TEST_F(QuickTap, tap_key_and_hold_again_after_quick_tap_term) { + TestDriver driver; + InSequence s; + auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); + + set_keymap({mod_tap_key}); + + /* Press mod-tap key. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_REPORT(driver, (KC_P)); + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + idle_for(QUICK_TAP_TERM + 10); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Press and hold mod-tap key again. */ + EXPECT_NO_REPORT(driver); + mod_tap_key.press(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Wait until tapping term expired */ + EXPECT_REPORT(driver, (KC_LSFT)); + idle_for(TAPPING_TERM); + testing::Mock::VerifyAndClearExpectations(&driver); + + /* Release mod-tap key. */ + EXPECT_EMPTY_REPORT(driver); + mod_tap_key.release(); + run_one_scan_loop(); + testing::Mock::VerifyAndClearExpectations(&driver); +} diff --git a/tests/tap_hold_configurations/tapping_force_hold/config.h b/tests/tap_hold_configurations/tapping_force_hold/config.h deleted file mode 100644 index 3b4646338a..0000000000 --- a/tests/tap_hold_configurations/tapping_force_hold/config.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2021 Stefan Kerkmann - * - * 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_FORCE_HOLD \ No newline at end of file diff --git a/tests/tap_hold_configurations/tapping_force_hold/test.mk b/tests/tap_hold_configurations/tapping_force_hold/test.mk deleted file mode 100644 index efecca2c22..0000000000 --- a/tests/tap_hold_configurations/tapping_force_hold/test.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2021 Stefan Kerkmann -# -# 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 -# -------------------------------------------------------------------------------- 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 deleted file mode 100644 index 965c702d7a..0000000000 --- a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2021 Stefan Kerkmann - * - * 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 "test_common.hpp" - -using testing::_; -using testing::InSequence; - -class ActionLayer : public TestFixture {}; - -TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) { - TestDriver driver; - KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)}; - - /* These keys must have the same position in the matrix, only the layer is different. */ - KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A}; - set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}}); - - /* Tap TT five times . */ - /* TODO: Tapping Force Hold breaks TT */ - EXPECT_NO_REPORT(driver); - - layer_key.press(); - run_one_scan_loop(); - layer_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - - layer_key.press(); - run_one_scan_loop(); - layer_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - - layer_key.press(); - run_one_scan_loop(); - layer_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - - layer_key.press(); - run_one_scan_loop(); - layer_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - - layer_key.press(); - run_one_scan_loop(); - layer_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - - testing::Mock::VerifyAndClearExpectations(&driver); - - EXPECT_REPORT(driver, (KC_A)).Times(1); - regular_key.press(); - run_one_scan_loop(); - expect_layer_state(0); - testing::Mock::VerifyAndClearExpectations(&driver); - - EXPECT_EMPTY_REPORT(driver).Times(1); - regular_key.release(); - run_one_scan_loop(); - expect_layer_state(0); - testing::Mock::VerifyAndClearExpectations(&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 deleted file mode 100644 index 604f9a4a54..0000000000 --- a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp +++ /dev/null @@ -1,213 +0,0 @@ - -/* Copyright 2021 Stefan Kerkmann - * - * 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_fixture.hpp" -#include "test_keymap_key.hpp" - -using testing::_; -using testing::InSequence; - -class TappingForceHold : public TestFixture {}; - -TEST_F(TappingForceHold, tap_regular_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - - set_keymap({mod_tap_hold_key, regular_key}); - - /* Press mod-tap-hold key. */ - EXPECT_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key. */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key. */ - EXPECT_NO_REPORT(driver); - regular_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key. */ - 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_REPORT(driver, (KC_LSFT, KC_A)); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_EMPTY_REPORT(driver); - idle_for(TAPPING_TERM - 3); - testing::Mock::VerifyAndClearExpectations(&driver); -} - -TEST_F(TappingForceHold, tap_mod_tap_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A)); - - set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); - - /* Press first mod-tap-hold key */ - EXPECT_NO_REPORT(driver); - first_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press second tap-hold key */ - EXPECT_NO_REPORT(driver); - second_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release second tap-hold key */ - 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_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_REPORT(driver, (KC_LSFT, KC_A)); - EXPECT_REPORT(driver, (KC_LSFT)); - EXPECT_EMPTY_REPORT(driver); - idle_for(TAPPING_TERM - 3); - testing::Mock::VerifyAndClearExpectations(&driver); -} - -TEST_F(TappingForceHold, tap_regular_key_while_layer_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - auto layer_key = KeymapKey(1, 2, 0, KC_B); - - set_keymap({layer_tap_hold_key, regular_key, layer_key}); - - /* Press layer-tap-hold key */ - EXPECT_NO_REPORT(driver); - layer_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key */ - EXPECT_NO_REPORT(driver); - regular_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release layer-tap-hold key */ - 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); -} - -TEST_F(TappingForceHold, tap_mod_tap_hold_key_two_times) { - TestDriver driver; - InSequence s; - auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - - set_keymap({mod_tap_hold_key}); - - /* Press mod-tap-hold key. */ - EXPECT_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key. */ - 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_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key. */ - EXPECT_REPORT(driver, (KC_P)); - EXPECT_EMPTY_REPORT(driver); - mod_tap_hold_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); -} - -TEST_F(TappingForceHold, tap_mod_tap_hold_key_twice_and_hold_on_second_time) { - TestDriver driver; - InSequence s; - auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - - set_keymap({mod_tap_hold_key}); - - /* Press mod-tap-hold key. */ - EXPECT_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key. */ - 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_NO_REPORT(driver); - mod_tap_hold_key.press(); - idle_for(TAPPING_TERM); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key. */ - EXPECT_REPORT(driver, (KC_LEFT_SHIFT)); - EXPECT_EMPTY_REPORT(driver); - mod_tap_hold_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); -} -- cgit v1.2.3 From 598735a2b8a7c69e3c3d9c05e856736d506a2ade Mon Sep 17 00:00:00 2001 From: QMK Bot Date: Mon, 12 Dec 2022 08:02:15 -0800 Subject: Format code according to conventions (#19305) --- tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp index be43f8e6c4..e2f8c51340 100644 --- a/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp +++ b/tests/tap_hold_configurations/quick_tap/test_quick_tap.cpp @@ -31,7 +31,7 @@ TEST_F(QuickTap, tap_regular_key_while_mod_tap_key_is_held) { TestDriver driver; InSequence s; auto mod_tap_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); + auto regular_key = KeymapKey(0, 2, 0, KC_A); set_keymap({mod_tap_key, regular_key}); @@ -111,8 +111,8 @@ TEST_F(QuickTap, tap_regular_key_while_layer_tap_key_is_held) { TestDriver driver; InSequence s; auto layer_tap_key = KeymapKey(0, 1, 0, LT(1, KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - auto layer_key = KeymapKey(1, 2, 0, KC_B); + auto regular_key = KeymapKey(0, 2, 0, KC_A); + auto layer_key = KeymapKey(1, 2, 0, KC_B); set_keymap({layer_tap_key, regular_key, layer_key}); @@ -216,7 +216,6 @@ TEST_F(QuickTap, tap_key_and_hold_again_before_quick_tap_term) { testing::Mock::VerifyAndClearExpectations(&driver); } - TEST_F(QuickTap, tap_key_and_tap_again_after_quick_tap_term) { TestDriver driver; InSequence s; -- cgit v1.2.3 From 454edf68d1035cfabbcd3e4a7b7e9768085e17e5 Mon Sep 17 00:00:00 2001 From: precondition <57645186+precondition@users.noreply.github.com> Date: Mon, 12 Dec 2022 22:16:12 +0100 Subject: Tests that caps word stays active after use of OSL (#19303) --- tests/caps_word/test_caps_word.cpp | 53 +++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/caps_word/test_caps_word.cpp b/tests/caps_word/test_caps_word.cpp index 3d0735d8c2..e5ecbb844e 100644 --- a/tests/caps_word/test_caps_word.cpp +++ b/tests/caps_word/test_caps_word.cpp @@ -591,6 +591,57 @@ INSTANTIATE_TEST_CASE_P( ), CapsWordDoubleTapShiftParams::GetName ); -// clang-format on +// Tests that holding a OSL keeps caps word active and shifts keys on the layer that need to be shifted. +TEST_F(CapsWord, IgnoresOSLHold) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_osl(0, 1, 0, OSL(1)); + KeymapKey key_b(1, 0, 0, KC_B); + set_keymap({key_a, key_osl, key_b}); + + // Allow any number of reports with no keys or only modifiers. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + caps_word_on(); + + key_osl.press(); + run_one_scan_loop(); + tap_key(key_b); + key_osl.release(); + run_one_scan_loop(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} + +// Tests that tapping a OSL keeps caps word active and shifts keys on the layer that need to be shifted. +TEST_F(CapsWord, IgnoresOSLTap) { + TestDriver driver; + KeymapKey key_a(0, 0, 0, KC_A); + KeymapKey key_osl(0, 1, 0, OSL(1)); + KeymapKey key_b(1, 0, 0, KC_B); + set_keymap({key_a, key_osl, key_b}); + + // Allow any number of reports with no keys or only modifiers. + // clang-format off + EXPECT_CALL(driver, send_keyboard_mock(AnyOf( + KeyboardReport(), + KeyboardReport(KC_LSFT)))) + .Times(AnyNumber()); + + EXPECT_REPORT(driver, (KC_LSFT, KC_B)); + caps_word_on(); + + tap_key(key_osl); + tap_key(key_b); + run_one_scan_loop(); + + testing::Mock::VerifyAndClearExpectations(&driver); +} +// clang-format on } // namespace -- cgit v1.2.3 From 515dd18c2801663bbac0e59f683c2a93e4bd9b1a Mon Sep 17 00:00:00 2001 From: precondition <57645186+precondition@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:20:07 +0100 Subject: Remove IGNORE_MOD_TAP_INTERRUPT_PER_KEY in favour of HOLD_ON_OTHER_KEY_PRESS_PER_KEY (#15741) --- .../default_mod_tap/config.h | 2 +- .../default_mod_tap/test_tap_hold.cpp | 2 +- .../ignore_mod_tap_interrupt/config.h | 21 ---- .../ignore_mod_tap_interrupt/test.mk | 18 --- .../ignore_mod_tap_interrupt/test_tap_hold.cpp | 136 --------------------- .../permissive_hold/test_tap_hold.cpp | 2 +- .../config.h | 22 ---- .../test.mk | 18 --- .../test_tap_hold.cpp | 133 -------------------- 9 files changed, 3 insertions(+), 351 deletions(-) delete mode 100644 tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h delete mode 100644 tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk delete mode 100644 tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp delete mode 100644 tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h delete mode 100644 tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk delete mode 100644 tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp (limited to 'tests') diff --git a/tests/tap_hold_configurations/default_mod_tap/config.h b/tests/tap_hold_configurations/default_mod_tap/config.h index 5955b8600a..f22448845e 100644 --- a/tests/tap_hold_configurations/default_mod_tap/config.h +++ b/tests/tap_hold_configurations/default_mod_tap/config.h @@ -18,4 +18,4 @@ #include "test_common.h" -#define IGNORE_MOD_TAP_INTERRUPT \ No newline at end of file +#define IGNORE_MOD_TAP_INTERRUPT 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 b70efe4aed..01943c10d2 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 @@ -66,7 +66,7 @@ TEST_F(DefaultTapHold, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); } -TEST_F(DefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held) { +TEST_F(DefaultTapHold, tap_a_mod_tap_key_while_another_mod_tap_key_is_held) { TestDriver driver; InSequence s; auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h deleted file mode 100644 index 5955b8600a..0000000000 --- a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2021 Stefan Kerkmann - * - * 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 IGNORE_MOD_TAP_INTERRUPT \ No newline at end of file diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk deleted file mode 100644 index efecca2c22..0000000000 --- a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2021 Stefan Kerkmann -# -# 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 -# -------------------------------------------------------------------------------- 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 deleted file mode 100644 index 319de61070..0000000000 --- a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright 2021 Stefan Kerkmann - * - * 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_fixture.hpp" -#include "test_keymap_key.hpp" - -using testing::_; -using testing::InSequence; - -class IgnoreModTapInterrupt : public TestFixture {}; - -TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - - set_keymap({mod_tap_hold_key, regular_key}); - - /* Press mod-tap-hold key */ - EXPECT_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key */ - EXPECT_NO_REPORT(driver); - regular_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release mod-tap-hold key */ - 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); -} - -TEST_F(IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A)); - - set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); - - /* Press first mod-tap-hold key */ - EXPECT_NO_REPORT(driver); - first_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press second tap-hold key */ - EXPECT_NO_REPORT(driver); - second_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release second tap-hold key */ - 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_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); -} - -TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - auto layer_key = KeymapKey(1, 2, 0, KC_B); - - set_keymap({layer_tap_hold_key, regular_key, layer_key}); - - /* Press layer-tap-hold key */ - EXPECT_NO_REPORT(driver); - layer_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key */ - EXPECT_NO_REPORT(driver); - regular_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release layer-tap-hold key */ - 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_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp index 74e81f347f..e6ecc86401 100644 --- a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp +++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp @@ -60,7 +60,7 @@ TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) { testing::Mock::VerifyAndClearExpectations(&driver); } -TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) { +TEST_F(PermissiveHold, tap_a_mod_tap_key_while_another_mod_tap_key_is_held) { TestDriver driver; InSequence s; auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h deleted file mode 100644 index a6abd50bbe..0000000000 --- a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2021 Stefan Kerkmann - * - * 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 IGNORE_MOD_TAP_INTERRUPT -#define PERMISSIVE_HOLD \ No newline at end of file diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk deleted file mode 100644 index efecca2c22..0000000000 --- a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2021 Stefan Kerkmann -# -# 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 -# -------------------------------------------------------------------------------- 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 deleted file mode 100644 index ee7e707c94..0000000000 --- a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp +++ /dev/null @@ -1,133 +0,0 @@ - -/* Copyright 2021 Stefan Kerkmann - * - * 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_fixture.hpp" -#include "test_keymap_key.hpp" - -using testing::_; -using testing::InSequence; - -class PermissiveHold_IgnoreModTapInterrupt : public TestFixture {}; - -TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - - set_keymap({mod_tap_hold_key, regular_key}); - - /* Press mod-tap-hold key */ - EXPECT_NO_REPORT(driver); - mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key */ - 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_EMPTY_REPORT(driver); - mod_tap_hold_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); -} - -TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P)); - auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A)); - - set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key}); - - /* Press first mod-tap-hold key */ - EXPECT_NO_REPORT(driver); - first_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press second tap-hold key */ - EXPECT_NO_REPORT(driver); - second_mod_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release second tap-hold key */ - 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_EMPTY_REPORT(driver); - first_mod_tap_hold_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); -} - -TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_layer_tap_key_is_held) { - TestDriver driver; - InSequence s; - auto layer_tap_hold_key = KeymapKey(0, 1, 0, LT(1, KC_P)); - auto regular_key = KeymapKey(0, 2, 0, KC_A); - auto layer_key = KeymapKey(1, 2, 0, KC_B); - - set_keymap({layer_tap_hold_key, regular_key, layer_key}); - - /* Press layer-tap-hold key */ - EXPECT_NO_REPORT(driver); - layer_tap_hold_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Press regular key */ - EXPECT_NO_REPORT(driver); - regular_key.press(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release regular key */ - EXPECT_REPORT(driver, (KC_B)); - EXPECT_EMPTY_REPORT(driver); - regular_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); - - /* Release layer-tap-hold key */ - EXPECT_NO_REPORT(driver); - layer_tap_hold_key.release(); - run_one_scan_loop(); - testing::Mock::VerifyAndClearExpectations(&driver); -} -- cgit v1.2.3 From 962e4c0e1854b10612bab547c3d842c5f967dd23 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Wed, 14 Dec 2022 16:31:08 +0100 Subject: [Test] Reset timer for every unit test and provide timestamps for log messages (#17028) --- tests/basic/test_keycode_util.cpp | 52 +++ tests/caps_word/test_caps_word.cpp | 9 +- tests/test_common/keyboard_report_util.cpp | 45 +- tests/test_common/keycode_table.cpp | 663 +++++++++++++++++++++++++++++ tests/test_common/keycode_util.cpp | 128 ++++++ tests/test_common/keycode_util.hpp | 5 + tests/test_common/matrix.c | 8 +- tests/test_common/test_common.hpp | 1 + tests/test_common/test_fixture.cpp | 29 +- tests/test_common/test_keymap_key.cpp | 16 +- tests/test_common/test_keymap_key.hpp | 16 +- tests/test_common/test_logger.cpp | 16 +- tests/test_common/test_logger.hpp | 8 +- 13 files changed, 962 insertions(+), 34 deletions(-) create mode 100644 tests/basic/test_keycode_util.cpp create mode 100644 tests/test_common/keycode_table.cpp create mode 100644 tests/test_common/keycode_util.cpp create mode 100644 tests/test_common/keycode_util.hpp (limited to 'tests') diff --git a/tests/basic/test_keycode_util.cpp b/tests/basic/test_keycode_util.cpp new file mode 100644 index 0000000000..693334676e --- /dev/null +++ b/tests/basic/test_keycode_util.cpp @@ -0,0 +1,52 @@ +// Copyright 2022 Stefan Kerkmann +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "test_common.hpp" + +class KeycodeToIdentifierSuite : public ::testing::TestWithParam> {}; + +TEST_P(KeycodeToIdentifierSuite, ConversionTests) { + ASSERT_EQ(get_keycode_identifier_or_default(GetParam().first), GetParam().second); +} + +INSTANTIATE_TEST_CASE_P(ConversionTestsP, KeycodeToIdentifierSuite, + // clang-format off +::testing::Values( + // Goto layer + std::make_pair(TO(0), "TO(0)"), + std::make_pair(TO(0x1F), "TO(31)"), + // Momentary switch layer + std::make_pair(MO(0), "MO(0)"), + std::make_pair(MO(0x1F), "MO(31)"), + // Set default layer + std::make_pair(DF(0), "DF(0)"), + std::make_pair(DF(0x1F), "DF(31)"), + // Toggle layer + std::make_pair(TG(0), "TG(0)"), + std::make_pair(TG(0x1F), "TG(31)"), + // One-shot layer + std::make_pair(OSL(0), "OSL(0)"), + std::make_pair(OSL(0x1F), "OSL(31)"), + // One-shot mod + std::make_pair(OSM(MOD_LSFT), "OSM(MOD_LSFT)"), + std::make_pair(OSM(MOD_LSFT | MOD_LCTL), "OSM(MOD_LCTL | MOD_LSFT)"), + // Layer Mod + std::make_pair(LM(0, MOD_LSFT), "LM(0, MOD_LSFT)"), + std::make_pair(LM(0xF, MOD_LSFT), "LM(15, MOD_LSFT)"), + std::make_pair(LM(0xF, MOD_LSFT | MOD_LCTL), "LM(15, MOD_LCTL | MOD_LSFT)"), + // Layer tap toggle + std::make_pair(TT(0), "TT(0)"), + std::make_pair(TT(0x1F), "TT(31)"), + // Layer tap + std::make_pair(LT(0, KC_A), "LT(0, KC_A)"), + std::make_pair(LT(0xF, KC_SPACE), "LT(15, KC_SPACE)"), + std::make_pair(LT(1, KC_SPC), "LT(1, KC_SPACE)"), + // Mod tap + std::make_pair(MT(MOD_LCTL, KC_A), "MT(MOD_LCTL, KC_A)"), + std::make_pair(MT(MOD_LCTL | MOD_LSFT, KC_A), "MT(MOD_LCTL | MOD_LSFT, KC_A)"), + std::make_pair(ALT_T(KC_TAB), "MT(MOD_LALT, KC_TAB)"), + // Mods + std::make_pair(LCTL(KC_A), "QK_MODS(KC_A, QK_LCTL)"), + std::make_pair(HYPR(KC_SPACE), "QK_MODS(KC_SPACE, QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI)") +)); +// clang-format on diff --git a/tests/caps_word/test_caps_word.cpp b/tests/caps_word/test_caps_word.cpp index e5ecbb844e..fa970c7d0e 100644 --- a/tests/caps_word/test_caps_word.cpp +++ b/tests/caps_word/test_caps_word.cpp @@ -505,7 +505,8 @@ class CapsWordDoubleTapShift : public ::testing::WithParamInterface #include #include + using namespace testing; +extern std::map KEYCODE_ID_TABLE; + namespace { + std::vector get_keys(const report_keyboard_t& report) { std::vector result; #if defined(NKRO_ENABLE) @@ -36,6 +41,19 @@ std::vector get_keys(const report_keyboard_t& report) { std::sort(result.begin(), result.end()); return result; } + +std::vector get_mods(const report_keyboard_t& report) { + std::vector result; + for (size_t i = 0; i < 8; i++) { + if (report.mods & (1 << i)) { + uint8_t code = KC_LEFT_CTRL + i; + result.emplace_back(code); + } + } + std::sort(result.begin(), result.end()); + return result; +} + } // namespace bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) { @@ -44,21 +62,36 @@ bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) { return lhs.mods == rhs.mods && lhskeys == rhskeys; } -std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& report) { +std::ostream& operator<<(std::ostream& os, const report_keyboard_t& report) { auto keys = get_keys(report); + auto mods = get_mods(report); - // TODO: This should probably print friendly names for the keys - stream << "Keyboard Report: Mods (" << (uint32_t)report.mods << ") Keys ("; + os << std::setw(10) << std::left << "report: "; + + if (!keys.size() && !mods.size()) { + return os << "empty" << std::endl; + } + os << "("; for (auto key = keys.cbegin(); key != keys.cend();) { - stream << +(*key); + os << KEYCODE_ID_TABLE.at(*key); key++; if (key != keys.cend()) { - stream << ","; + os << ", "; + } + } + + os << ") ["; + + for (auto mod = mods.cbegin(); mod != mods.cend();) { + os << KEYCODE_ID_TABLE.at(*mod); + mod++; + if (mod != mods.cend()) { + os << ", "; } } - return stream << ")" << std::endl; + return os << "]" << std::endl; } KeyboardReportMatcher::KeyboardReportMatcher(const std::vector& keys) { diff --git a/tests/test_common/keycode_table.cpp b/tests/test_common/keycode_table.cpp new file mode 100644 index 0000000000..63350c272d --- /dev/null +++ b/tests/test_common/keycode_table.cpp @@ -0,0 +1,663 @@ +// Copyright 2022 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +/******************************************************************************* + 88888888888 888 d8b .d888 d8b 888 d8b + 888 888 Y8P d88P" Y8P 888 Y8P + 888 888 888 888 + 888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b + 888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K + 888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b. + 888 888 888 888 X88 888 888 888 Y8b. 888 X88 + 888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P' + 888 888 + 888 888 + 888 888 + .d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888 + d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888 + 888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888 + Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888 + "Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888 + 888 + Y8b d88P + "Y88P" +*******************************************************************************/ + +// clang-format off +extern "C" { +#include +} +#include +#include +#include + +std::map KEYCODE_ID_TABLE = { + {KC_NO, "KC_NO"}, + {KC_TRANSPARENT, "KC_TRANSPARENT"}, + {KC_A, "KC_A"}, + {KC_B, "KC_B"}, + {KC_C, "KC_C"}, + {KC_D, "KC_D"}, + {KC_E, "KC_E"}, + {KC_F, "KC_F"}, + {KC_G, "KC_G"}, + {KC_H, "KC_H"}, + {KC_I, "KC_I"}, + {KC_J, "KC_J"}, + {KC_K, "KC_K"}, + {KC_L, "KC_L"}, + {KC_M, "KC_M"}, + {KC_N, "KC_N"}, + {KC_O, "KC_O"}, + {KC_P, "KC_P"}, + {KC_Q, "KC_Q"}, + {KC_R, "KC_R"}, + {KC_S, "KC_S"}, + {KC_T, "KC_T"}, + {KC_U, "KC_U"}, + {KC_V, "KC_V"}, + {KC_W, "KC_W"}, + {KC_X, "KC_X"}, + {KC_Y, "KC_Y"}, + {KC_Z, "KC_Z"}, + {KC_1, "KC_1"}, + {KC_2, "KC_2"}, + {KC_3, "KC_3"}, + {KC_4, "KC_4"}, + {KC_5, "KC_5"}, + {KC_6, "KC_6"}, + {KC_7, "KC_7"}, + {KC_8, "KC_8"}, + {KC_9, "KC_9"}, + {KC_0, "KC_0"}, + {KC_ENTER, "KC_ENTER"}, + {KC_ESCAPE, "KC_ESCAPE"}, + {KC_BACKSPACE, "KC_BACKSPACE"}, + {KC_TAB, "KC_TAB"}, + {KC_SPACE, "KC_SPACE"}, + {KC_MINUS, "KC_MINUS"}, + {KC_EQUAL, "KC_EQUAL"}, + {KC_LEFT_BRACKET, "KC_LEFT_BRACKET"}, + {KC_RIGHT_BRACKET, "KC_RIGHT_BRACKET"}, + {KC_BACKSLASH, "KC_BACKSLASH"}, + {KC_NONUS_HASH, "KC_NONUS_HASH"}, + {KC_SEMICOLON, "KC_SEMICOLON"}, + {KC_QUOTE, "KC_QUOTE"}, + {KC_GRAVE, "KC_GRAVE"}, + {KC_COMMA, "KC_COMMA"}, + {KC_DOT, "KC_DOT"}, + {KC_SL