forked from mirrors/qmk_userspace
		
	Improve test invocation, fix Retro Shift bugs, and add Auto+Retro Shift test cases (#15889)
This commit is contained in:
		
					parent
					
						
							
								1fb02d5ad8
							
						
					
				
			
			
				commit
				
					
						dd94877ec6
					
				
			
		
					 48 changed files with 2584 additions and 89 deletions
				
			
		
							
								
								
									
										26
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -300,17 +300,18 @@ endef
 | 
			
		|||
define BUILD_TEST
 | 
			
		||||
    TEST_PATH := $1
 | 
			
		||||
    TEST_NAME := $$(notdir $$(TEST_PATH))
 | 
			
		||||
    TEST_FULL_NAME := $$(subst /,_,$$(patsubst $$(ROOT_DIR)tests/%,%,$$(TEST_PATH)))
 | 
			
		||||
    MAKE_TARGET := $2
 | 
			
		||||
    COMMAND := $1
 | 
			
		||||
    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)
 | 
			
		||||
    $$(eval $$(call BUILD))
 | 
			
		||||
    ifneq ($$(MAKE_TARGET),clean)
 | 
			
		||||
        TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf
 | 
			
		||||
        TESTS += $$(TEST_NAME)
 | 
			
		||||
        TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_FULL_NAME).elf
 | 
			
		||||
        TESTS += $$(TEST_FULL_NAME)
 | 
			
		||||
        TEST_MSG := $$(MSG_TEST)
 | 
			
		||||
        $$(TEST_NAME)_COMMAND := \
 | 
			
		||||
        $$(TEST_FULL_NAME)_COMMAND := \
 | 
			
		||||
            printf "$$(TEST_MSG)\n"; \
 | 
			
		||||
            $$(TEST_EXECUTABLE); \
 | 
			
		||||
            if [ $$$$? -gt 0 ]; \
 | 
			
		||||
| 
						 | 
				
			
			@ -322,15 +323,22 @@ endef
 | 
			
		|||
 | 
			
		||||
define PARSE_TEST
 | 
			
		||||
    TESTS :=
 | 
			
		||||
    TEST_NAME := $$(firstword $$(subst :, ,$$(RULE)))
 | 
			
		||||
    TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE)))
 | 
			
		||||
    # list of possible targets, colon-delimited, to reassign to MAKE_TARGET and remove
 | 
			
		||||
    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
 | 
			
		||||
    ifeq ($$(TEST_NAME),all)
 | 
			
		||||
    ifeq ($$(RULE),all)
 | 
			
		||||
        MATCHED_TESTS := $$(TEST_LIST)
 | 
			
		||||
    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
 | 
			
		||||
    $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
 | 
			
		||||
    $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(MAKE_TARGET))))
 | 
			
		||||
endef
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,10 +13,10 @@
 | 
			
		|||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
$(TEST)_INC := \
 | 
			
		||||
$(TEST_OUTPUT)_INC := \
 | 
			
		||||
	tests/test_common/common_config.h
 | 
			
		||||
 | 
			
		||||
$(TEST)_SRC := \
 | 
			
		||||
$(TEST_OUTPUT)_SRC := \
 | 
			
		||||
	$(QUANTUM_SRC) \
 | 
			
		||||
	$(SRC) \
 | 
			
		||||
	$(QUANTUM_PATH)/keymap_introspection.c \
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +30,8 @@ $(TEST)_SRC := \
 | 
			
		|||
	tests/test_common/test_logger.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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,13 +9,13 @@ OPT = g
 | 
			
		|||
include paths.mk
 | 
			
		||||
include $(BUILDDEFS_PATH)/message.mk
 | 
			
		||||
 | 
			
		||||
TARGET=test/$(TEST)
 | 
			
		||||
TARGET=test/$(TEST_OUTPUT)
 | 
			
		||||
 | 
			
		||||
GTEST_OUTPUT = $(BUILD_DIR)/gtest
 | 
			
		||||
 | 
			
		||||
TEST_OBJ = $(BUILD_DIR)/test_obj
 | 
			
		||||
 | 
			
		||||
OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
 | 
			
		||||
OUTPUTS := $(TEST_OBJ)/$(TEST_OUTPUT) $(GTEST_OUTPUT)
 | 
			
		||||
 | 
			
		||||
GTEST_INC := \
 | 
			
		||||
	$(LIB_PATH)/googletest/googletest/include \
 | 
			
		||||
| 
						 | 
				
			
			@ -71,18 +71,18 @@ ifneq ($(filter $(FULL_TESTS),$(TEST)),)
 | 
			
		|||
include $(BUILDDEFS_PATH)/build_full_test.mk
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(TEST)_SRC += \
 | 
			
		||||
$(TEST_OUTPUT)_SRC += \
 | 
			
		||||
	tests/test_common/main.cpp \
 | 
			
		||||
	$(QUANTUM_PATH)/logging/print.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
 | 
			
		||||
 | 
			
		||||
$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
 | 
			
		||||
$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
 | 
			
		||||
$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
 | 
			
		||||
$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG)
 | 
			
		||||
$(TEST_OBJ)/$(TEST_OUTPUT)_SRC := $($(TEST_OUTPUT)_SRC)
 | 
			
		||||
$(TEST_OBJ)/$(TEST_OUTPUT)_INC := $($(TEST_OUTPUT)_INC) $(VPATH) $(GTEST_INC)
 | 
			
		||||
$(TEST_OBJ)/$(TEST_OUTPUT)_DEFS := $($(TEST_OUTPUT)_DEFS)
 | 
			
		||||
$(TEST_OBJ)/$(TEST_OUTPUT)_CONFIG := $($(TEST_OUTPUT)_CONFIG)
 | 
			
		||||
 | 
			
		||||
include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
 | 
			
		||||
include $(BUILDDEFS_PATH)/common_rules.mk
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
#    ifndef NO_AUTO_SHIFT_ALPHA
 | 
			
		||||
        case KC_A ... KC_Z:
 | 
			
		||||
        case AUTO_SHIFT_ALPHA:
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifndef NO_AUTO_SHIFT_NUMERIC
 | 
			
		||||
        case KC_1 ... KC_0:
 | 
			
		||||
        case AUTO_SHIFT_NUMERIC:
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifndef NO_AUTO_SHIFT_SPECIAL
 | 
			
		||||
#    ifndef NO_AUTO_SHIFT_TAB
 | 
			
		||||
#        ifndef NO_AUTO_SHIFT_TAB
 | 
			
		||||
        case KC_TAB:
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifndef NO_AUTO_SHIFT_SYMBOLS
 | 
			
		||||
#        endif
 | 
			
		||||
#        ifndef NO_AUTO_SHIFT_SYMBOLS
 | 
			
		||||
        case AUTO_SHIFT_SYMBOLS:
 | 
			
		||||
#    endif
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifdef AUTO_SHIFT_ENTER
 | 
			
		||||
        case KC_ENT:
 | 
			
		||||
| 
						 | 
				
			
			@ -310,10 +310,16 @@ generating taps on release. For example:
 | 
			
		|||
#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
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
**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
 | 
			
		||||
 | 
			
		||||
Tap Hold Configurations work a little differently when using Retro Shift.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,9 @@ Note how there's several different tests, each mocking out a separate part. Also
 | 
			
		|||
 | 
			
		||||
## 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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -497,7 +497,7 @@ void process_action(keyrecord_t *record, action_t action) {
 | 
			
		|||
                default:
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        if (tap_count > 0) {
 | 
			
		||||
#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 | 
			
		||||
#    ifdef HOLD_ON_OTHER_KEY_PRESS
 | 
			
		||||
                            if (
 | 
			
		||||
#        ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 | 
			
		||||
                                get_hold_on_other_key_press(get_event_keycode(record->event, false), record) &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,25 +116,26 @@ void action_tapping_process(keyrecord_t record) {
 | 
			
		|||
 * readable. The conditional definition of tapping_keycode and all the
 | 
			
		||||
 * 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)
 | 
			
		||||
#    else
 | 
			
		||||
#        define TAP_DEFINE_KEYCODE
 | 
			
		||||
#    endif
 | 
			
		||||
#    define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
 | 
			
		||||
 | 
			
		||||
#    if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
 | 
			
		||||
#        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
 | 
			
		||||
#            define TAP_GET_RETRO_TAPPING true
 | 
			
		||||
#            define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp)
 | 
			
		||||
#        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_MT IS_QK_MOD_TAP(tapping_keycode)
 | 
			
		||||
#        define TAP_IS_RETRO IS_RETRO(tapping_keycode)
 | 
			
		||||
#    else
 | 
			
		||||
#        define TAP_GET_RETRO_TAPPING false
 | 
			
		||||
#        define MAYBE_RETRO_SHIFTING(ev) false
 | 
			
		||||
#        define TAP_GET_RETRO_TAPPING(keyp) false
 | 
			
		||||
#        define MAYBE_RETRO_SHIFTING(ev, kp) false
 | 
			
		||||
#        define TAP_IS_LT false
 | 
			
		||||
#        define TAP_IS_MT false
 | 
			
		||||
#        define TAP_IS_RETRO false
 | 
			
		||||
| 
						 | 
				
			
			@ -187,20 +188,19 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
        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;
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
    // process "pressed" tapping key state
 | 
			
		||||
    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)) {
 | 
			
		||||
                // early return for tick events
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (tapping_key.tap.count == 0) {
 | 
			
		||||
                if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
 | 
			
		||||
#    if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
 | 
			
		||||
                    retroshift_swap_times();
 | 
			
		||||
#    endif
 | 
			
		||||
                    // first tap!
 | 
			
		||||
                    ac_dprintf("Tapping: First tap(0->1).\n");
 | 
			
		||||
                    tapping_key.tap.count = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -218,28 +218,12 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
                 */
 | 
			
		||||
                // clang-format off
 | 
			
		||||
                else if (
 | 
			
		||||
                    !event.pressed && waiting_buffer_typed(event) &&
 | 
			
		||||
                    (
 | 
			
		||||
                        !event.pressed && waiting_buffer_typed(event) &&
 | 
			
		||||
                        TAP_GET_PERMISSIVE_HOLD
 | 
			
		||||
                    )
 | 
			
		||||
                    // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
 | 
			
		||||
                    // 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)
 | 
			
		||||
                            )
 | 
			
		||||
                        )
 | 
			
		||||
                        TAP_GET_PERMISSIVE_HOLD ||
 | 
			
		||||
                        // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
 | 
			
		||||
                        // unnecessarily and fixes them for Layer Taps.
 | 
			
		||||
                        TAP_GET_RETRO_TAPPING(keyp)
 | 
			
		||||
                    )
 | 
			
		||||
                ) {
 | 
			
		||||
                    // clang-format on
 | 
			
		||||
| 
						 | 
				
			
			@ -284,10 +268,16 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
                    process_record(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // set interrupted flag when other key preesed during tapping
 | 
			
		||||
                    // set interrupted flag when other key pressed during tapping
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        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");
 | 
			
		||||
                            process_record(&tapping_key);
 | 
			
		||||
                            tapping_key = (keyrecord_t){0};
 | 
			
		||||
| 
						 | 
				
			
			@ -332,6 +322,9 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    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);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -388,7 +381,7 @@ bool process_tapping(keyrecord_t *keyp) {
 | 
			
		|||
    }
 | 
			
		||||
    // process "released" tapping key state
 | 
			
		||||
    else {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
 | 
			
		||||
            if (IS_NOEVENT(event)) {
 | 
			
		||||
                // early return for tick events
 | 
			
		||||
                return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -506,9 +499,16 @@ void waiting_buffer_scan_tap(void) {
 | 
			
		|||
        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) {
 | 
			
		||||
        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;
 | 
			
		||||
            candidate->tap.count  = 1;
 | 
			
		||||
            process_record(&tapping_key);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco
 | 
			
		|||
    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) {
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
#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.
 | 
			
		||||
    autoshift_lastrecord               = *record;
 | 
			
		||||
    autoshift_lastrecord.event.pressed = false;
 | 
			
		||||
    autoshift_lastrecord.event.time    = 0;
 | 
			
		||||
    autoshift_lastrecord            = *record;
 | 
			
		||||
    autoshift_lastrecord.event.time = 0;
 | 
			
		||||
    // clang-format off
 | 
			
		||||
#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
 | 
			
		||||
    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.
 | 
			
		||||
            // clang-format off
 | 
			
		||||
#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
 | 
			
		||||
#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 | 
			
		||||
            const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record);
 | 
			
		||||
#    ifdef HOLD_ON_OTHER_KEY_PRESS
 | 
			
		||||
            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
 | 
			
		||||
            const bool is_hold_on_interrupt = false;
 | 
			
		||||
#    endif
 | 
			
		||||
| 
						 | 
				
			
			@ -450,8 +453,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
#endif
 | 
			
		||||
        ) {
 | 
			
		||||
            // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
 | 
			
		||||
#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 | 
			
		||||
            if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) {
 | 
			
		||||
#ifdef HOLD_ON_OTHER_KEY_PRESS
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
#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.
 | 
			
		||||
void retroshift_swap_times(void) {
 | 
			
		||||
    if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
 | 
			
		||||
        uint16_t temp        = retroshift_time;
 | 
			
		||||
        retroshift_time      = last_retroshift_time;
 | 
			
		||||
        last_retroshift_time = temp;
 | 
			
		||||
    if (autoshift_flags.in_progress) {
 | 
			
		||||
        autoshift_time = last_retroshift_time;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,4 +56,5 @@ uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
 | 
			
		|||
void     set_autoshift_timeout(uint16_t timeout);
 | 
			
		||||
void     autoshift_matrix_scan(void);
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								tests/auto_shift/auto_shift_repeat/config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/auto_shift/auto_shift_repeat/config.h
									
										
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										20
									
								
								tests/auto_shift/auto_shift_repeat/test.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/auto_shift/auto_shift_repeat/test.mk
									
										
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										107
									
								
								tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
									
										
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,4 +16,4 @@
 | 
			
		|||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -17,4 +17,4 @@
 | 
			
		|||
# Keep this file, even if it is empty, as a marker that this folder contains tests
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
AUTO_SHIFT_ENABLE = yes
 | 
			
		||||
AUTO_SHIFT_ENABLE = yes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,4 +16,4 @@
 | 
			
		|||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,4 +15,4 @@
 | 
			
		|||
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
# Keep this file, even if it is empty, as a marker that this folder contains tests
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								tests/caps_word/auto_shift/config.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/caps_word/auto_shift/config.h
									
										
									
									
									
										Normal 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
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +27,10 @@
 | 
			
		|||
            KeyboardReport(KC_LSFT))))
 | 
			
		||||
// clang-format on
 | 
			
		||||
 | 
			
		||||
bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using ::testing::_;
 | 
			
		||||
using ::testing::AnyNumber;
 | 
			
		||||
using ::testing::AnyOf;
 | 
			
		||||
							
								
								
									
										18
									
								
								tests/caps_word/auto_shift/test.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/caps_word/auto_shift/test.mk
									
										
									
									
									
										Normal 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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
									
										
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -15,4 +15,4 @@
 | 
			
		|||
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
# Keep this file, even if it is empty, as a marker that this folder contains tests
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
# --------------------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,4 +18,4 @@
 | 
			
		|||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
 | 
			
		||||
#define PERMISSIVE_HOLD
 | 
			
		||||
#define PERMISSIVE_HOLD
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,4 +13,4 @@
 | 
			
		|||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
CUSTOM_MATRIX=yes
 | 
			
		||||
CUSTOM_MATRIX=yes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,4 +29,4 @@ int main(int argc, char **argv) {
 | 
			
		|||
    init_logging();
 | 
			
		||||
 | 
			
		||||
    return RUN_ALL_TESTS();
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define MATRIX_ROWS 4
 | 
			
		||||
#define MATRIX_COLS 10
 | 
			
		||||
#define MATRIX_COLS 10
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue