* 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; |