* Add per-test keymaps * Add better trace and info logs for failed unit-tests * Add layer state assertion with tracing message * Use individual test binaries configuration options * Add basic qmk functionality tests * Add tap hold configurations tests * Add auto shift tests Co-authored-by: Nick Brassel <nick@tzarc.org>pull/15285/head
@ -0,0 +1,19 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" |
@ -0,0 +1,20 @@ | |||||
# 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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- | |||||
AUTO_SHIFT_ENABLE = yes |
@ -0,0 +1,73 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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 AutoShift : public TestFixture {}; | |||||
TEST_F(AutoShift, key_release_before_timeout) { | |||||
TestDriver driver; | |||||
InSequence s; | |||||
auto regular_key = KeymapKey(0, 2, 0, KC_A); | |||||
set_keymap({regular_key}); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(AutoShift, key_release_after_timeout) { | |||||
TestDriver driver; | |||||
InSequence s; | |||||
auto regular_key = KeymapKey(0, 2, 0, KC_A); | |||||
set_keymap({regular_key}); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -1,45 +0,0 @@ | |||||
/* Copyright 2017 Fred Sundvik | |||||
* | |||||
* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "quantum.h" | |||||
// Don't rearrange keys as existing tests might rely on the order | |||||
// Col2, Row 0 has to be KC_NO, because tests rely on it | |||||
#define COMBO1 RSFT(LCTL(KC_O)) | |||||
const uint16_t PROGMEM | |||||
keymaps[][MATRIX_ROWS][MATRIX_COLS] = | |||||
{ | |||||
[0] = | |||||
{ | |||||
// 0 1 2 3 4 5 6 7 8 9 | |||||
{KC_A, KC_B, KC_NO, KC_LSFT, KC_RSFT, KC_LCTL, COMBO1, SFT_T(KC_P), M(0), KC_NO}, | |||||
{KC_EQL, KC_PLUS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
{KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
{KC_C, KC_D, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
}, | |||||
}; | |||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { | |||||
if (record->event.pressed) { | |||||
switch (id) { | |||||
case 0: | |||||
return MACRO(D(LSFT), T(H), U(LSFT), T(E), T(L), T(L), T(O), T(SPACE), W(100), D(LSFT), T(W), U(LSFT), I(10), T(O), T(R), T(L), T(D), D(LSFT), T(1), U(LSFT), END); | |||||
} | |||||
} | |||||
return MACRO_NONE; | |||||
}; |
@ -0,0 +1,18 @@ | |||||
# Copyright 2017 Fred Sundvik | |||||
# | |||||
# 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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,197 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "action_util.h" | |||||
#include "keyboard_report_util.hpp" | |||||
#include "test_common.hpp" | |||||
using testing::_; | |||||
using testing::InSequence; | |||||
class OneShot : public TestFixture {}; | |||||
class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {}; | |||||
TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) { | |||||
TestDriver driver; | |||||
auto osm_key = KeymapKey(0, 0, 0, OSM(MOD_LSFT), KC_LSFT); | |||||
set_keymap({osm_key}); | |||||
/* Press and release OSM key*/ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osm_key.press(); | |||||
run_one_scan_loop(); | |||||
osm_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* OSM are added when an actual report is send */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code))); | |||||
send_keyboard_report(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Make unit-test pass */ | |||||
clear_oneshot_mods(); | |||||
} | |||||
#if defined(ONESHOT_TIMEOUT) | |||||
TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) { | |||||
TestDriver driver; | |||||
KeymapKey osm_key = GetParam().first; | |||||
KeymapKey regular_key = GetParam().second; | |||||
set_keymap({osm_key, regular_key}); | |||||
/* Press and release OSM */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osm_key.press(); | |||||
run_one_scan_loop(); | |||||
osm_key.release(); | |||||
idle_for(ONESHOT_TIMEOUT); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
#endif | |||||
TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) { | |||||
TestDriver driver; | |||||
KeymapKey osm_key = GetParam().first; | |||||
KeymapKey regular_key = GetParam().second; | |||||
set_keymap({osm_key, regular_key}); | |||||
/* Press and release OSM */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osm_key.press(); | |||||
run_one_scan_loop(); | |||||
osm_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) { | |||||
TestDriver driver; | |||||
testing::InSequence s; | |||||
KeymapKey osm_key = GetParam().first; | |||||
KeymapKey regular_key = GetParam().second; | |||||
set_keymap({osm_key, regular_key}); | |||||
/* Press OSM */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osm_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
osm_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
// clang-format off | |||||
INSTANTIATE_TEST_CASE_P( | |||||
OneShotModifierTests, | |||||
OneShotParametrizedTestFixture, | |||||
::testing::Values( | |||||
/* first is osm key, second is regular key. */ | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}), | |||||
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 | |||||
TEST_F(OneShot, OSLWithAdditionalKeypress) { | |||||
TestDriver driver; | |||||
InSequence s; | |||||
KeymapKey osl_key = KeymapKey{0, 0, 0, OSL(1)}; | |||||
KeymapKey regular_key = KeymapKey{1, 1, 0, KC_A}; | |||||
set_keymap({osl_key, regular_key}); | |||||
/* Press OSL key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osl_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release OSL key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2); | |||||
osl_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(2); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define IGNORE_MOD_TAP_INTERRUPT |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,230 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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 DefaultTapHold : public TestFixture {}; | |||||
TEST_F(DefaultTapHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Idle for tapping term of mod tap hold key. */ | |||||
idle_for(TAPPING_TERM - 3); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(DefaultTapHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
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); | |||||
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())); | |||||
first_mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(DefaultTapHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
layer_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_CALL(driver, send_keyboard_mock(_)); | |||||
layer_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
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)); | |||||
set_keymap({mod_tap_hold_key}); | |||||
/* Press mod-tap-hold key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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())); | |||||
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))); | |||||
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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
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)); | |||||
set_keymap({mod_tap_hold_key}); | |||||
/* Press mod-tap-hold key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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())); | |||||
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))); | |||||
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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(DefaultTapHold, tap_and_hold_mod_tap_hold_key) { | |||||
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_CALL(driver, send_keyboard_mock(KeyboardReport(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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define IGNORE_MOD_TAP_INTERRUPT |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,136 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_A, KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
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); | |||||
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_A, KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
layer_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_P, regular_key.report_code))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
layer_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define PERMISSIVE_HOLD |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,76 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "action_util.h" | |||||
#include "keyboard_report_util.hpp" | |||||
#include "test_common.hpp" | |||||
using testing::_; | |||||
using testing::InSequence; | |||||
class OneShot : public TestFixture {}; | |||||
class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {}; | |||||
TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) { | |||||
TestDriver driver; | |||||
KeymapKey osm_key = GetParam().first; | |||||
KeymapKey regular_key = GetParam().second; | |||||
set_keymap({osm_key, regular_key}); | |||||
/* Press OSM */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
osm_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
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); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release OSM */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1); | |||||
osm_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
// clang-format off | |||||
INSTANTIATE_TEST_CASE_P( | |||||
OneShotModifierTests, | |||||
OneShotParametrizedTestFixture, | |||||
::testing::Values( | |||||
/* first is osm key, second is regular key. */ | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}), | |||||
std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}), | |||||
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 |
@ -0,0 +1,132 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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 : public TestFixture {}; | |||||
TEST_F(PermissiveHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
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))); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release mod-tap-hold key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(PermissiveHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
second_mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
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))); | |||||
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())); | |||||
first_mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(PermissiveHold, 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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
layer_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(layer_key.report_code))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release layer-tap-hold key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
layer_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -0,0 +1,22 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define IGNORE_MOD_TAP_INTERRUPT | |||||
#define PERMISSIVE_HOLD |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,134 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
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))); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release mod-tap-hold key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
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(KeyboardReport(KC_LSFT))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
layer_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release layer-tap-hold key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
layer_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define RETRO_TAPPING |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,52 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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 RetroTapping : public TestFixture {}; | |||||
TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) { | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
idle_for(TAPPING_TERM); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* 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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -0,0 +1,112 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "keyboard_report_util.hpp" | |||||
#include "keycode.h" | |||||
#include "test_common.hpp" | |||||
#include "action_tapping.h" | |||||
#include "test_keymap_key.hpp" | |||||
using testing::_; | |||||
using testing::InSequence; | |||||
class Tapping : public TestFixture {}; | |||||
TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) { | |||||
TestDriver driver; | |||||
InSequence s; | |||||
auto mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P)); | |||||
set_keymap({mod_tap_hold_key}); | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
idle_for(TAPPING_TERM); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} | |||||
TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) { | |||||
TestDriver driver; | |||||
InSequence s; | |||||
auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P)); | |||||
set_keymap({key_shift_hold_p_tap}); | |||||
/* Press mod_tap_hold key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
key_shift_hold_p_tap.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())); | |||||
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))); | |||||
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())); | |||||
key_shift_hold_p_tap.release(); | |||||
idle_for(TAPPING_TERM + 1); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press mod_tap_hold key again */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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(KC_P))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
key_shift_hold_p_tap.release(); | |||||
idle_for(TAPPING_TERM + 1); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press mod_tap_hold key again */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
key_shift_hold_p_tap.press(); | |||||
idle_for(TAPPING_TERM); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* 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())); | |||||
key_shift_hold_p_tap.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include "test_common.h" | |||||
#define TAPPING_FORCE_HOLD |
@ -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 <http://www.gnu.org/licenses/>. | |||||
# -------------------------------------------------------------------------------- | |||||
# Keep this file, even if it is empty, as a marker that this folder contains tests | |||||
# -------------------------------------------------------------------------------- |
@ -0,0 +1,81 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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: QMK currently sends an empty report even if nothing needs to be reported to the host! */ | |||||
/* TODO: Tapping Force Hold breaks TT */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(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); | |||||
layer_key.press(); | |||||
run_one_scan_loop(); | |||||
layer_key.release(); | |||||
run_one_scan_loop(); | |||||
expect_layer_state(0); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
expect_layer_state(0); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -0,0 +1,215 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
mod_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release mod-tap-hold key. */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(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))); | |||||
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())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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); | |||||
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); | |||||
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_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))); | |||||
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())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
layer_tap_hold_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Press regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
regular_key.press(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
/* Release regular key */ | |||||
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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_CALL(driver, send_keyboard_mock(_)); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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())); | |||||
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(_)).Times(0); | |||||
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())); | |||||
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_CALL(driver, send_keyboard_mock(_)).Times(0); | |||||
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())); | |||||
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(_)).Times(0); | |||||
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(KC_LSHIFT))); | |||||
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())); | |||||
mod_tap_hold_key.release(); | |||||
run_one_scan_loop(); | |||||
testing::Mock::VerifyAndClearExpectations(&driver); | |||||
} |
@ -0,0 +1,33 @@ | |||||
/* Copyright 2017 Fred Sundvik | |||||
* | |||||
* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "quantum.h" | |||||
// clang-format off | |||||
const uint16_t PROGMEM | |||||
keymaps[][MATRIX_ROWS][MATRIX_COLS] = | |||||
{ | |||||
[0] = | |||||
{ | |||||
{KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
{KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
{KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
{KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO}, | |||||
}, | |||||
}; | |||||
// clang-format on |
@ -0,0 +1,4 @@ | |||||
#pragma once | |||||
#define MATRIX_ROWS 4 | |||||
#define MATRIX_COLS 10 |
@ -0,0 +1,30 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "test_keymap_key.hpp" | |||||
#include "test_logger.hpp" | |||||
#include "gtest/gtest-message.h" | |||||
#include "gtest/gtest.h" | |||||
void KeymapKey::press() { | |||||
test_logger.trace() << "Key pressed: (" << +this->position.col << "," << +this->position.row << ")" << std::endl; | |||||
press_key(this->position.col, this->position.row); | |||||
} | |||||
void KeymapKey::release() { | |||||
test_logger.trace() << "Key released: (" << +this->position.col << "," << +this->position.row << ")" << std::endl; | |||||
release_key(this->position.col, this->position.row); | |||||
} |
@ -0,0 +1,46 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
extern "C" { | |||||
#include "keyboard.h" | |||||
#include "test_matrix.h" | |||||
} | |||||
#include <cassert> | |||||
typedef uint8_t layer_t; | |||||
struct KeymapKey { | |||||
KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(keycode) { validate(); } | |||||
KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode, uint16_t report_code) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(report_code) { validate(); } | |||||
void press(); | |||||
void release(); | |||||
const layer_t layer; | |||||
const keypos_t position; | |||||
const uint16_t code; | |||||
/* Sometimes the keycode does not match the code that is send in the usb report, so we provide it here. */ | |||||
const uint16_t report_code; | |||||
private: | |||||
void validate() { | |||||
assert(position.col <= MATRIX_COLS); | |||||
assert(position.row <= MATRIX_ROWS); | |||||
} | |||||
}; |
@ -0,0 +1,39 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <iostream> | |||||
#include "test_logger.hpp" | |||||
TestLogger test_logger; | |||||
TestLogger& TestLogger::info() { | |||||
*this << "[ INFO ] "; | |||||
return *this; | |||||
} | |||||
TestLogger& TestLogger::trace() { | |||||
*this << "[ TRACE ] "; | |||||
return *this; | |||||
} | |||||
TestLogger& TestLogger::error() { | |||||
*this << "[ ERROR ] "; | |||||
return *this; | |||||
} | |||||
void TestLogger::reset() { this->m_log.str(""); }; | |||||
void TestLogger::print_log() { std::cerr << this->m_log.str(); } |
@ -0,0 +1,35 @@ | |||||
/* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#pragma once | |||||
#include <ostream> | |||||
#include <sstream> | |||||
class TestLogger : public std::ostream { | |||||
public: | |||||
TestLogger() : std::ostream(&m_log){}; | |||||
TestLogger& info(); | |||||
TestLogger& trace(); | |||||
TestLogger& error(); | |||||
void print_log(); | |||||
void reset(); | |||||
private: | |||||
std::stringbuf m_log; | |||||
}; | |||||
extern TestLogger test_logger; |