dd94877ec6d2ee5c4cdb0e71287abd76585b0268

Author
Isaac Elenbaas <isaacelenbaas@gmail.com>
Committer
GitHub <noreply@github.com>
Date

Message

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

Diff

This diff is truncated to protect this page.

   1diff --git a/Makefile b/Makefile
   2index 9f2e4636a4b478cbe6752b9d9e749e2915abf766..9ef406e420618b5fb0093da63a953580d7d20748 100644
   3--- a/Makefile
   4+++ b/Makefile
   5@@ -300,17 +300,18 @@ endef
   6 define BUILD_TEST
   7     TEST_PATH := $1
   8     TEST_NAME := $$(notdir $$(TEST_PATH))
   9+    TEST_FULL_NAME := $$(subst /,_,$$(patsubst $$(ROOT_DIR)tests/%,%,$$(TEST_PATH)))
  10     MAKE_TARGET := $2
  11     COMMAND := $1
  12     MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f $(BUILDDEFS_PATH)/build_test.mk $$(MAKE_TARGET)
  13-    MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
  14+    MAKE_VARS := TEST=$$(TEST_NAME) TEST_OUTPUT=$$(TEST_FULL_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
  15     MAKE_MSG := $$(MSG_MAKE_TEST)
  16     $$(eval $$(call BUILD))
  17     ifneq ($$(MAKE_TARGET),clean)
  18-        TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_NAME).elf
  19-        TESTS += $$(TEST_NAME)
  20+        TEST_EXECUTABLE := $$(TEST_OUTPUT_DIR)/$$(TEST_FULL_NAME).elf
  21+        TESTS += $$(TEST_FULL_NAME)
  22         TEST_MSG := $$(MSG_TEST)
  23-        $$(TEST_NAME)_COMMAND := \
  24+        $$(TEST_FULL_NAME)_COMMAND := \
  25             printf "$$(TEST_MSG)\n"; \
  26             $$(TEST_EXECUTABLE); \
  27             if [ $$$$? -gt 0 ]; \
  28@@ -322,15 +323,22 @@ endef
  29 
  30 define PARSE_TEST
  31     TESTS :=
  32-    TEST_NAME := $$(firstword $$(subst :, ,$$(RULE)))
  33-    TEST_TARGET := $$(subst $$(TEST_NAME),,$$(subst $$(TEST_NAME):,,$$(RULE)))
  34+    # list of possible targets, colon-delimited, to reassign to MAKE_TARGET and remove
  35+    TARGETS := :clean:
  36+    ifneq (,$$(findstring :$$(lastword $$(subst :, ,$$(RULE))):, $$(TARGETS)))
  37+        MAKE_TARGET := $$(lastword $$(subst :, ,$$(RULE)))
  38+        TEST_SUBPATH := $$(subst $$(eval) ,/,$$(wordlist 2, $$(words $$(subst :, ,$$(RULE))), _ $$(subst :, ,$$(RULE))))
  39+    else
  40+        MAKE_TARGET :=
  41+        TEST_SUBPATH := $$(subst :,/,$$(RULE))
  42+    endif
  43     include $(BUILDDEFS_PATH)/testlist.mk
  44-    ifeq ($$(TEST_NAME),all)
  45+    ifeq ($$(RULE),all)
  46         MATCHED_TESTS := $$(TEST_LIST)
  47     else
  48-        MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring x$$(TEST_NAME)x, x$$(notdir $$(TEST))x), $$(TEST),))
  49+        MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring /$$(TEST_SUBPATH)/, $$(patsubst %,%/,$$(TEST))), $$(TEST),))
  50     endif
  51-    $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
  52+    $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(MAKE_TARGET))))
  53 endef
  54 
  55 
  56diff --git a/builddefs/build_full_test.mk b/builddefs/build_full_test.mk
  57index 85ee0898ec2d32172075856005f4702cbd718413..63f9fea915db61cbab3e638bc6febf7c441f66d3 100644
  58--- a/builddefs/build_full_test.mk
  59+++ b/builddefs/build_full_test.mk
  60@@ -13,10 +13,10 @@
  61 # You should have received a copy of the GNU General Public License
  62 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  63 
  64-$(TEST)_INC := \
  65+$(TEST_OUTPUT)_INC := \
  66 	tests/test_common/common_config.h
  67 
  68-$(TEST)_SRC := \
  69+$(TEST_OUTPUT)_SRC := \
  70 	$(QUANTUM_SRC) \
  71 	$(SRC) \
  72 	$(QUANTUM_PATH)/keymap_introspection.c \
  73@@ -30,8 +30,8 @@ $(TEST)_SRC := \
  74 	tests/test_common/test_logger.cpp \
  75 	$(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
  76 
  77-$(TEST)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
  78+$(TEST_OUTPUT)_DEFS := $(OPT_DEFS) "-DKEYMAP_C=\"keymap.c\""
  79 
  80-$(TEST)_CONFIG := $(TEST_PATH)/config.h
  81+$(TEST_OUTPUT)_CONFIG := $(TEST_PATH)/config.h
  82 
  83 VPATH += $(TOP_DIR)/tests/test_common
  84diff --git a/builddefs/build_test.mk b/builddefs/build_test.mk
  85index 9eead77beabd9e1c187bb93bcf0d443dec735428..2cc1134da5b3eb791fd1be52f0b8b80290a27553 100644
  86--- a/builddefs/build_test.mk
  87+++ b/builddefs/build_test.mk
  88@@ -9,13 +9,13 @@ OPT = g
  89 include paths.mk
  90 include $(BUILDDEFS_PATH)/message.mk
  91 
  92-TARGET=test/$(TEST)
  93+TARGET=test/$(TEST_OUTPUT)
  94 
  95 GTEST_OUTPUT = $(BUILD_DIR)/gtest
  96 
  97 TEST_OBJ = $(BUILD_DIR)/test_obj
  98 
  99-OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
 100+OUTPUTS := $(TEST_OBJ)/$(TEST_OUTPUT) $(GTEST_OUTPUT)
 101 
 102 GTEST_INC := \
 103 	$(LIB_PATH)/googletest/googletest/include \
 104@@ -71,18 +71,18 @@ ifneq ($(filter $(FULL_TESTS),$(TEST)),)
 105 include $(BUILDDEFS_PATH)/build_full_test.mk
 106 endif
 107 
 108-$(TEST)_SRC += \
 109+$(TEST_OUTPUT)_SRC += \
 110 	tests/test_common/main.cpp \
 111 	$(QUANTUM_PATH)/logging/print.c
 112 
 113 ifneq ($(strip $(INTROSPECTION_KEYMAP_C)),)
 114-$(TEST)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
 115+$(TEST_OUTPUT)_DEFS += -DINTROSPECTION_KEYMAP_C=\"$(strip $(INTROSPECTION_KEYMAP_C))\"
 116 endif
 117 
 118-$(TEST_OBJ)/$(TEST)_SRC := $($(TEST)_SRC)
 119-$(TEST_OBJ)/$(TEST)_INC := $($(TEST)_INC) $(VPATH) $(GTEST_INC)
 120-$(TEST_OBJ)/$(TEST)_DEFS := $($(TEST)_DEFS)
 121-$(TEST_OBJ)/$(TEST)_CONFIG := $($(TEST)_CONFIG)
 122+$(TEST_OBJ)/$(TEST_OUTPUT)_SRC := $($(TEST_OUTPUT)_SRC)
 123+$(TEST_OBJ)/$(TEST_OUTPUT)_INC := $($(TEST_OUTPUT)_INC) $(VPATH) $(GTEST_INC)
 124+$(TEST_OBJ)/$(TEST_OUTPUT)_DEFS := $($(TEST_OUTPUT)_DEFS)
 125+$(TEST_OBJ)/$(TEST_OUTPUT)_CONFIG := $($(TEST_OUTPUT)_CONFIG)
 126 
 127 include $(PLATFORM_PATH)/$(PLATFORM_KEY)/platform.mk
 128 include $(BUILDDEFS_PATH)/common_rules.mk
 129diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
 130index 6241cbaeb1587a286181ca96268fe265e50de052..74be33cdd47bd3afbbd4c880c4127fc065b852c1 100644
 131--- a/docs/feature_auto_shift.md
 132+++ b/docs/feature_auto_shift.md
 133@@ -180,18 +180,18 @@ For more granular control, there is `get_auto_shifted_key`. The default function
 134 bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
 135     switch (keycode) {
 136 #    ifndef NO_AUTO_SHIFT_ALPHA
 137-        case KC_A ... KC_Z:
 138+        case AUTO_SHIFT_ALPHA:
 139 #    endif
 140 #    ifndef NO_AUTO_SHIFT_NUMERIC
 141-        case KC_1 ... KC_0:
 142+        case AUTO_SHIFT_NUMERIC:
 143 #    endif
 144 #    ifndef NO_AUTO_SHIFT_SPECIAL
 145-#    ifndef NO_AUTO_SHIFT_TAB
 146+#        ifndef NO_AUTO_SHIFT_TAB
 147         case KC_TAB:
 148-#    endif
 149-#    ifndef NO_AUTO_SHIFT_SYMBOLS
 150+#        endif
 151+#        ifndef NO_AUTO_SHIFT_SYMBOLS
 152         case AUTO_SHIFT_SYMBOLS:
 153-#    endif
 154+#        endif
 155 #    endif
 156 #    ifdef AUTO_SHIFT_ENTER
 157         case KC_ENT:
 158@@ -310,10 +310,16 @@ generating taps on release. For example:
 159 #define RETRO_SHIFT 500
 160 ```
 161 
 162+Without a value set, holds of any length without an interrupting key will produce the shifted value.
 163+
 164 This value (if set) must be greater than one's `TAPPING_TERM`, as the key press
 165 must be designated as a 'hold' by `process_tapping` before we send the modifier.
 166+[Per-key tapping terms](tap_hold.md#tapping-term) can be used as a workaround.
 167 There is no such limitation in regards to `AUTO_SHIFT_TIMEOUT` for normal keys.
 168 
 169+**Note:** Tap Holds must be added to Auto Shift, see [here.](feature_auto_shift.md#auto-shift-per-key)
 170+`IS_RETRO` may be helpful if one wants all Tap Holds retro shifted.
 171+
 172 ### Retro Shift and Tap Hold Configurations
 173 
 174 Tap Hold Configurations work a little differently when using Retro Shift.
 175diff --git a/docs/unit_testing.md b/docs/unit_testing.md
 176index 47a1055796435d1a4f70b7ab19a192d695171028..60787fdffcf2cfaa47639602cafceab0c4b5716e 100644
 177--- a/docs/unit_testing.md
 178+++ b/docs/unit_testing.md
 179@@ -36,7 +36,9 @@ Note how there's several different tests, each mocking out a separate part. Also
 180 
 181 ## Running the Tests
 182 
 183diff --git a/quantum/action.c b/quantum/action.c
 184index 6368f7398c610013c115e13fe187df0ac3555fc9..3b89431cea0889906cfe852b71e3f6bdcfe16549 100644
 185--- a/quantum/action.c
 186+++ b/quantum/action.c
 187@@ -497,7 +497,7 @@ void process_action(keyrecord_t *record, action_t action) {
 188                 default:
 189                     if (event.pressed) {
 190                         if (tap_count > 0) {
 191-#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 192+#    ifdef HOLD_ON_OTHER_KEY_PRESS
 193                             if (
 194 #        ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 195                                 get_hold_on_other_key_press(get_event_keycode(record->event, false), record) &&
 196diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c
 197index f94e5e6f693ce623dd0aad4e30ad81b0fb004f22..8f238490f2a883e23ecd572d83f2bab8aee08023 100644
 198--- a/quantum/action_tapping.c
 199+++ b/quantum/action_tapping.c
 200@@ -116,25 +116,26 @@ void action_tapping_process(keyrecord_t record) {
 201  * readable. The conditional definition of tapping_keycode and all the
 202  * conditional uses of it are hidden inside macros named TAP_...
 203  */
 204-#    if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
 205-#        define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
 206-#    else
 207-#        define TAP_DEFINE_KEYCODE
 208-#    endif
 209+#    define TAP_DEFINE_KEYCODE const uint16_t tapping_keycode = get_record_keycode(&tapping_key, false)
 210 
 211 #    if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
 212 #        ifdef RETRO_TAPPING_PER_KEY
 213-#            define TAP_GET_RETRO_TAPPING get_retro_tapping(tapping_keycode, &tapping_key)
 214+#            define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp) && get_retro_tapping(tapping_keycode, &tapping_key)
 215 #        else
 216-#            define TAP_GET_RETRO_TAPPING true
 217+#            define TAP_GET_RETRO_TAPPING(keyp) get_auto_shifted_key(tapping_keycode, keyp)
 218 #        endif
 219-#        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))
 220+/* Used to extend TAPPING_TERM:
 221+ *     indefinitely if RETRO_SHIFT does not have a value
 222+ *     to RETRO_SHIFT if RETRO_SHIFT is set
 223+ * for possibly retro shifted keys.
 224+ */
 225+#        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)))
 226 #        define TAP_IS_LT IS_QK_LAYER_TAP(tapping_keycode)
 227 #        define TAP_IS_MT IS_QK_MOD_TAP(tapping_keycode)
 228 #        define TAP_IS_RETRO IS_RETRO(tapping_keycode)
 229 #    else
 230-#        define TAP_GET_RETRO_TAPPING false
 231-#        define MAYBE_RETRO_SHIFTING(ev) false
 232+#        define TAP_GET_RETRO_TAPPING(keyp) false
 233+#        define MAYBE_RETRO_SHIFTING(ev, kp) false
 234 #        define TAP_IS_LT false
 235 #        define TAP_IS_MT false
 236 #        define TAP_IS_RETRO false
 237@@ -187,20 +188,19 @@ bool process_tapping(keyrecord_t *keyp) {
 238         return true;
 239     }
 240 
 241+#    if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
 242     TAP_DEFINE_KEYCODE;
 243+#    endif
 244 
 245     // process "pressed" tapping key state
 246     if (tapping_key.event.pressed) {
 247-        if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event)) {
 248+        if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) {
 249             if (IS_NOEVENT(event)) {
 250                 // early return for tick events
 251                 return true;
 252             }
 253             if (tapping_key.tap.count == 0) {
 254                 if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
 255-#    if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
 256-                    retroshift_swap_times();
 257-#    endif
 258                     // first tap!
 259                     ac_dprintf("Tapping: First tap(0->1).\n");
 260                     tapping_key.tap.count = 1;
 261@@ -218,28 +218,12 @@ bool process_tapping(keyrecord_t *keyp) {
 262                  */
 263                 // clang-format off
 264                 else if (
 265+                    !event.pressed && waiting_buffer_typed(event) &&
 266                     (
 267-                        !event.pressed && waiting_buffer_typed(event) &&
 268-                        TAP_GET_PERMISSIVE_HOLD
 269-                    )
 270-                    // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
 271-                    // unnecessarily and fixes them for Layer Taps.
 272-                    || (TAP_GET_RETRO_TAPPING &&
 273-                        (
 274-                            // Rolled over the two keys.
 275-                            (tapping_key.tap.interrupted == true && (
 276-                                (TAP_IS_LT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS) ||
 277-                                (TAP_IS_MT && TAP_GET_HOLD_ON_OTHER_KEY_PRESS)
 278-                                )
 279-                            )
 280-                            // Makes Retro Shift ignore the default behavior of
 281-                            // MTs and LTs on nested taps below TAPPING_TERM or RETRO_SHIFT
 282-                            || (
 283-                                TAP_IS_RETRO
 284-                                && (event.key.col != tapping_key.event.key.col || event.key.row != tapping_key.event.key.row)
 285-                                && !event.pressed && waiting_buffer_typed(event)
 286-                            )
 287-                        )
 288+                        TAP_GET_PERMISSIVE_HOLD ||
 289+                        // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT
 290+                        // unnecessarily and fixes them for Layer Taps.
 291+                        TAP_GET_RETRO_TAPPING(keyp)
 292                     )
 293                 ) {
 294                     // clang-format on
 295@@ -284,10 +268,16 @@ bool process_tapping(keyrecord_t *keyp) {
 296                     process_record(keyp);
 297                     return true;
 298                 } else {
 299-                    // set interrupted flag when other key preesed during tapping
 300diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
 301index 9b78214e438a7435bd11d4b882ad022b3ff63a10..28a21c4b670f553fe676635a9ee7a353a9f328c9 100644
 302--- a/quantum/process_keycode/process_auto_shift.c
 303+++ b/quantum/process_keycode/process_auto_shift.c
 304@@ -66,7 +66,7 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco
 305     return false;
 306 }
 307 
 308-/** \brief Called on physical press, returns whether is Auto Shift key */
 309+/** \brief Called on physical press, returns whether key is an Auto Shift key */
 310 __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
 311     switch (keycode) {
 312 #ifndef NO_AUTO_SHIFT_ALPHA
 313@@ -178,9 +178,8 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)
 314     }
 315 
 316     // Store record to be sent to user functions if there's no release record then.
 317-    autoshift_lastrecord               = *record;
 318-    autoshift_lastrecord.event.pressed = false;
 319-    autoshift_lastrecord.event.time    = 0;
 320+    autoshift_lastrecord            = *record;
 321+    autoshift_lastrecord.event.time = 0;
 322     // clang-format off
 323 #if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)
 324     if (keycode == autoshift_lastkey &&
 325@@ -409,8 +408,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
 326             // If Retro Shift is disabled, possible custom actions shouldn't happen.
 327             // clang-format off
 328 #if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)
 329-#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 330-            const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record);
 331+#    ifdef HOLD_ON_OTHER_KEY_PRESS
 332+            const bool is_hold_on_interrupt = (IS_QK_MOD_TAP(keycode)
 333+#        ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 334+                && get_hold_on_other_key_press(keycode, record)
 335+#        endif
 336+            );
 337 #    else
 338             const bool is_hold_on_interrupt = false;
 339 #    endif
 340@@ -450,8 +453,12 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
 341 #endif
 342         ) {
 343             // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set.
 344-#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 345-            if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) {
 346+#ifdef HOLD_ON_OTHER_KEY_PRESS
 347+            if (autoshift_flags.in_progress
 348+#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 349+                && get_hold_on_other_key_press(keycode, record)
 350+#    endif
 351+            ) {
 352                 autoshift_end(KC_NO, now, false, &autoshift_lastrecord);
 353             }
 354 #endif
 355@@ -488,10 +495,8 @@ void retroshift_poll_time(keyevent_t *event) {
 356 }
 357 // Used to swap the times of Retro Shifted key and Auto Shift key that interrupted it.
 358 void retroshift_swap_times(void) {
 359-    if (last_retroshift_time != 0 && autoshift_flags.in_progress) {
 360-        uint16_t temp        = retroshift_time;
 361-        retroshift_time      = last_retroshift_time;
 362-        last_retroshift_time = temp;
 363+    if (autoshift_flags.in_progress) {
 364+        autoshift_time = last_retroshift_time;
 365     }
 366 }
 367 #endif
 368diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
 369index 885a47b5339dcb3cd41e1e4f26f8925c7c3ffd3e..1353548aa6caf5d9a2f3e02d5b6f60afac5a10f2 100644
 370--- a/quantum/process_keycode/process_auto_shift.h
 371+++ b/quantum/process_keycode/process_auto_shift.h
 372@@ -56,4 +56,5 @@ uint16_t (get_autoshift_timeout)(uint16_t keycode, keyrecord_t *record);
 373 void     set_autoshift_timeout(uint16_t timeout);
 374 void     autoshift_matrix_scan(void);
 375 bool     get_custom_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
 376+bool     get_auto_shifted_key(uint16_t keycode, keyrecord_t *record);
 377 // clang-format on
 378diff --git a/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/config.h b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/config.h
 379new file mode 100644
 380index 0000000000000000000000000000000000000000..973e04582fda8ee18bfcf960ac1c45ae30bb0d7f
 381--- /dev/null
 382+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/config.h
 383@@ -0,0 +1,22 @@
 384+/* Copyright 2022 Isaac Elenbaas
 385+ *
 386+ * This program is free software: you can redistribute it and/or modify
 387+ * it under the terms of the GNU General Public License as published by
 388+ * the Free Software Foundation, either version 2 of the License, or
 389+ * (at your option) any later version.
 390+ *
 391+ * This program is distributed in the hope that it will be useful,
 392+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 393+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 394+ * GNU General Public License for more details.
 395+ *
 396+ * You should have received a copy of the GNU General Public License
 397+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 398+ */
 399+
 400+#pragma once
 401+
 402+#include "test_common.h"
 403+
 404+#define AUTO_SHIFT_REPEAT
 405+#define AUTO_SHIFT_NO_AUTO_REPEAT
 406diff --git a/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test.mk b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test.mk
 407new file mode 100644
 408index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
 409--- /dev/null
 410+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test.mk
 411@@ -0,0 +1,20 @@
 412+# Copyright 2022 Isaac Elenbaas
 413+#
 414+# This program is free software: you can redistribute it and/or modify
 415+# it under the terms of the GNU General Public License as published by
 416+# the Free Software Foundation, either version 2 of the License, or
 417+# (at your option) any later version.
 418+#
 419+# This program is distributed in the hope that it will be useful,
 420+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 421+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 422+# GNU General Public License for more details.
 423+#
 424+# You should have received a copy of the GNU General Public License
 425+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 426+
 427+# --------------------------------------------------------------------------------
 428+# Keep this file, even if it is empty, as a marker that this folder contains tests
 429+# --------------------------------------------------------------------------------
 430+
 431+AUTO_SHIFT_ENABLE = yes
 432diff --git a/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test_auto_shift.cpp b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test_auto_shift.cpp
 433new file mode 100644
 434index 0000000000000000000000000000000000000000..cd219a547461ce37cccc12f51274e3080a12e427
 435--- /dev/null
 436+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test_auto_shift.cpp
 437@@ -0,0 +1,105 @@
 438+/* Copyright 2022 Isaac Elenbaas
 439+ *
 440+ * This program is free software: you can redistribute it and/or modify
 441+ * it under the terms of the GNU General Public License as published by
 442+ * the Free Software Foundation, either version 2 of the License, or
 443+ * (at your option) any later version.
 444+ *
 445+ * This program is distributed in the hope that it will be useful,
 446+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 447+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 448+ * GNU General Public License for more details.
 449+ *
 450+ * You should have received a copy of the GNU General Public License
 451+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 452+ */
 453+
 454+#include "keyboard_report_util.hpp"
 455+#include "keycode.h"
 456+#include "test_common.hpp"
 457+#include "action_tapping.h"
 458+#include "test_fixture.hpp"
 459+#include "test_keymap_key.hpp"
 460+
 461+using testing::_;
 462+using testing::AnyNumber;
 463+using testing::AnyOf;
 464+using testing::InSequence;
 465+
 466+class AutoShiftNoAutoRepeat : public TestFixture {};
 467+
 468+TEST_F(AutoShiftNoAutoRepeat, no_auto_repeat) {
 469+    TestDriver driver;
 470+    InSequence s;
 471+    auto       repeat_key = KeymapKey(0, 1, 0, KC_A);
 472+
 473+    set_keymap({repeat_key});
 474+
 475+    /* Press repeat key. */
 476+    EXPECT_NO_REPORT(driver);
 477+    repeat_key.press();
 478+    run_one_scan_loop();
 479+    testing::Mock::VerifyAndClearExpectations(&driver);
 480+
 481+    /* Idle for auto-repeat to (not) kick in. */
 482+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 483+    EXPECT_REPORT(driver, (KC_LSFT, KC_A));
 484+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 485+    EXPECT_EMPTY_REPORT(driver);
 486+    idle_for(AUTO_SHIFT_TIMEOUT);
 487+    run_one_scan_loop();
 488+    testing::Mock::VerifyAndClearExpectations(&driver);
 489+
 490+    /* Release repeat key. */
 491+    EXPECT_NO_REPORT(driver);
 492+    repeat_key.release();
 493+    run_one_scan_loop();
 494+    testing::Mock::VerifyAndClearExpectations(&driver);
 495+}
 496+
 497+TEST_F(AutoShiftNoAutoRepeat, tap_regular_key_while_another_key_repeats) {
 498+    TestDriver driver;
 499+    InSequence s;
 500+    auto       repeat_key  = KeymapKey(0, 1, 0, KC_P);
 501+    auto       regular_key = KeymapKey(0, 2, 0, KC_A);
 502+
 503+    set_keymap({repeat_key, regular_key});
 504+
 505+    /* Press repeat key. */
 506+    EXPECT_NO_REPORT(driver);
 507+    repeat_key.press();
 508+    run_one_scan_loop();
 509+    testing::Mock::VerifyAndClearExpectations(&driver);
 510+
 511+    /* Release repeat key. */
 512+    EXPECT_REPORT(driver, (KC_P));
 513+    EXPECT_EMPTY_REPORT(driver);
 514+    repeat_key.release();
 515+    run_one_scan_loop();
 516+    testing::Mock::VerifyAndClearExpectations(&driver);
 517+
 518+    /* Press repeat key. */
 519+    EXPECT_REPORT(driver, (KC_P));
 520+    repeat_key.press();
 521+    run_one_scan_loop();
 522+    testing::Mock::VerifyAndClearExpectations(&driver);
 523+
 524+    /* Press regular key. */
 525+    EXPECT_NO_REPORT(driver);
 526+    regular_key.press();
 527+    run_one_scan_loop();
 528+    testing::Mock::VerifyAndClearExpectations(&driver);
 529+
 530+    /* Release regular key. */
 531+    EXPECT_REPORT(driver, (KC_P, KC_A));
 532+    EXPECT_REPORT(driver, (KC_P));
 533+    regular_key.release();
 534+    run_one_scan_loop();
 535+    testing::Mock::VerifyAndClearExpectations(&driver);
 536+
 537diff --git a/tests/auto_shift/auto_shift_repeat/config.h b/tests/auto_shift/auto_shift_repeat/config.h
 538new file mode 100644
 539index 0000000000000000000000000000000000000000..fb4c506b20f0c5f90c829fe46ea28701b3e840e6
 540--- /dev/null
 541+++ b/tests/auto_shift/auto_shift_repeat/config.h
 542@@ -0,0 +1,21 @@
 543+/* Copyright 2022 Isaac Elenbaas
 544+ *
 545+ * This program is free software: you can redistribute it and/or modify
 546+ * it under the terms of the GNU General Public License as published by
 547+ * the Free Software Foundation, either version 2 of the License, or
 548+ * (at your option) any later version.
 549+ *
 550+ * This program is distributed in the hope that it will be useful,
 551+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 552+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 553+ * GNU General Public License for more details.
 554+ *
 555+ * You should have received a copy of the GNU General Public License
 556+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 557+ */
 558+
 559+#pragma once
 560+
 561+#include "test_common.h"
 562+
 563+#define AUTO_SHIFT_REPEAT
 564diff --git a/tests/auto_shift/auto_shift_repeat/test.mk b/tests/auto_shift/auto_shift_repeat/test.mk
 565new file mode 100644
 566index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
 567--- /dev/null
 568+++ b/tests/auto_shift/auto_shift_repeat/test.mk
 569@@ -0,0 +1,20 @@
 570+# Copyright 2022 Isaac Elenbaas
 571+#
 572+# This program is free software: you can redistribute it and/or modify
 573+# it under the terms of the GNU General Public License as published by
 574+# the Free Software Foundation, either version 2 of the License, or
 575+# (at your option) any later version.
 576+#
 577+# This program is distributed in the hope that it will be useful,
 578+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 579+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 580+# GNU General Public License for more details.
 581+#
 582+# You should have received a copy of the GNU General Public License
 583+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 584+
 585+# --------------------------------------------------------------------------------
 586+# Keep this file, even if it is empty, as a marker that this folder contains tests
 587+# --------------------------------------------------------------------------------
 588+
 589+AUTO_SHIFT_ENABLE = yes
 590diff --git a/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp b/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
 591new file mode 100644
 592index 0000000000000000000000000000000000000000..4a7569ea9073fd85ac067d78024ba2cd93cd9cad
 593--- /dev/null
 594+++ b/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
 595@@ -0,0 +1,107 @@
 596+/* Copyright 2022 Isaac Elenbaas
 597+ *
 598+ * This program is free software: you can redistribute it and/or modify
 599+ * it under the terms of the GNU General Public License as published by
 600+ * the Free Software Foundation, either version 2 of the License, or
 601+ * (at your option) any later version.
 602+ *
 603+ * This program is distributed in the hope that it will be useful,
 604+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 605+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 606+ * GNU General Public License for more details.
 607+ *
 608+ * You should have received a copy of the GNU General Public License
 609+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 610+ */
 611+
 612+#include "keyboard_report_util.hpp"
 613+#include "keycode.h"
 614+#include "test_common.hpp"
 615+#include "action_tapping.h"
 616+#include "test_fixture.hpp"
 617+#include "test_keymap_key.hpp"
 618+
 619+using testing::_;
 620+using testing::AnyNumber;
 621+using testing::InSequence;
 622+
 623+class AutoShiftRepeat : public TestFixture {};
 624+
 625+TEST_F(AutoShiftRepeat, tap_regular_key_cancelling_another_key_hold) {
 626+    TestDriver driver;
 627+    InSequence s;
 628+    auto       repeat_key  = KeymapKey(0, 1, 0, KC_P);
 629+    auto       regular_key = KeymapKey(0, 2, 0, KC_A);
 630+
 631+    set_keymap({repeat_key, regular_key});
 632+
 633+    /* Press repeat key. */
 634+    EXPECT_NO_REPORT(driver);
 635+    repeat_key.press();
 636+    run_one_scan_loop();
 637+    testing::Mock::VerifyAndClearExpectations(&driver);
 638+
 639+    /* Press regular key. */
 640+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
 641+    EXPECT_REPORT(driver, (KC_P));
 642+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
 643+    regular_key.press();
 644+    run_one_scan_loop();
 645+    testing::Mock::VerifyAndClearExpectations(&driver);
 646+
 647+    /* Release regular key. */
 648+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
 649+    EXPECT_REPORT(driver, (KC_A));
 650+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(testing::AnyNumber());
 651+    regular_key.release();
 652+    run_one_scan_loop();
 653+    testing::Mock::VerifyAndClearExpectations(&driver);
 654+
 655+    /* Release repeat key. */
 656+    EXPECT_NO_REPORT(driver);
 657+    repeat_key.release();
 658+    run_one_scan_loop();
 659+    testing::Mock::VerifyAndClearExpectations(&driver);
 660+}
 661+
 662+TEST_F(AutoShiftRepeat, tap_regular_key_while_another_key_is_held) {
 663+    TestDriver driver;
 664+    InSequence s;
 665+    auto       repeat_key  = KeymapKey(0, 1, 0, KC_P);
 666+    auto       regular_key = KeymapKey(0, 2, 0, KC_A);
 667+
 668+    set_keymap({repeat_key, regular_key});
 669+
 670+    /* Press repeat key. */
 671+    EXPECT_NO_REPORT(driver);
 672+    repeat_key.press();
 673+    run_one_scan_loop();
 674+    testing::Mock::VerifyAndClearExpectations(&driver);
 675+
 676+    /* Idle for auto-repeat to kick in. */
 677+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 678+    EXPECT_REPORT(driver, (KC_LSFT, KC_P));
 679+    idle_for(AUTO_SHIFT_TIMEOUT);
 680+    run_one_scan_loop();
 681+    testing::Mock::VerifyAndClearExpectations(&driver);
 682+
 683+    /* Press regular key. */
 684+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 685+    EXPECT_NO_REPORT(driver);
 686+    regular_key.press();
 687+    run_one_scan_loop();
 688+    testing::Mock::VerifyAndClearExpectations(&driver);
 689+
 690+    /* Release regular key. */
 691+    EXPECT_REPORT(driver, (KC_P, KC_A));
 692+    EXPECT_REPORT(driver, (KC_P));
 693+    regular_key.release();
 694+    run_one_scan_loop();
 695diff --git a/tests/auto_shift/config.h b/tests/auto_shift/config.h
 696index 4f343b45299531730d47ae5e07d11cc8fde5702d..6d872dd57b5e09d515f0297a01ed1ec49c8ea496 100644
 697--- a/tests/auto_shift/config.h
 698+++ b/tests/auto_shift/config.h
 699@@ -16,4 +16,4 @@
 700 
 701 #pragma once
 702 
 703-#include "test_common.h"
 704+#include "test_common.h"
 705diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/config.h b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/config.h
 706new file mode 100644
 707index 0000000000000000000000000000000000000000..0de9845d9d40ebf2661de8aa96a6f01667694c02
 708--- /dev/null
 709+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/config.h
 710@@ -0,0 +1,24 @@
 711+/* Copyright 2022 Isaac Elenbaas
 712+ *
 713+ * This program is free software: you can redistribute it and/or modify
 714+ * it under the terms of the GNU General Public License as published by
 715+ * the Free Software Foundation, either version 2 of the License, or
 716+ * (at your option) any later version.
 717+ *
 718+ * This program is distributed in the hope that it will be useful,
 719+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 720+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 721+ * GNU General Public License for more details.
 722+ *
 723+ * You should have received a copy of the GNU General Public License
 724+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 725+ */
 726+
 727+#pragma once
 728+
 729+#include "test_common.h"
 730+
 731+#define RETRO_SHIFT 2 * TAPPING_TERM
 732+// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
 733+#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
 734+#define AUTO_SHIFT_MODIFIERS
 735diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/config.h b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/config.h
 736new file mode 100644
 737index 0000000000000000000000000000000000000000..dc9dc28cab8bcb47640a2239f67f4d06f4f6cbfe
 738--- /dev/null
 739+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/config.h
 740@@ -0,0 +1,21 @@
 741+/* Copyright 2021 Stefan Kerkmann
 742+ *
 743+ * This program is free software: you can redistribute it and/or modify
 744+ * it under the terms of the GNU General Public License as published by
 745+ * the Free Software Foundation, either version 2 of the License, or
 746+ * (at your option) any later version.
 747+ *
 748+ * This program is distributed in the hope that it will be useful,
 749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 751+ * GNU General Public License for more details.
 752+ *
 753+ * You should have received a copy of the GNU General Public License
 754+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 755+ */
 756+
 757+#pragma once
 758+
 759+#include "test_common.h"
 760+
 761+#define RETRO_SHIFT
 762diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test.mk b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test.mk
 763new file mode 100644
 764index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
 765--- /dev/null
 766+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test.mk
 767@@ -0,0 +1,20 @@
 768+# Copyright 2022 Isaac Elenbaas
 769+#
 770+# This program is free software: you can redistribute it and/or modify
 771+# it under the terms of the GNU General Public License as published by
 772+# the Free Software Foundation, either version 2 of the License, or
 773+# (at your option) any later version.
 774+#
 775+# This program is distributed in the hope that it will be useful,
 776+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 777+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 778+# GNU General Public License for more details.
 779+#
 780+# You should have received a copy of the GNU General Public License
 781+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 782+
 783+# --------------------------------------------------------------------------------
 784+# Keep this file, even if it is empty, as a marker that this folder contains tests
 785+# --------------------------------------------------------------------------------
 786+
 787+AUTO_SHIFT_ENABLE = yes
 788diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test_retro_shift.cpp b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test_retro_shift.cpp
 789new file mode 100644
 790index 0000000000000000000000000000000000000000..6d7d06427cb2aac435e2cf280a8a852cf1d26524
 791--- /dev/null
 792+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test_retro_shift.cpp
 793@@ -0,0 +1,57 @@
 794+/* Copyright 2022 Isaac Elenbaas
 795+ *
 796+ * This program is free software: you can redistribute it and/or modify
 797+ * it under the terms of the GNU General Public License as published by
 798+ * the Free Software Foundation, either version 2 of the License, or
 799+ * (at your option) any later version.
 800+ *
 801+ * This program is distributed in the hope that it will be useful,
 802+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 803+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 804+ * GNU General Public License for more details.
 805+ *
 806+ * You should have received a copy of the GNU General Public License
 807+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 808+ */
 809+
 810+#include "keyboard_report_util.hpp"
 811+#include "keycode.h"
 812+#include "test_common.hpp"
 813+#include "action_tapping.h"
 814+#include "test_fixture.hpp"
 815+#include "test_keymap_key.hpp"
 816+
 817+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
 818+    return true;
 819+}
 820+
 821+using testing::_;
 822+using testing::AnyNumber;
 823+using testing::AnyOf;
 824+using testing::InSequence;
 825+
 826+class RetroShiftDefaultTapHold : public TestFixture {};
 827+
 828+TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_for_long) {
 829+    TestDriver driver;
 830+    InSequence s;
 831+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
 832+
 833+    set_keymap({mod_tap_hold_key});
 834+
 835+    /* Press mod-tap-hold key. */
 836+    EXPECT_NO_REPORT(driver);
 837+    mod_tap_hold_key.press();
 838+    run_one_scan_loop();
 839+    idle_for(4 * TAPPING_TERM);
 840+    testing::Mock::VerifyAndClearExpectations(&driver);
 841+
 842+    /* Release mod-tap-hold key. */
 843+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 844+    EXPECT_REPORT(driver, (KC_LSFT, KC_A));
 845+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 846+    EXPECT_EMPTY_REPORT(driver);
 847+    mod_tap_hold_key.release();
 848+    run_one_scan_loop();
 849+    testing::Mock::VerifyAndClearExpectations(&driver);
 850+}
 851diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test.mk b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test.mk
 852new file mode 100644
 853index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
 854--- /dev/null
 855+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test.mk
 856@@ -0,0 +1,20 @@
 857+# Copyright 2022 Isaac Elenbaas
 858+#
 859+# This program is free software: you can redistribute it and/or modify
 860+# it under the terms of the GNU General Public License as published by
 861+# the Free Software Foundation, either version 2 of the License, or
 862+# (at your option) any later version.
 863+#
 864+# This program is distributed in the hope that it will be useful,
 865+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 866+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 867+# GNU General Public License for more details.
 868+#
 869+# You should have received a copy of the GNU General Public License
 870+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 871+
 872+# --------------------------------------------------------------------------------
 873+# Keep this file, even if it is empty, as a marker that this folder contains tests
 874+# --------------------------------------------------------------------------------
 875+
 876+AUTO_SHIFT_ENABLE = yes
 877diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test_retro_shift.cpp b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test_retro_shift.cpp
 878new file mode 100644
 879index 0000000000000000000000000000000000000000..f85a511632e7fa666dd41d5938b8d93f2d70a276
 880--- /dev/null
 881+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test_retro_shift.cpp
 882@@ -0,0 +1,485 @@
 883+/* Copyright 2022 Isaac Elenbaas
 884+ *
 885+ * This program is free software: you can redistribute it and/or modify
 886+ * it under the terms of the GNU General Public License as published by
 887+ * the Free Software Foundation, either version 2 of the License, or
 888+ * (at your option) any later version.
 889+ *
 890+ * This program is distributed in the hope that it will be useful,
 891+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 892+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 893+ * GNU General Public License for more details.
 894+ *
 895+ * You should have received a copy of the GNU General Public License
 896+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 897+ */
 898+
 899+#include "keyboard_report_util.hpp"
 900+#include "keycode.h"
 901+#include "test_common.hpp"
 902+#include "action_tapping.h"
 903+#include "test_fixture.hpp"
 904+#include "test_keymap_key.hpp"
 905+
 906+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
 907+    return true;
 908+}
 909+
 910+using testing::_;
 911+using testing::AnyNumber;
 912+using testing::AnyOf;
 913+using testing::InSequence;
 914+
 915+class RetroShiftDefaultTapHold : public TestFixture {};
 916+
 917+TEST_F(RetroShiftDefaultTapHold, tap_mod_tap_key) {
 918+    TestDriver driver;
 919+    InSequence s;
 920+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
 921+
 922+    set_keymap({mod_tap_hold_key});
 923+
 924+    /* Press mod-tap-hold key. */
 925+    EXPECT_NO_REPORT(driver);
 926+    mod_tap_hold_key.press();
 927+    run_one_scan_loop();
 928+    testing::Mock::VerifyAndClearExpectations(&driver);
 929+
 930+    /* Release mod-tap-hold key. */
 931+    EXPECT_REPORT(driver, (KC_A));
 932+    EXPECT_EMPTY_REPORT(driver);
 933+    mod_tap_hold_key.release();
 934+    run_one_scan_loop();
 935+    testing::Mock::VerifyAndClearExpectations(&driver);
 936+}
 937+
 938+TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_under_retro_shift) {
 939+    TestDriver driver;
 940+    InSequence s;
 941+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
 942+
 943+    set_keymap({mod_tap_hold_key});
 944+
 945+    /* Press mod-tap-hold key. */
 946+    EXPECT_NO_REPORT(driver);
 947+    mod_tap_hold_key.press();
 948+    run_one_scan_loop();
 949+    idle_for(AUTO_SHIFT_TIMEOUT);
 950+    testing::Mock::VerifyAndClearExpectations(&driver);
 951+
 952+    /* Release mod-tap-hold key. */
 953+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 954+    EXPECT_REPORT(driver, (KC_LSFT, KC_A));
 955+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT))).Times(AnyNumber());
 956+    EXPECT_EMPTY_REPORT(driver);
 957+    mod_tap_hold_key.release();
 958+    run_one_scan_loop();
 959+    testing::Mock::VerifyAndClearExpectations(&driver);
 960+}
 961+
 962+TEST_F(RetroShiftDefaultTapHold, hold_mod_tap_key_over_retro_shift) {
 963+    TestDriver driver;
 964+    InSequence s;
 965+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_A));
 966+
 967+    set_keymap({mod_tap_hold_key});
 968+
 969+    /* Press mod-tap-hold key. */
 970+    EXPECT_REPORT(driver, (KC_LCTL));
 971+    mod_tap_hold_key.press();
 972+    run_one_scan_loop();
 973+    idle_for(RETRO_SHIFT);
 974+    testing::Mock::VerifyAndClearExpectations(&driver);
 975+
 976+    /* Release mod-tap-hold key. */
 977+    EXPECT_EMPTY_REPORT(driver);
 978+    mod_tap_hold_key.release();
 979+    run_one_scan_loop();
 980+    testing::Mock::VerifyAndClearExpectations(&driver);
 981+}
 982diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/config.h b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/config.h
 983new file mode 100644
 984index 0000000000000000000000000000000000000000..396683963d36e588dece10337bf99308d5d869ad
 985--- /dev/null
 986+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/config.h
 987@@ -0,0 +1,26 @@
 988+/* Copyright 2022 Isaac Elenbaas
 989+ *
 990+ * This program is free software: you can redistribute it and/or modify
 991+ * it under the terms of the GNU General Public License as published by
 992+ * the Free Software Foundation, either version 2 of the License, or
 993+ * (at your option) any later version.
 994+ *
 995+ * This program is distributed in the hope that it will be useful,
 996+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 997+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 998+ * GNU General Public License for more details.
 999+ *
1000+ * You should have received a copy of the GNU General Public License
1001+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1002+ */
1003+
1004+#pragma once
1005+
1006+#include "test_common.h"
1007+
1008+#define HOLD_ON_OTHER_KEY_PRESS
1009+
1010+#define RETRO_SHIFT 2 * TAPPING_TERM
1011+// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
1012+#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
1013+#define AUTO_SHIFT_MODIFIERS
1014diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test.mk b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test.mk
1015new file mode 100644
1016index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
1017--- /dev/null
1018+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test.mk
1019@@ -0,0 +1,20 @@
1020+# Copyright 2022 Isaac Elenbaas
1021+#
1022+# This program is free software: you can redistribute it and/or modify
1023+# it under the terms of the GNU General Public License as published by
1024+# the Free Software Foundation, either version 2 of the License, or
1025+# (at your option) any later version.
1026+#
1027+# This program is distributed in the hope that it will be useful,
1028+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1029+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1030+# GNU General Public License for more details.
1031+#
1032+# You should have received a copy of the GNU General Public License
1033+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1034+
1035+# --------------------------------------------------------------------------------
1036+# Keep this file, even if it is empty, as a marker that this folder contains tests
1037+# --------------------------------------------------------------------------------
1038+
1039+AUTO_SHIFT_ENABLE = yes
1040diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test_retro_shift.cpp b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test_retro_shift.cpp
1041new file mode 100644
1042index 0000000000000000000000000000000000000000..52fc082ea3d66c1a0f77b36b6595029ea411c3f9
1043--- /dev/null
1044+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test_retro_shift.cpp
1045@@ -0,0 +1,442 @@
1046+/* Copyright 2022 Isaac Elenbaas
1047+ *
1048+ * This program is free software: you can redistribute it and/or modify
1049+ * it under the terms of the GNU General Public License as published by
1050+ * the Free Software Foundation, either version 2 of the License, or
1051+ * (at your option) any later version.
1052+ *
1053+ * This program is distributed in the hope that it will be useful,
1054+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1055+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1056+ * GNU General Public License for more details.
1057+ *
1058+ * You should have received a copy of the GNU General Public License
1059+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1060+ */
1061+
1062+#include "keyboard_report_util.hpp"
1063+#include "keycode.h"
1064+#include "test_common.hpp"
1065+#include "action_tapping.h"
1066+#include "test_fixture.hpp"
1067+#include "test_keymap_key.hpp"
1068+
1069+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
1070+    return true;
1071+}
1072+
1073+using testing::_;
1074+using testing::AnyNumber;
1075+using testing::AnyOf;
1076+using testing::InSequence;
1077+
1078+class RetroShiftHoldOnOtherKeyPress : public TestFixture {};
1079+
1080+TEST_F(RetroShiftHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
1081+    TestDriver driver;
1082+    InSequence s;
1083+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
1084+    auto       regular_key      = KeymapKey(0, 1, 0, KC_A);
1085+
1086+    set_keymap({mod_tap_hold_key, regular_key});
1087+
1088+    /* Press mod-tap-hold key. */
1089+    EXPECT_NO_REPORT(driver);
1090+    mod_tap_hold_key.press();
1091+    run_one_scan_loop();
1092+    testing::Mock::VerifyAndClearExpectations(&driver);
1093+
1094+    /* Press regular key. */
1095+    EXPECT_NO_REPORT(driver);
1096+    regular_key.press();
1097+    run_one_scan_loop();
1098+    testing::Mock::VerifyAndClearExpectations(&driver);
1099+
1100+    /* Release regular key. */
1101+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1102+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1103+    EXPECT_REPORT(driver, (KC_LCTL));
1104+    regular_key.release();
1105+    run_one_scan_loop();
1106+    testing::Mock::VerifyAndClearExpectations(&driver);
1107+
1108+    /* Release mod-tap-hold key. */
1109+    EXPECT_EMPTY_REPORT(driver);
1110+    mod_tap_hold_key.release();
1111+    run_one_scan_loop();
1112+    testing::Mock::VerifyAndClearExpectations(&driver);
1113+}
1114+
1115+TEST_F(RetroShiftHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
1116+    TestDriver driver;
1117+    InSequence s;
1118+    auto       mod_tap_hold_key    = KeymapKey(0, 0, 0, CTL_T(KC_P));
1119+    auto       mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
1120+
1121+    set_keymap({mod_tap_hold_key, mod_tap_regular_key});
1122+
1123+    /* Press mod-tap-hold key. */
1124+    EXPECT_NO_REPORT(driver);
1125+    mod_tap_hold_key.press();
1126+    run_one_scan_loop();
1127+    testing::Mock::VerifyAndClearExpectations(&driver);
1128+
1129+    /* Press mod-tap-regular key. */
1130+    EXPECT_NO_REPORT(driver);
1131+    mod_tap_regular_key.press();
1132+    run_one_scan_loop();
1133+    testing::Mock::VerifyAndClearExpectations(&driver);
1134+
1135+    /* Release mod-tap-regular key. */
1136+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1137+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1138+    EXPECT_REPORT(driver, (KC_LCTL));
1139+    mod_tap_regular_key.release();
1140+    run_one_scan_loop();
1141+    testing::Mock::VerifyAndClearExpectations(&driver);
1142+
1143+    /* Release mod-tap-hold key. */
1144+    EXPECT_EMPTY_REPORT(driver);
1145diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/config.h b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/config.h
1146new file mode 100644
1147index 0000000000000000000000000000000000000000..5194027c9f97368ffa4c58795e6aa7f440e0d4fd
1148--- /dev/null
1149+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/config.h
1150@@ -0,0 +1,26 @@
1151+/* Copyright 2022 Isaac Elenbaas
1152+ *
1153+ * This program is free software: you can redistribute it and/or modify
1154+ * it under the terms of the GNU General Public License as published by
1155+ * the Free Software Foundation, either version 2 of the License, or
1156+ * (at your option) any later version.
1157+ *
1158+ * This program is distributed in the hope that it will be useful,
1159+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1160+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1161+ * GNU General Public License for more details.
1162+ *
1163+ * You should have received a copy of the GNU General Public License
1164+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1165+ */
1166+
1167+#pragma once
1168+
1169+#include "test_common.h"
1170+
1171+#define PERMISSIVE_HOLD
1172+
1173+#define RETRO_SHIFT 2 * TAPPING_TERM
1174+// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
1175+#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
1176+#define AUTO_SHIFT_MODIFIERS
1177diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test.mk b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test.mk
1178new file mode 100644
1179index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
1180--- /dev/null
1181+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test.mk
1182@@ -0,0 +1,20 @@
1183+# Copyright 2022 Isaac Elenbaas
1184+#
1185+# This program is free software: you can redistribute it and/or modify
1186+# it under the terms of the GNU General Public License as published by
1187+# the Free Software Foundation, either version 2 of the License, or
1188+# (at your option) any later version.
1189+#
1190+# This program is distributed in the hope that it will be useful,
1191+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1192+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1193+# GNU General Public License for more details.
1194+#
1195+# You should have received a copy of the GNU General Public License
1196+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1197+
1198+# --------------------------------------------------------------------------------
1199+# Keep this file, even if it is empty, as a marker that this folder contains tests
1200+# --------------------------------------------------------------------------------
1201+
1202+AUTO_SHIFT_ENABLE = yes
1203diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test_retro_shift.cpp b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test_retro_shift.cpp
1204new file mode 100644
1205index 0000000000000000000000000000000000000000..a6c2cab16788614205fc55e5412e0083ec12cf62
1206--- /dev/null
1207+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test_retro_shift.cpp
1208@@ -0,0 +1,419 @@
1209+/* Copyright 2022 Isaac Elenbaas
1210+ *
1211+ * This program is free software: you can redistribute it and/or modify
1212+ * it under the terms of the GNU General Public License as published by
1213+ * the Free Software Foundation, either version 2 of the License, or
1214+ * (at your option) any later version.
1215+ *
1216+ * This program is distributed in the hope that it will be useful,
1217+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1218+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1219+ * GNU General Public License for more details.
1220+ *
1221+ * You should have received a copy of the GNU General Public License
1222+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1223+ */
1224+
1225+#include "keyboard_report_util.hpp"
1226+#include "keycode.h"
1227+#include "test_common.hpp"
1228+#include "action_tapping.h"
1229+#include "test_fixture.hpp"
1230+#include "test_keymap_key.hpp"
1231+
1232+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
1233+    return true;
1234+}
1235+
1236+using testing::_;
1237+using testing::AnyNumber;
1238+using testing::AnyOf;
1239+using testing::InSequence;
1240+
1241+class RetroShiftPermissiveHold : public TestFixture {};
1242+
1243+TEST_F(RetroShiftPermissiveHold, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
1244+    TestDriver driver;
1245+    InSequence s;
1246+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
1247+    auto       regular_key      = KeymapKey(0, 1, 0, KC_A);
1248+
1249+    set_keymap({mod_tap_hold_key, regular_key});
1250+
1251+    /* Press mod-tap-hold key. */
1252+    EXPECT_NO_REPORT(driver);
1253+    mod_tap_hold_key.press();
1254+    run_one_scan_loop();
1255+    testing::Mock::VerifyAndClearExpectations(&driver);
1256+
1257+    /* Press regular key. */
1258+    EXPECT_NO_REPORT(driver);
1259+    regular_key.press();
1260+    run_one_scan_loop();
1261+    testing::Mock::VerifyAndClearExpectations(&driver);
1262+
1263+    /* Release regular key. */
1264+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1265+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1266+    EXPECT_REPORT(driver, (KC_LCTL));
1267+    regular_key.release();
1268+    run_one_scan_loop();
1269+    testing::Mock::VerifyAndClearExpectations(&driver);
1270+
1271+    /* Release mod-tap-hold key. */
1272+    EXPECT_EMPTY_REPORT(driver);
1273+    mod_tap_hold_key.release();
1274+    run_one_scan_loop();
1275+    testing::Mock::VerifyAndClearExpectations(&driver);
1276+}
1277+
1278+TEST_F(RetroShiftPermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
1279+    TestDriver driver;
1280+    InSequence s;
1281+    auto       mod_tap_hold_key    = KeymapKey(0, 0, 0, CTL_T(KC_P));
1282+    auto       mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
1283+
1284+    set_keymap({mod_tap_hold_key, mod_tap_regular_key});
1285+
1286+    /* Press mod-tap-hold key. */
1287+    EXPECT_NO_REPORT(driver);
1288+    mod_tap_hold_key.press();
1289+    run_one_scan_loop();
1290+    testing::Mock::VerifyAndClearExpectations(&driver);
1291+
1292+    /* Press mod-tap-regular key. */
1293+    EXPECT_NO_REPORT(driver);
1294+    mod_tap_regular_key.press();
1295+    run_one_scan_loop();
1296+    testing::Mock::VerifyAndClearExpectations(&driver);
1297+
1298+    /* Release mod-tap-regular key. */
1299+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1300+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1301+    EXPECT_REPORT(driver, (KC_LCTL));
1302+    mod_tap_regular_key.release();
1303+    run_one_scan_loop();
1304+    testing::Mock::VerifyAndClearExpectations(&driver);
1305+
1306+    /* Release mod-tap-hold key. */
1307+    EXPECT_EMPTY_REPORT(driver);
1308diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/config.h b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/config.h
1309new file mode 100644
1310index 0000000000000000000000000000000000000000..a9535d8db0f6a377dd5e8d6a0430b7cb14cd5bf6
1311--- /dev/null
1312+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/config.h
1313@@ -0,0 +1,27 @@
1314+/* Copyright 2022 Isaac Elenbaas
1315+ *
1316+ * This program is free software: you can redistribute it and/or modify
1317+ * it under the terms of the GNU General Public License as published by
1318+ * the Free Software Foundation, either version 2 of the License, or
1319+ * (at your option) any later version.
1320+ *
1321+ * This program is distributed in the hope that it will be useful,
1322+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1323+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1324+ * GNU General Public License for more details.
1325+ *
1326+ * You should have received a copy of the GNU General Public License
1327+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1328+ */
1329+
1330+#pragma once
1331+
1332+#include "test_common.h"
1333+
1334+#define HOLD_ON_OTHER_KEY_PRESS
1335+#define PERMISSIVE_HOLD
1336+
1337+#define RETRO_SHIFT 2 * TAPPING_TERM
1338+// releases between AUTO_SHIFT_TIMEOUT and TAPPING_TERM are not tested
1339+#define AUTO_SHIFT_TIMEOUT TAPPING_TERM
1340+#define AUTO_SHIFT_MODIFIERS
1341diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test.mk b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test.mk
1342new file mode 100644
1343index 0000000000000000000000000000000000000000..b68733200517bdfc97810aa02c20dfed2cbd0b1f
1344--- /dev/null
1345+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test.mk
1346@@ -0,0 +1,20 @@
1347+# Copyright 2022 Isaac Elenbaas
1348+#
1349+# This program is free software: you can redistribute it and/or modify
1350+# it under the terms of the GNU General Public License as published by
1351+# the Free Software Foundation, either version 2 of the License, or
1352+# (at your option) any later version.
1353+#
1354+# This program is distributed in the hope that it will be useful,
1355+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1356+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1357+# GNU General Public License for more details.
1358+#
1359+# You should have received a copy of the GNU General Public License
1360+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1361+
1362+# --------------------------------------------------------------------------------
1363+# Keep this file, even if it is empty, as a marker that this folder contains tests
1364+# --------------------------------------------------------------------------------
1365+
1366+AUTO_SHIFT_ENABLE = yes
1367diff --git a/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test_retro_shift.cpp b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test_retro_shift.cpp
1368new file mode 100644
1369index 0000000000000000000000000000000000000000..25c80b2cba33da2c7a4bb96adce5e80ad7415ca9
1370--- /dev/null
1371+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test_retro_shift.cpp
1372@@ -0,0 +1,442 @@
1373+/* Copyright 2022 Isaac Elenbaas
1374+ *
1375+ * This program is free software: you can redistribute it and/or modify
1376+ * it under the terms of the GNU General Public License as published by
1377+ * the Free Software Foundation, either version 2 of the License, or
1378+ * (at your option) any later version.
1379+ *
1380+ * This program is distributed in the hope that it will be useful,
1381+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1382+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1383+ * GNU General Public License for more details.
1384+ *
1385+ * You should have received a copy of the GNU General Public License
1386+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1387+ */
1388+
1389+#include "keyboard_report_util.hpp"
1390+#include "keycode.h"
1391+#include "test_common.hpp"
1392+#include "action_tapping.h"
1393+#include "test_fixture.hpp"
1394+#include "test_keymap_key.hpp"
1395+
1396+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
1397+    return true;
1398+}
1399+
1400+using testing::_;
1401+using testing::AnyNumber;
1402+using testing::AnyOf;
1403+using testing::InSequence;
1404+
1405+class RetroShiftPermissiveHoldHoldOnOtherKeyPress : public TestFixture {};
1406+
1407+TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_regular_key_while_mod_tap_key_is_held_under_tapping_term) {
1408+    TestDriver driver;
1409+    InSequence s;
1410+    auto       mod_tap_hold_key = KeymapKey(0, 0, 0, CTL_T(KC_P));
1411+    auto       regular_key      = KeymapKey(0, 1, 0, KC_A);
1412+
1413+    set_keymap({mod_tap_hold_key, regular_key});
1414+
1415+    /* Press mod-tap-hold key. */
1416+    EXPECT_NO_REPORT(driver);
1417+    mod_tap_hold_key.press();
1418+    run_one_scan_loop();
1419+    testing::Mock::VerifyAndClearExpectations(&driver);
1420+
1421+    /* Press regular key. */
1422+    EXPECT_NO_REPORT(driver);
1423+    regular_key.press();
1424+    run_one_scan_loop();
1425+    testing::Mock::VerifyAndClearExpectations(&driver);
1426+
1427+    /* Release regular key. */
1428+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1429+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1430+    EXPECT_REPORT(driver, (KC_LCTL));
1431+    regular_key.release();
1432+    run_one_scan_loop();
1433+    testing::Mock::VerifyAndClearExpectations(&driver);
1434+
1435+    /* Release mod-tap-hold key. */
1436+    EXPECT_EMPTY_REPORT(driver);
1437+    mod_tap_hold_key.release();
1438+    run_one_scan_loop();
1439+    testing::Mock::VerifyAndClearExpectations(&driver);
1440+}
1441+
1442+TEST_F(RetroShiftPermissiveHoldHoldOnOtherKeyPress, tap_mod_tap_key_while_mod_tap_key_is_held_under_tapping_term) {
1443+    TestDriver driver;
1444+    InSequence s;
1445+    auto       mod_tap_hold_key    = KeymapKey(0, 0, 0, CTL_T(KC_P));
1446+    auto       mod_tap_regular_key = KeymapKey(0, 1, 0, ALT_T(KC_A));
1447+
1448+    set_keymap({mod_tap_hold_key, mod_tap_regular_key});
1449+
1450+    /* Press mod-tap-hold key. */
1451+    EXPECT_NO_REPORT(driver);
1452+    mod_tap_hold_key.press();
1453+    run_one_scan_loop();
1454+    testing::Mock::VerifyAndClearExpectations(&driver);
1455+
1456+    /* Press mod-tap-regular key. */
1457+    EXPECT_NO_REPORT(driver);
1458+    mod_tap_regular_key.press();
1459+    run_one_scan_loop();
1460+    testing::Mock::VerifyAndClearExpectations(&driver);
1461+
1462+    /* Release mod-tap-regular key. */
1463+    EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LCTL))).Times(AnyNumber());
1464+    EXPECT_REPORT(driver, (KC_LCTL, KC_A));
1465+    EXPECT_REPORT(driver, (KC_LCTL));
1466+    mod_tap_regular_key.release();
1467+    run_one_scan_loop();
1468+    testing::Mock::VerifyAndClearExpectations(&driver);
1469+
1470+    /* Release mod-tap-hold key. */
1471+    EXPECT_EMPTY_REPORT(driver);
1472diff --git a/tests/auto_shift/test.mk b/tests/auto_shift/test.mk
1473index 4259c606e472940f512b0d092e351d34cb7a02c9..a4c6b380edaf806d93f5f653afacb0b3a5f03c79 100644
1474--- a/tests/auto_shift/test.mk
1475+++ b/tests/auto_shift/test.mk
1476@@ -17,4 +17,4 @@
1477 # Keep this file, even if it is empty, as a marker that this folder contains tests
1478 # --------------------------------------------------------------------------------
1479 
1480-AUTO_SHIFT_ENABLE = yes
1481+AUTO_SHIFT_ENABLE = yes
1482diff --git a/tests/basic/config.h b/tests/basic/config.h
1483index 85fa9d691d08ab9d119d707f96247cbabea4c5e7..7fc76d7c2e7f66076f420439263ca38ee1a22a8c 100644
1484--- a/tests/basic/config.h
1485+++ b/tests/basic/config.h
1486@@ -16,4 +16,4 @@
1487 
1488 #pragma once
1489 
1490-#include "test_common.h"
1491+#include "test_common.h"
1492diff --git a/tests/basic/test.mk b/tests/basic/test.mk
1493index 29690d1adf7b4530aeed9679a8194b1271437623..6ec384609c79cf768894e9dac0cc241357f79b1a 100644
1494--- a/tests/basic/test.mk
1495+++ b/tests/basic/test.mk
1496@@ -15,4 +15,4 @@
1497 
1498 # --------------------------------------------------------------------------------
1499 # Keep this file, even if it is empty, as a marker that this folder contains tests
1500-# --------------------------------------------------------------------------------
1501+# --------------------------------------------------------------------------------
1502diff --git a/tests/caps_word/auto_shift/config.h b/tests/caps_word/auto_shift/config.h
1503new file mode 100644
1504index 0000000000000000000000000000000000000000..aff389100e2a0c64cd6e3038c9ad0f58dd95e5f2
1505--- /dev/null
1506+++ b/tests/caps_word/auto_shift/config.h
1507@@ -0,0 +1,21 @@
1508+// Copyright 2022 Google LLC
1509+//
1510+// This program is free software: you can redistribute it and/or modify
1511+// it under the terms of the GNU General Public License as published by
1512+// the Free Software Foundation, either version 2 of the License, or
1513+// (at your option) any later version.
1514+//
1515+// This program is distributed in the hope that it will be useful,
1516+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1517+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1518+// GNU General Public License for more details.
1519+//
1520+// You should have received a copy of the GNU General Public License
1521+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
1522+
1523+#pragma once
1524+
1525+#include "test_common.h"
1526+
1527+#define TAPPING_TERM 200
1528+#define AUTO_SHIFT_TIMEOUT 150
1529diff --git a/tests/caps_word/caps_word_autoshift/config.h b/tests/caps_word/auto_shift/retro_shift/config.h
1530rename from tests/caps_word/caps_word_autoshift/config.h
1531rename to tests/caps_word/auto_shift/retro_shift/config.h
1532diff --git a/tests/caps_word/caps_word_autoshift/test.mk b/tests/caps_word/auto_shift/retro_shift/test.mk
1533rename from tests/caps_word/caps_word_autoshift/test.mk
1534rename to tests/caps_word/auto_shift/retro_shift/test.mk
1535diff --git a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp b/tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
1536rename from tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp
1537rename to tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
1538index 01b1a78a5f44a73b8aa3a448997958fec58ecf52..03a7a61a738635a92e765abefb9a154e0956d2c2 100644
1539--- a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp
1540+++ b/tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
1541@@ -27,6 +27,10 @@
1542             KeyboardReport(KC_LSFT))))
1543 // clang-format on
1544 
1545+bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {
1546+    return true;
1547+}
1548+
1549 using ::testing::_;
1550 using ::testing::AnyNumber;
1551 using ::testing::AnyOf;
1552diff --git a/tests/caps_word/auto_shift/test.mk b/tests/caps_word/auto_shift/test.mk
1553new file mode 100644
1554index 0000000000000000000000000000000000000000..7f717d7fc1da450e680d805d8edcad32eb6ec3eb
1555--- /dev/null
1556+++ b/tests/caps_word/auto_shift/test.mk
1557@@ -0,0 +1,18 @@
1558+# Copyright 2022 Google LLC
1559+#
1560+# This program is free software: you can redistribute it and/or modify
1561+# it under the terms of the GNU General Public License as published by
1562+# the Free Software Foundation, either version 2 of the License, or
1563+# (at your option) any later version.
1564+#
1565+# This program is distributed in the hope that it will be useful,
1566+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1567+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1568+# GNU General Public License for more details.
1569+#
1570+# You should have received a copy of the GNU General Public License
1571+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1572+
1573+CAPS_WORD_ENABLE = yes
1574+AUTO_SHIFT_ENABLE = yes
1575+
1576diff --git a/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp b/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
1577new file mode 100644
1578index 0000000000000000000000000000000000000000..849b993525eb48d32fe00027382ec8f8766d5963
1579--- /dev/null
1580+++ b/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
1581@@ -0,0 +1,66 @@
1582+// Copyright 2022 Google LLC
1583+//
1584+// This program is free software: you can redistribute it and/or modify
1585+// it under the terms of the GNU General Public License as published by
1586+// the Free Software Foundation, either version 2 of the License, or
1587+// (at your option) any later version.
1588+//
1589+// This program is distributed in the hope that it will be useful,
1590+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1591+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1592+// GNU General Public License for more details.
1593+//
1594+// You should have received a copy of the GNU General Public License
1595+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
1596+
1597+#include "keyboard_report_util.hpp"
1598+#include "keycode.h"
1599+#include "test_common.hpp"
1600+#include "test_fixture.hpp"
1601+#include "test_keymap_key.hpp"
1602+
1603+using ::testing::_;
1604+using ::testing::AnyNumber;
1605+using ::testing::AnyOf;
1606+using ::testing::InSequence;
1607+
1608+class CapsWord : public TestFixture {
1609+   public:
1610+    void SetUp() override {
1611+        caps_word_off();
1612+    }
1613+};
1614+
1615+// Tests that with Auto Shift, letter keys are shifted by Caps Word
1616+// regardless of whether they are released before AUTO_SHIFT_TIMEOUT.
1617+TEST_F(CapsWord, AutoShiftKeys) {
1618+    TestDriver driver;
1619+    KeymapKey  key_a(0, 0, 0, KC_A);
1620+    KeymapKey  key_spc(0, 1, 0, KC_SPC);
1621+    set_keymap({key_a, key_spc});
1622+
1623+    // Allow any number of reports with no keys or only KC_LSFT.
1624+    // clang-format off
1625+    EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
1626+                KeyboardReport(),
1627+                KeyboardReport(KC_LSFT))))
1628+        .Times(AnyNumber());
1629+    // clang-format on
1630+    { // Expect: "A, A, space, a".
1631+        InSequence s;
1632+        EXPECT_REPORT(driver, (KC_LSFT, KC_A));
1633+        EXPECT_REPORT(driver, (KC_LSFT, KC_A));
1634+        EXPECT_REPORT(driver, (KC_SPC));
1635+        EXPECT_REPORT(driver, (KC_A));
1636+    }
1637+
1638+    // Turn on Caps Word and type "A (quick tap), A (long press), space, A".
1639+    caps_word_on();
1640+
1641+    tap_key(key_a);                         // Tap A quickly.
1642+    tap_key(key_a, AUTO_SHIFT_TIMEOUT + 1); // Long press A.
1643+    tap_key(key_spc);
1644+    tap_key(key_a);
1645+
1646+    testing::Mock::VerifyAndClearExpectations(&driver);
1647+}
1648diff --git a/tests/caps_word/caps_word_unicodemap/config.h b/tests/caps_word/unicodemap/config.h
1649rename from tests/caps_word/caps_word_unicodemap/config.h
1650rename to tests/caps_word/unicodemap/config.h
1651diff --git a/tests/caps_word/caps_word_unicodemap/test.mk b/tests/caps_word/unicodemap/test.mk
1652rename from tests/caps_word/caps_word_unicodemap/test.mk
1653rename to tests/caps_word/unicodemap/test.mk
1654diff --git a/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp b/tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp
1655rename from tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp
1656rename to tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp
1657diff --git a/tests/tap_hold_configurations/default_mod_tap/test.mk b/tests/tap_hold_configurations/default_mod_tap/test.mk
1658index cfab996e0ef819205d9c1662559032fab99b8c1c..efecca2c22f09099d78348c694cede8d28467229 100644
1659--- a/tests/tap_hold_configurations/default_mod_tap/test.mk
1660+++ b/tests/tap_hold_configurations/default_mod_tap/test.mk
1661@@ -15,4 +15,4 @@
1662 
1663 # --------------------------------------------------------------------------------
1664 # Keep this file, even if it is empty, as a marker that this folder contains tests
1665-# --------------------------------------------------------------------------------
1666+# --------------------------------------------------------------------------------
1667diff --git a/tests/tap_hold_configurations/permissive_hold/config.h b/tests/tap_hold_configurations/permissive_hold/config.h
1668index 2d5a9849e7d7c72a68542b3905b3c2a037f3d25f..0031c6e5bcf158c801d96ee02a0df63c15cd9b7e 100644
1669--- a/tests/tap_hold_configurations/permissive_hold/config.h
1670+++ b/tests/tap_hold_configurations/permissive_hold/config.h
1671@@ -18,4 +18,4 @@
1672 
1673 #include "test_common.h"
1674 
1675-#define PERMISSIVE_HOLD
1676+#define PERMISSIVE_HOLD
1677diff --git a/tests/test_common/build.mk b/tests/test_common/build.mk
1678index aeb30578549a2205ee695f7ec64349a206343564..d7423bc78a90dce39d7724ba709074e5a957672e 100644
1679--- a/tests/test_common/build.mk
1680+++ b/tests/test_common/build.mk
1681@@ -13,4 +13,4 @@
1682 # You should have received a copy of the GNU General Public License
1683 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
1684 
1685-CUSTOM_MATRIX=yes
1686+CUSTOM_MATRIX=yes
1687diff --git a/tests/test_common/main.cpp b/tests/test_common/main.cpp
1688index 0f4e320b07e2a38400c41655843f18e30c818eab..ac481b8fbabc5b75d0e56ad1a999bd5f16b440f2 100644
1689--- a/tests/test_common/main.cpp
1690+++ b/tests/test_common/main.cpp
1691@@ -29,4 +29,4 @@ int main(int argc, char **argv) {
1692     init_logging();
1693 
1694     return RUN_ALL_TESTS();
1695-}
1696+}
1697diff --git a/tests/test_common/test_common.h b/tests/test_common/test_common.h
1698index 19ffcddceaec2cc3caf34ec5f9f647818e7b7caa..8b93c032b6a06c03032fc8cb830f72938906b886 100644
1699--- a/tests/test_common/test_common.h
1700+++ b/tests/test_common/test_common.h
1701@@ -1,4 +1,4 @@
1702 #pragma once
1703 
1704 #define MATRIX_ROWS 4
1705-#define MATRIX_COLS 10
1706+#define MATRIX_COLS 10