Improve test invocation, fix Retro Shift bugs, and add Auto+Retro Shift test cases (#15889)

master
Isaac Elenbaas 2023-09-24 22:45:49 -04:00 committed by GitHub
parent 1fb02d5ad8
commit dd94877ec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2584 additions and 89 deletions

View File

@ -300,17 +300,18 @@ endef
define BUILD_TEST define BUILD_TEST
TEST_PATH := $1 TEST_PATH := $1
TEST_NAME := $$(notdir $$(TEST_PATH)) TEST_NAME := $$(notdir $$(TEST_PATH))
TEST_FULL_NAME := $$(subst /,_,$$(patsubst $$(ROOT_DIR)tests/%,%,$$(TEST_PATH)))
MAKE_TARGET := $2 MAKE_TARGET := $2
COMMAND := $1 COMMAND := $1
MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET) MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET)
MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)" MAKE_VARS := TEST=$$(TEST_NAME) TEST_OUTPUT=$$(TEST_FULL_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
MAKE_MSG := $$(MSG_MAKE_TEST) MAKE_MSG := $$(MSG_MAKE_TEST)
$$(eval $$(call BUILD)) $$(eval $$(call BUILD))
ifneq ($$(MAKE_TARGET),clean) ifneq ($$(MAKE_TARGET),clean)
TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_FULL_NAME).elf
TESTS += $$(TEST_NAME) TESTS += $$(TEST_FULL_NAME)
TEST_MSG := $$(MSG_TEST) TEST_MSG := $$(MSG_TEST)
$$(TEST_NAME)_COMMAND := \ $$(TEST_FULL_NAME)_COMMAND := \
printf "$$(TEST_MSG)\n"; \ printf "$$(TEST_MSG)\n"; \
$$(TEST_EXECUTABLE); \ $$(TEST_EXECUTABLE); \
if [ $$$$? -gt 0 ]; \ if [ $$$$? -gt 0 ]; \
@ -322,15 +323,22 @@ endef
define PARSE_TEST define PARSE_TEST
TESTS := TESTS :=
TEST_NAME := $$(firstword $$(subst :, ,$$(RULE))) # list of possible targets, colon-delimited, to reassign to MAKE_TARGET and remove
TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE))) TARGETS := :clean:
ifneq (,$$(findstring :$$(lastword $$(subst :, ,$$(RULE))):, $$(TARGETS)))
MAKE_TARGET := $$(lastword $$(subst :, ,$$(RULE)))
TEST_SUBPATH := $$(subst $$(eval) ,/,$$(wordlist 2, $$(words $$(subst :, ,$$(RULE))), _ $$(subst :, ,$$(RULE))))
else
MAKE_TARGET :=
TEST_SUBPATH := $$(subst :,/,$$(RULE))
endif
include $(BUILDDEFS_PATH)/testlist.mk include $(BUILDDEFS_PATH)/testlist.mk
ifeq ($$(TEST_NAME),all) ifeq ($$(RULE),all)
MATCHED_TESTS := $$(TEST_LIST) MATCHED_TESTS := $$(TEST_LIST)
else else
MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring x$$(TEST_NAME)x, x$$(notdir $$(TEST))x), $$(TEST),)) MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring /$$(TEST_SUBPATH)/, $$(patsubst %,%/,$$(TEST))), $$(TEST),))
endif endif
$$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET)))) $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(MAKE_TARGET))))
endef endef

View File

@ -13,10 +13,10 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
$(TEST)_INC := \ $(TEST_OUTPUT)_INC := \
tests/test_common/common_config.h tests/test_common/common_config.h
$(TEST)_SRC := \ $(TEST_OUTPUT)_SRC := \
$(QUANTUM_SRC) \ $(QUANTUM_SRC) \
$(SRC) \ $(SRC) \
$(QUANTUM_PATH)/keymap_introspection.c \ $(QUANTUM_PATH)/keymap_introspection.c \
@ -30,8 +30,8 @@ $(TEST)_SRC := \
tests/test_common/test_logger.cpp \ tests/test_common/test_logger.cpp \
$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp)) $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
$(TEST)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\"" $(TEST_OUTPUT)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
$(TEST)_CONFIG := $(TEST_PATH)/config.h $(TEST_OUTPUT)_CONFIG := $(TEST_PATH)/config.h
VPATH += $(TOP_DIR)/tests/test_common VPATH += $(TOP_DIR)/tests/test_common

View File

@ -9,13 +9,13 @@ OPT = g
include paths.mk include paths.mk
include $(BUILDDEFS_PATH)/message.mk include $(BUILDDEFS_PATH)/message.mk
TARGET=test/$(TEST) TARGET=test/$(TEST_OUTPUT)
GTEST_OUTPUT = $(BUILD_DIR)/gtest GTEST_OUTPUT = $(BUILD_DIR)/gtest
TEST_OBJ = $(BUILD_DIR)/test_obj TEST_OBJ = $(BUILD_DIR)/test_obj
OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT) OUTPUTS := $(TEST_OBJ)/$(TEST_OUTPUT) $(GTEST_OUTPUT)
GTEST_INC := \ GTEST_INC := \
$(LIB_PATH)/googletest/googletest/include \ $(LIB_PATH)/googletest/googletest/include \
@ -71,18 +71,18 @@ ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include $(BUILDDEFS_PATH)/build_full_test.mk include $(BUILDDEFS_PATH)/build_full_test.mk
endif endif
$(TEST)_SRC += \ $(TEST_OUTPUT)_SRC += \
tests/test_common/main.cpp \ tests/test_common/main.cpp \
$(QUANTUM_PATH)/logging/print.c $(QUANTUM_PATH)/logging/print.c
ifneq ($(strip $(INTROSPECTION_KEYMAP_C)),) ifneq ($(strip $(INTROSPECTION_KEYMAP_C)),)
$(TEST)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\" $(TEST_OUTPUT)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
endif endif
$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC) $(TEST_OBJ)/$(TEST_OUTPUT)_SRC := $($(TEST_OUTPUT)_SRC)
$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC) $(TEST_OBJ)/$(TEST_OUTPUT)_INC := $($(TEST_OUTPUT)_INC) $(VPATH) $(GTEST_INC)
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS) $(TEST_OBJ)/$(TEST_OUTPUT)_DEFS := $($(TEST_OUTPUT)_DEFS)
$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG) $(TEST_OBJ)/$(TEST_OUTPUT)_CONFIG := $($(TEST_OUTPUT)_CONFIG)
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
include $(BUILDDEFS_PATH)/common_rules.mk include $(BUILDDEFS_PATH)/common_rules.mk

View File

@ -180,18 +180,18 @@ For more granular control, there is `get_auto_shifted_key`. The default function
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
# ifndef NO_AUTO_SHIFT_ALPHA # ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z: case AUTO_SHIFT_ALPHA:
# endif # endif
# ifndef NO_AUTO_SHIFT_NUMERIC # ifndef NO_AUTO_SHIFT_NUMERIC
case KC_1 ... KC_0: case AUTO_SHIFT_NUMERIC:
# endif # endif
# ifndef NO_AUTO_SHIFT_SPECIAL # ifndef NO_AUTO_SHIFT_SPECIAL
# ifndef NO_AUTO_SHIFT_TAB # ifndef NO_AUTO_SHIFT_TAB
case KC_TAB: case KC_TAB:
# endif # endif
# ifndef NO_AUTO_SHIFT_SYMBOLS # ifndef NO_AUTO_SHIFT_SYMBOLS
case AUTO_SHIFT_SYMBOLS: case AUTO_SHIFT_SYMBOLS:
# endif # endif
# endif # endif
# ifdef AUTO_SHIFT_ENTER # ifdef AUTO_SHIFT_ENTER
case KC_ENT: case KC_ENT:
@ -310,10 +310,16 @@ generating taps on release. For example:
#define RETRO_SHIFT 500 #define RETRO_SHIFT 500
``` ```
Without a value set, holds of any length without an interrupting key will produce the shifted value.
This value (if set) must be greater than one's `TAPPING_TERM`, as the key press This value (if set) must be greater than one's `TAPPING_TERM`, as the key press
must be designated as a 'hold' by `process_tapping` before we send the modifier. must be designated as a 'hold' by `process_tapping` before we send the modifier.
[Per-key tapping terms](tap_hold.md#tapping-term) can be used as a workaround.
There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys. There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys.
**Note:** Tap Holds must be added to Auto Shift, see [here.](feature_auto_shift.md#auto-shift-per-key)
`IS_RETRO` may be helpful if one wants all Tap Holds retro shifted.
### Retro Shift and Tap Hold Configurations ### Retro Shift and Tap Hold Configurations
Tap Hold Configurations work a little differently when using Retro Shift. Tap Hold Configurations work a little differently when using Retro Shift.

View File

@ -36,7 +36,9 @@ Note how there's several different tests, each mocking out a separate part. Also
## Running the Tests ## Running the Tests
To run all the tests in the codebase, type `make test:all`. You can also run test matching a substring by typing `make test:matchingsubstring` Note that the tests are always compiled with the native compiler of your platform, so they are also run like any other program on your computer. To run all the tests in the codebase, type `make test:all`. You can also run test matching a substring by typing `make test:matchingsubstring`. `matchingsubstring` can contain colons to be more specific; `make test:tap_hold_configurations` will run the `tap_hold_configurations` tests for all features while `make test:retro_shift:tap_hold_configurations` will run the `tap_hold_configurations` tests for only the Retro Shift feature.
Note that the tests are always compiled with the native compiler of your platform, so they are also run like any other program on your computer.
## Debugging the Tests ## Debugging the Tests

View File

@ -497,7 +497,7 @@ void process_action(keyrecord_t *record, action_t action) {
default: default:
if (event.pressed) { if (event.pressed) {
if (tap_count > 0) { if (tap_count > 0) {
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY # ifdef HOLD_ON_OTHER_KEY_PRESS
if ( if (
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY # ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
get_hold_on_other_key_press(get_event_keycode(record->event, false), record) && get_hold_on_other_key_press(get_event_keycode(record->event, false), record) &&

View File

@ -116,25 +116,26 @@ void action_tapping_process(keyrecord_t record) {
* readable. The conditional definition of tapping_keycode and all the * readable. The conditional definition of tapping_keycode and all the
* conditional uses of it are hidden inside macros named TAP_... * conditional uses of it are hidden inside macros named TAP_...
*/ */
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) # define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
# define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
# else
# define TAP_DEFINE_KEYCODE
# endif
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) # if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
# ifdef RETRO_TAPPING_PER_KEY # ifdef RETRO_TAPPING_PER_KEY
# define TAP_GET_RETRO_TAPPING get_retro_tapping(tapping_keycode, &tapping_key) # define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp) && get_retro_tapping(tapping_keycode, &tapping_key)
# else # else
# define TAP_GET_RETRO_TAPPING true # define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp)
# endif # endif
# define MAYBE_RETRO_SHIFTING(ev) (TAP_GET_RETRO_TAPPING && (RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16((ev).time, tapping_key.event.time) < (RETRO_SHIFT + 0)) /* Used to extend TAPPING_TERM:
* indefinitely if RETRO_SHIFT does not have a value
* to RETRO_SHIFT if RETRO_SHIFT is set
* for possibly retro shifted keys.
*/
# define MAYBE_RETRO_SHIFTING(ev, keyp) (get_auto_shifted_key(tapping_keycode, keyp) && TAP_GET_RETRO_TAPPING(keyp) && ((RETRO_SHIFT + 0) == 0 || TIMER_DIFF_16((ev).time, tapping_key.event.time) < (RETRO_SHIFT + 0)))
# define TAP_IS_LT IS_QK_LAYER_TAP(tapping_keycode) # define TAP_IS_LT IS_QK_LAYER_TAP(tapping_keycode)
# define TAP_IS_MT IS_QK_MOD_TAP(tapping_keycode) # define TAP_IS_MT IS_QK_MOD_TAP(tapping_keycode)
# define TAP_IS_RETRO IS_RETRO(tapping_keycode) # define TAP_IS_RETRO IS_RETRO(tapping_keycode)
# else # else
# define TAP_GET_RETRO_TAPPING false # define TAP_GET_RETRO_TAPPING(keyp) false
# define MAYBE_RETRO_SHIFTING(ev) false # define MAYBE_RETRO_SHIFTING(ev, kp) false
# define TAP_IS_LT false # define TAP_IS_LT false
# define TAP_IS_MT false # define TAP_IS_MT false
# define TAP_IS_RETRO false # define TAP_IS_RETRO false
@ -187,20 +188,19 @@ bool process_tapping(keyrecord_t *keyp) {
return true; return true;
} }
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
TAP_DEFINE_KEYCODE; TAP_DEFINE_KEYCODE;
# endif
// process "pressed" tapping key state // process "pressed" tapping key state
if (tapping_key.event.pressed) { if (tapping_key.event.pressed) {
if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) { if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
if (IS_NOEVENT(event)) { if (IS_NOEVENT(event)) {
// early return for tick events // early return for tick events
return true; return true;
} }
if (tapping_key.tap.count == 0) { if (tapping_key.tap.count == 0) {
if (IS_TAPPING_RECORD(keyp) && !event.pressed) { if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
retroshift_swap_times();
# endif
// first tap! // first tap!
ac_dprintf("Tapping: First tap(0->1).\n"); ac_dprintf("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1; tapping_key.tap.count = 1;
@ -218,28 +218,12 @@ bool process_tapping(keyrecord_t *keyp) {
*/ */
// clang-format off // clang-format off
else if ( else if (
!event.pressed && waiting_buffer_typed(event) &&
( (
!event.pressed && waiting_buffer_typed(event) && TAP_GET_PERMISSIVE_HOLD ||
TAP_GET_PERMISSIVE_HOLD // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
) // unnecessarily and fixes them for Layer Taps.
// Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT TAP_GET_RETRO_TAPPING(keyp)
// unnecessarily and fixes them for Layer Taps.
|| (TAP_GET_RETRO_TAPPING &&
(
// Rolled over the two keys.
(tapping_key.tap.interrupted == true && (
(TAP_IS_LT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS) ||
(TAP_IS_MT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS)
)
)
// Makes Retro Shift ignore the default behavior of
// MTs and LTs on nested taps below TAPPING_TERM or RETRO_SHIFT
|| (
TAP_IS_RETRO
&& (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
&& !event.pressed && waiting_buffer_typed(event)
)
)
) )
) { ) {
// clang-format on // clang-format on
@ -284,10 +268,16 @@ bool process_tapping(keyrecord_t *keyp) {
process_record(keyp); process_record(keyp);
return true; return true;
} else { } else {
// set interrupted flag when other key preesed during tapping // set interrupted flag when other key pressed during tapping
if (event.pressed) { if (event.pressed) {
tapping_key.tap.interrupted = true; tapping_key.tap.interrupted = true;
if (TAP_GET_HOLD_ON_OTHER_KEY_PRESS) { if (TAP_GET_HOLD_ON_OTHER_KEY_PRESS
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
// Auto Shift cannot evaluate this early
// Retro Shift uses the hold action for all nested taps even without HOLD_ON_OTHER_KEY_PRESS, so this is fine to skip
&& !(MAYBE_RETRO_SHIFTING(event, keyp) && get_auto_shifted_key(get_record_keycode(keyp, false), keyp))
# endif
) {
ac_dprintf("Tapping: End. No tap. Interfered by pressed key\n"); ac_dprintf("Tapping: End. No tap. Interfered by pressed key\n");
process_record(&tapping_key); process_record(&tapping_key);
tapping_key = (keyrecord_t){0}; tapping_key = (keyrecord_t){0};
@ -332,6 +322,9 @@ bool process_tapping(keyrecord_t *keyp) {
return true; return true;
} else { } else {
ac_dprintf("Tapping: key event while last tap(>0).\n"); ac_dprintf("Tapping: key event while last tap(>0).\n");
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
retroshift_swap_times();
# endif
process_record(keyp); process_record(keyp);
return true; return true;
} }
@ -388,7 +381,7 @@ bool process_tapping(keyrecord_t *keyp) {
} }
// process "released" tapping key state // process "released" tapping key state
else { else {
if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) { if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
if (IS_NOEVENT(event)) { if (IS_NOEVENT(event)) {
// early return for tick events // early return for tick events
return true; return true;
@ -506,9 +499,16 @@ void waiting_buffer_scan_tap(void) {
return; return;
} }
# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT))
TAP_DEFINE_KEYCODE;
# endif
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
keyrecord_t *candidate = &waiting_buffer[i]; keyrecord_t *candidate = &waiting_buffer[i];
if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && WITHIN_TAPPING_TERM(candidate->event)) { // clang-format off
if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && (
WITHIN_TAPPING_TERM(waiting_buffer[i].event) || MAYBE_RETRO_SHIFTING(waiting_buffer[i].event, &tapping_key)
)) {
// clang-format on
tapping_key.tap.count = 1; tapping_key.tap.count = 1;
candidate->tap.count = 1; candidate->tap.count = 1;
process_record(&tapping_key); process_record(&tapping_key);

View File

@ -66,7 +66,7 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco
return false; return false;
} }
/** \brief Called on physical press, returns whether is Auto Shift key */ /** \brief Called on physical press, returns whether key is an Auto Shift key */
__attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) { __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
#ifndef NO_AUTO_SHIFT_ALPHA #ifndef NO_AUTO_SHIFT_ALPHA
@ -178,9 +178,8 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
} }
// Store record to be sent to user functions if there's no release record then. // Store record to be sent to user functions if there's no release record then.
autoshift_lastrecord = *record; autoshift_lastrecord = *record;
autoshift_lastrecord.event.pressed = false; autoshift_lastrecord.event.time = 0;
autoshift_lastrecord.event.time = 0;
// clang-format off // clang-format off
#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) #if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
if (keycode == autoshift_lastkey && if (keycode == autoshift_lastkey &&
@ -409,8 +408,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
// If Retro Shift is disabled, possible custom actions shouldn't happen. // If Retro Shift is disabled, possible custom actions shouldn't happen.
// clang-format off // clang-format off
#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) #if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY # ifdef HOLD_ON_OTHER_KEY_PRESS
const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record); const bool is_hold_on_interrupt = (IS_QK_MOD_TAP(keycode)
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
&& get_hold_on_other_key_press(keycode, record)
# endif
);
# else # else
const bool is_hold_on_interrupt = false; const bool is_hold_on_interrupt = false;
# endif # endif
@ -450,8 +453,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
#endif #endif
) { ) {
// Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set. // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY #ifdef HOLD_ON_OTHER_KEY_PRESS
if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) { if (autoshift_flags.in_progress
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
&& get_hold_on_other_key_press(keycode, record)
# endif
) {
autoshift_end(KC_NO, now, false, &autoshift_lastrecord); autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
} }
#endif #endif
@ -488,10 +495,8 @@ void retroshift_poll_time(keyevent_t *event) {
} }
// Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it. // Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
void retroshift_swap_times(void) { void retroshift_swap_times(void) {
if (last_retroshift_time != 0 && autoshift_flags.in_progress) { if (autoshift_flags.in_progress) {
uint16_t temp = retroshift_time; autoshift_time = last_retroshift_time;
retroshift_time = last_retroshift_time;
last_retroshift_time = temp;
} }
} }
#endif #endif

View File

@ -56,4 +56,5 @@ uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
void set_autoshift_timeout(uint16_t timeout); void set_autoshift_timeout(uint16_t timeout);
void autoshift_matrix_scan(void); void autoshift_matrix_scan(void);
bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record); bool get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
// clang-format on // clang-format on

View File

@ -0,0 +1,22 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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 AUTO_SHIFT_REPEAT
#define AUTO_SHIFT_NO_AUTO_REPEAT

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,105 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class AutoShiftNoAutoRepeat : public TestFixture {};
TEST_F(AutoShiftNoAutoRepeat, no_auto_repeat) {
TestDriver driver;
InSequence s;
auto repeat_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({repeat_key});
/* Press repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Idle for auto-repeat to (not) kick in. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(AutoShiftNoAutoRepeat, tap_regular_key_while_another_key_repeats) {
TestDriver driver;
InSequence s;
auto repeat_key = KeymapKey(0, 1, 0, KC_P);
auto regular_key = KeymapKey(0, 2, 0, KC_A);
set_keymap({repeat_key, regular_key});
/* Press repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release repeat key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
repeat_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press repeat key. */
EXPECT_REPORT(driver, (KC_P));
repeat_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_REPORT(driver, (KC_P, KC_A));
EXPECT_REPORT(driver, (KC_P));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release repeat key. */
EXPECT_EMPTY_REPORT(driver);
repeat_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,21 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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 AUTO_SHIFT_REPEAT

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,107 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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::AnyNumber;
using testing::InSequence;
class AutoShiftRepeat : public TestFixture {};
TEST_F(AutoShiftRepeat, tap_regular_key_cancelling_another_key_hold) {
TestDriver driver;
InSequence s;
auto repeat_key = KeymapKey(0, 1, 0, KC_P);
auto regular_key = KeymapKey(0, 2, 0, KC_A);
set_keymap({repeat_key, regular_key});
/* Press repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
EXPECT_REPORT(driver, (KC_P));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
EXPECT_REPORT(driver, (KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(AutoShiftRepeat, tap_regular_key_while_another_key_is_held) {
TestDriver driver;
InSequence s;
auto repeat_key = KeymapKey(0, 1, 0, KC_P);
auto regular_key = KeymapKey(0, 2, 0, KC_A);
set_keymap({repeat_key, regular_key});
/* Press repeat key. */
EXPECT_NO_REPORT(driver);
repeat_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Idle for auto-repeat to kick in. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_P));
idle_for(AUTO_SHIFT_TIMEOUT);
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_REPORT(driver, (KC_P, KC_A));
EXPECT_REPORT(driver, (KC_P));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release repeat key. */
EXPECT_EMPTY_REPORT(driver);
repeat_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,24 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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_SHIFT 2 * TAPPING_TERM
// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
#define AUTO_SHIFT_MODIFIERS

View File

@ -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_SHIFT

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,57 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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"
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using testing::_;
using testing::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class RetroShiftDefaultTapHold : public TestFixture {};
TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_for_long) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
set_keymap({mod_tap_hold_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
idle_for(4 * TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,485 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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"
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using testing::_;
using testing::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class RetroShiftDefaultTapHold : public TestFixture {};
TEST_F(RetroShiftDefaultTapHold, tap_mod_tap_key) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
set_keymap({mod_tap_hold_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_under_retro_shift) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
set_keymap({mod_tap_hold_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_over_retro_shift) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
set_keymap({mod_tap_hold_key});
/* Press mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_hold_key.press();
run_one_scan_loop();
idle_for(RETRO_SHIFT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, tap_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, hold_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, roll_tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, roll_tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, roll_hold_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_NO_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftDefaultTapHold, roll_hold_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,26 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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 HOLD_ON_OTHER_KEY_PRESS
#define RETRO_SHIFT 2 * TAPPING_TERM
// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
#define AUTO_SHIFT_MODIFIERS

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,442 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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"
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using testing::_;
using testing::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class RetroShiftHoldOnOtherKeyPress : public TestFixture {};
TEST_F(RetroShiftHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, hold_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, hold_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, roll_tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, roll_tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
EXPECT_EMPTY_REPORT(driver);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, roll_hold_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftHoldOnOtherKeyPress, roll_hold_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,26 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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
#define RETRO_SHIFT 2 * TAPPING_TERM
// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
#define AUTO_SHIFT_MODIFIERS

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,419 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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"
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using testing::_;
using testing::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class RetroShiftPermissiveHold : public TestFixture {};
TEST_F(RetroShiftPermissiveHold, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, tap_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, hold_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, hold_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, roll_tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, roll_tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, roll_hold_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_NO_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHold, roll_hold_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_REPORT(driver, (KC_P));
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,27 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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 HOLD_ON_OTHER_KEY_PRESS
#define PERMISSIVE_HOLD
#define RETRO_SHIFT 2 * TAPPING_TERM
// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
#define AUTO_SHIFT_MODIFIERS

View File

@ -0,0 +1,20 @@
# Copyright 2022 Isaac Elenbaas
#
# 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

View File

@ -0,0 +1,442 @@
/* Copyright 2022 Isaac Elenbaas
*
* 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"
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using testing::_;
using testing::AnyNumber;
using testing::AnyOf;
using testing::InSequence;
class RetroShiftPermissiveHoldHoldOnOtherKeyPress : public TestFixture {};
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, hold_regular_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, hold_mod_tap_key_while_mod_tap_key_is_held_over_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL));
mod_tap_regular_key.release();
run_one_scan_loop();
idle_for(TAPPING_TERM);
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_EMPTY_REPORT(driver);
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, roll_tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, roll_tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
EXPECT_REPORT(driver, (KC_LCTL, KC_A));
EXPECT_REPORT(driver, (KC_LCTL));
EXPECT_EMPTY_REPORT(driver);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, roll_hold_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto regular_key = KeymapKey(0, 1, 0, KC_A);
set_keymap({mod_tap_hold_key, regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press regular key. */
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, roll_hold_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
TestDriver driver;
InSequence s;
auto mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
auto mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
set_keymap({mod_tap_hold_key, mod_tap_regular_key});
/* Press mod-tap-hold key. */
EXPECT_NO_REPORT(driver);
mod_tap_hold_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Press mod-tap-regular key. */
EXPECT_NO_REPORT(driver);
mod_tap_regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-hold key. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
mod_tap_hold_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
/* Release mod-tap-regular key. */
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_REPORT(driver, (KC_LCTL, KC_LSFT, KC_A));
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(KC_LCTL, KC_LSFT),
KeyboardReport(KC_LSFT),
KeyboardReport(KC_LCTL))))
.Times(AnyNumber());
// clang-format on
EXPECT_EMPTY_REPORT(driver);
idle_for(AUTO_SHIFT_TIMEOUT);
mod_tap_regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}

View File

@ -0,0 +1,21 @@
// Copyright 2022 Google LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "test_common.h"
#define TAPPING_TERM 200
#define AUTO_SHIFT_TIMEOUT 150

View File

@ -27,6 +27,10 @@
KeyboardReport(KC_LSFT)))) KeyboardReport(KC_LSFT))))
// clang-format on // clang-format on
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
return true;
}
using ::testing::_; using ::testing::_;
using ::testing::AnyNumber; using ::testing::AnyNumber;
using ::testing::AnyOf; using ::testing::AnyOf;

View File

@ -0,0 +1,18 @@
# Copyright 2022 Google LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
CAPS_WORD_ENABLE = yes
AUTO_SHIFT_ENABLE = yes

View File

@ -0,0 +1,66 @@
// Copyright 2022 Google LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keyboard_report_util.hpp"
#include "keycode.h"
#include "test_common.hpp"
#include "test_fixture.hpp"
#include "test_keymap_key.hpp"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AnyOf;
using ::testing::InSequence;
class CapsWord : public TestFixture {
public:
void SetUp() override {
caps_word_off();
}
};
// Tests that with Auto Shift, letter keys are shifted by Caps Word
// regardless of whether they are released before AUTO_SHIFT_TIMEOUT.
TEST_F(CapsWord, AutoShiftKeys) {
TestDriver driver;
KeymapKey key_a(0, 0, 0, KC_A);
KeymapKey key_spc(0, 1, 0, KC_SPC);
set_keymap({key_a, key_spc});
// Allow any number of reports with no keys or only KC_LSFT.
// clang-format off
EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
KeyboardReport(),
KeyboardReport(KC_LSFT))))
.Times(AnyNumber());
// clang-format on
{ // Expect: "A, A, space, a".
InSequence s;
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_REPORT(driver, (KC_SPC));
EXPECT_REPORT(driver, (KC_A));
}
// Turn on Caps Word and type "A (quick tap), A (long press), space, A".
caps_word_on();
tap_key(key_a); // Tap A quickly.
tap_key(key_a, AUTO_SHIFT_TIMEOUT + 1); // Long press A.
tap_key(key_spc);
tap_key(key_a);
testing::Mock::VerifyAndClearExpectations(&driver);
}