From dd94877ec6d2ee5c4cdb0e71287abd76585b0268 Mon Sep 17 00:00:00 2001
From: Isaac Elenbaas
Date: Sun, 24 Sep 2023 22:45:49 -0400
Subject: Improve test invocation, fix Retro Shift bugs, and add Auto+Retro
Shift test cases (#15889)
---
.../auto_shift_no_auto_repeat/config.h | 22 +
.../auto_shift_no_auto_repeat/test.mk | 20 +
.../auto_shift_no_auto_repeat/test_auto_shift.cpp | 105 +++++
tests/auto_shift/auto_shift_repeat/config.h | 21 +
tests/auto_shift/auto_shift_repeat/test.mk | 20 +
.../auto_shift_repeat/test_auto_shift.cpp | 107 +++++
tests/auto_shift/config.h | 2 +-
.../default_mod_tap/config.h | 24 +
.../default_mod_tap/no_timeout/config.h | 21 +
.../default_mod_tap/no_timeout/test.mk | 20 +
.../no_timeout/test_retro_shift.cpp | 57 +++
.../default_mod_tap/test.mk | 20 +
.../default_mod_tap/test_retro_shift.cpp | 485 +++++++++++++++++++++
.../hold_on_other_key_press/config.h | 26 ++
.../hold_on_other_key_press/test.mk | 20 +
.../hold_on_other_key_press/test_retro_shift.cpp | 442 +++++++++++++++++++
.../permissive_hold/config.h | 26 ++
.../permissive_hold/test.mk | 20 +
.../permissive_hold/test_retro_shift.cpp | 419 ++++++++++++++++++
.../config.h | 27 ++
.../test.mk | 20 +
.../test_retro_shift.cpp | 442 +++++++++++++++++++
tests/auto_shift/test.mk | 2 +-
tests/basic/config.h | 2 +-
tests/basic/test.mk | 2 +-
tests/caps_word/auto_shift/config.h | 21 +
tests/caps_word/auto_shift/retro_shift/config.h | 22 +
tests/caps_word/auto_shift/retro_shift/test.mk | 18 +
.../retro_shift/test_caps_word_retroshift.cpp | 141 ++++++
tests/caps_word/auto_shift/test.mk | 18 +
.../auto_shift/test_caps_word_autoshift.cpp | 66 +++
tests/caps_word/caps_word_autoshift/config.h | 22 -
tests/caps_word/caps_word_autoshift/test.mk | 18 -
.../test_caps_word_autoshift.cpp | 137 ------
tests/caps_word/caps_word_unicodemap/config.h | 20 -
tests/caps_word/caps_word_unicodemap/test.mk | 18 -
.../test_caps_word_unicodemap.cpp | 121 -----
tests/caps_word/unicodemap/config.h | 20 +
tests/caps_word/unicodemap/test.mk | 18 +
.../unicodemap/test_caps_word_unicodemap.cpp | 121 +++++
.../default_mod_tap/test.mk | 2 +-
.../permissive_hold/config.h | 2 +-
tests/test_common/build.mk | 2 +-
tests/test_common/main.cpp | 2 +-
tests/test_common/test_common.h | 2 +-
45 files changed, 2818 insertions(+), 345 deletions(-)
create mode 100644 tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/config.h
create mode 100644 tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test.mk
create mode 100644 tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test_auto_shift.cpp
create mode 100644 tests/auto_shift/auto_shift_repeat/config.h
create mode 100644 tests/auto_shift/auto_shift_repeat/test.mk
create mode 100644 tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/config.h
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/config.h
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test.mk
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test_retro_shift.cpp
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test.mk
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test_retro_shift.cpp
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/config.h
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test.mk
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test_retro_shift.cpp
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/config.h
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test.mk
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test_retro_shift.cpp
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/config.h
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test.mk
create mode 100644 tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test_retro_shift.cpp
create mode 100644 tests/caps_word/auto_shift/config.h
create mode 100644 tests/caps_word/auto_shift/retro_shift/config.h
create mode 100644 tests/caps_word/auto_shift/retro_shift/test.mk
create mode 100644 tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
create mode 100644 tests/caps_word/auto_shift/test.mk
create mode 100644 tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
delete mode 100644 tests/caps_word/caps_word_autoshift/config.h
delete mode 100644 tests/caps_word/caps_word_autoshift/test.mk
delete mode 100644 tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp
delete mode 100644 tests/caps_word/caps_word_unicodemap/config.h
delete mode 100644 tests/caps_word/caps_word_unicodemap/test.mk
delete mode 100644 tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp
create mode 100644 tests/caps_word/unicodemap/config.h
create mode 100644 tests/caps_word/unicodemap/test.mk
create mode 100644 tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp
(limited to 'tests')
diff --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
new file mode 100644
index 0000000000..973e04582f
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/config.h
@@ -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 .
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define AUTO_SHIFT_REPEAT
+#define AUTO_SHIFT_NO_AUTO_REPEAT
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..cd219a5474
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/auto_shift_no_auto_repeat/test_auto_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --git a/tests/auto_shift/auto_shift_repeat/config.h b/tests/auto_shift/auto_shift_repeat/config.h
new file mode 100644
index 0000000000..fb4c506b20
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/config.h
@@ -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 .
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define AUTO_SHIFT_REPEAT
diff --git a/tests/auto_shift/auto_shift_repeat/test.mk b/tests/auto_shift/auto_shift_repeat/test.mk
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --git a/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp b/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
new file mode 100644
index 0000000000..4a7569ea90
--- /dev/null
+++ b/tests/auto_shift/auto_shift_repeat/test_auto_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --git a/tests/auto_shift/config.h b/tests/auto_shift/config.h
index 4f343b4529..6d872dd57b 100644
--- a/tests/auto_shift/config.h
+++ b/tests/auto_shift/config.h
@@ -16,4 +16,4 @@
#pragma once
-#include "test_common.h"
\ No newline at end of file
+#include "test_common.h"
diff --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
new file mode 100644
index 0000000000..0de9845d9d
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/config.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 .
+ */
+
+#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
diff --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
new file mode 100644
index 0000000000..dc9dc28cab
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/config.h
@@ -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 .
+ */
+
+#pragma once
+
+#include "test_common.h"
+
+#define RETRO_SHIFT
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..6d7d06427c
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/no_timeout/test_retro_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..f85a511632
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/default_mod_tap/test_retro_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --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
new file mode 100644
index 0000000000..396683963d
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/config.h
@@ -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 .
+ */
+
+#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
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..52fc082ea3
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/hold_on_other_key_press/test_retro_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --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
new file mode 100644
index 0000000000..5194027c9f
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/config.h
@@ -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 .
+ */
+
+#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
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..a6c2cab167
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold/test_retro_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --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
new file mode 100644
index 0000000000..a9535d8db0
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/config.h
@@ -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 .
+ */
+
+#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
diff --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
new file mode 100644
index 0000000000..b687332005
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test.mk
@@ -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 .
+
+# --------------------------------------------------------------------------------
+# Keep this file, even if it is empty, as a marker that this folder contains tests
+# --------------------------------------------------------------------------------
+
+AUTO_SHIFT_ENABLE = yes
diff --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
new file mode 100644
index 0000000000..25c80b2cba
--- /dev/null
+++ b/tests/auto_shift/retro_shift/tap_hold_configurations/permissive_hold_hold_on_other_key_press/test_retro_shift.cpp
@@ -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 .
+ */
+
+#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);
+}
diff --git a/tests/auto_shift/test.mk b/tests/auto_shift/test.mk
index 4259c606e4..a4c6b380ed 100644
--- a/tests/auto_shift/test.mk
+++ b/tests/auto_shift/test.mk
@@ -17,4 +17,4 @@
# Keep this file, even if it is empty, as a marker that this folder contains tests
# --------------------------------------------------------------------------------
-AUTO_SHIFT_ENABLE = yes
\ No newline at end of file
+AUTO_SHIFT_ENABLE = yes
diff --git a/tests/basic/config.h b/tests/basic/config.h
index 85fa9d691d..7fc76d7c2e 100644
--- a/tests/basic/config.h
+++ b/tests/basic/config.h
@@ -16,4 +16,4 @@
#pragma once
-#include "test_common.h"
\ No newline at end of file
+#include "test_common.h"
diff --git a/tests/basic/test.mk b/tests/basic/test.mk
index 29690d1adf..6ec384609c 100644
--- a/tests/basic/test.mk
+++ b/tests/basic/test.mk
@@ -15,4 +15,4 @@
# --------------------------------------------------------------------------------
# Keep this file, even if it is empty, as a marker that this folder contains tests
-# --------------------------------------------------------------------------------
\ No newline at end of file
+# --------------------------------------------------------------------------------
diff --git a/tests/caps_word/auto_shift/config.h b/tests/caps_word/auto_shift/config.h
new file mode 100644
index 0000000000..aff389100e
--- /dev/null
+++ b/tests/caps_word/auto_shift/config.h
@@ -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 .
+
+#pragma once
+
+#include "test_common.h"
+
+#define TAPPING_TERM 200
+#define AUTO_SHIFT_TIMEOUT 150
diff --git a/tests/caps_word/auto_shift/retro_shift/config.h b/tests/caps_word/auto_shift/retro_shift/config.h
new file mode 100644
index 0000000000..b80f53b9dd
--- /dev/null
+++ b/tests/caps_word/auto_shift/retro_shift/config.h
@@ -0,0 +1,22 @@
+// 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 .
+
+#pragma once
+
+#include "test_common.h"
+
+#define TAPPING_TERM 200
+#define AUTO_SHIFT_TIMEOUT 150
+#define RETRO_SHIFT 500
diff --git a/tests/caps_word/auto_shift/retro_shift/test.mk b/tests/caps_word/auto_shift/retro_shift/test.mk
new file mode 100644
index 0000000000..7f717d7fc1
--- /dev/null
+++ b/tests/caps_word/auto_shift/retro_shift/test.mk
@@ -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 .
+
+CAPS_WORD_ENABLE = yes
+AUTO_SHIFT_ENABLE = yes
+
diff --git a/tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp b/tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
new file mode 100644
index 0000000000..03a7a61a73
--- /dev/null
+++ b/tests/caps_word/auto_shift/retro_shift/test_caps_word_retroshift.cpp
@@ -0,0 +1,141 @@
+// 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 .
+
+#include "keyboard_report_util.hpp"
+#include "keycode.h"
+#include "test_common.hpp"
+#include "test_fixture.hpp"
+#include "test_keymap_key.hpp"
+
+// Allow reports with no keys or only KC_LSFT.
+// clang-format off
+#define EXPECT_EMPTY_OR_LSFT(driver) \
+ EXPECT_CALL(driver, send_keyboard_mock(AnyOf( \
+ KeyboardReport(), \
+ 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;
+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});
+
+ EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
+ { // 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);
+
+ VERIFY_AND_CLEAR(driver);
+}
+
+// Test Caps Word + Auto Shift where keys A and B are rolled.
+TEST_F(CapsWord, AutoShiftRolledShiftedKeys) {
+ TestDriver driver;
+ KeymapKey key_a(0, 0, 0, KC_A);
+ KeymapKey key_b(0, 0, 1, KC_B);
+ set_keymap({key_a, key_b});
+
+ EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
+ { // Expect: "A, B, A, B".
+ InSequence s;
+ EXPECT_REPORT(driver, (KC_LSFT, KC_A));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_A));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ }
+
+ caps_word_on();
+
+ key_a.press(); // Overlapping taps: A down, B down, A up, B up.
+ run_one_scan_loop();
+ key_b.press();
+ run_one_scan_loop();
+ key_a.release();
+ run_one_scan_loop();
+ key_b.release();
+ run_one_scan_loop();
+
+ key_a.press(); // Nested taps: A down, B down, B up, A up.
+ run_one_scan_loop();
+ key_b.press();
+ run_one_scan_loop();
+ key_b.release();
+ run_one_scan_loop();
+ key_a.release();
+ run_one_scan_loop();
+
+ caps_word_off();
+ VERIFY_AND_CLEAR(driver);
+}
+
+// Tests that with tap-hold keys with Retro Shift, letter keys are shifted by
+// Caps Word regardless of whether they are retroshifted.
+TEST_F(CapsWord, RetroShiftKeys) {
+ TestDriver driver;
+ KeymapKey key_modtap_a(0, 0, 0, LCTL_T(KC_A));
+ KeymapKey key_layertap_b(0, 1, 0, LT(1, KC_B));
+ set_keymap({key_modtap_a, key_layertap_b});
+
+ EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
+ { // Expect: "B, A, B, A".
+ InSequence s;
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_A));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_B));
+ EXPECT_REPORT(driver, (KC_LSFT, KC_A));
+ }
+
+ // Turn on Caps Word and type "B, A (long press), B (long press), A".
+ caps_word_on();
+
+ tap_key(key_layertap_b); // Tap B quickly.
+ tap_key(key_modtap_a, TAPPING_TERM + 1); // Long press A.
+ tap_key(key_layertap_b, TAPPING_TERM + 1); // Long press B.
+ tap_key(key_modtap_a); // Tap A quickly.
+
+ EXPECT_EQ(is_caps_word_on(), true);
+ VERIFY_AND_CLEAR(driver);
+}
diff --git a/tests/caps_word/auto_shift/test.mk b/tests/caps_word/auto_shift/test.mk
new file mode 100644
index 0000000000..7f717d7fc1
--- /dev/null
+++ b/tests/caps_word/auto_shift/test.mk
@@ -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 .
+
+CAPS_WORD_ENABLE = yes
+AUTO_SHIFT_ENABLE = yes
+
diff --git a/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp b/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
new file mode 100644
index 0000000000..849b993525
--- /dev/null
+++ b/tests/caps_word/auto_shift/test_caps_word_autoshift.cpp
@@ -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 .
+
+#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);
+}
diff --git a/tests/caps_word/caps_word_autoshift/config.h b/tests/caps_word/caps_word_autoshift/config.h
deleted file mode 100644
index b80f53b9dd..0000000000
--- a/tests/caps_word/caps_word_autoshift/config.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 .
-
-#pragma once
-
-#include "test_common.h"
-
-#define TAPPING_TERM 200
-#define AUTO_SHIFT_TIMEOUT 150
-#define RETRO_SHIFT 500
diff --git a/tests/caps_word/caps_word_autoshift/test.mk b/tests/caps_word/caps_word_autoshift/test.mk
deleted file mode 100644
index 7f717d7fc1..0000000000
--- a/tests/caps_word/caps_word_autoshift/test.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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 .
-
-CAPS_WORD_ENABLE = yes
-AUTO_SHIFT_ENABLE = yes
-
diff --git a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp b/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp
deleted file mode 100644
index 01b1a78a5f..0000000000
--- a/tests/caps_word/caps_word_autoshift/test_caps_word_autoshift.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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 .
-
-#include "keyboard_report_util.hpp"
-#include "keycode.h"
-#include "test_common.hpp"
-#include "test_fixture.hpp"
-#include "test_keymap_key.hpp"
-
-// Allow reports with no keys or only KC_LSFT.
-// clang-format off
-#define EXPECT_EMPTY_OR_LSFT(driver) \
- EXPECT_CALL(driver, send_keyboard_mock(AnyOf( \
- KeyboardReport(), \
- KeyboardReport(KC_LSFT))))
-// clang-format on
-
-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});
-
- EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
- { // 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);
-
- VERIFY_AND_CLEAR(driver);
-}
-
-// Test Caps Word + Auto Shift where keys A and B are rolled.
-TEST_F(CapsWord, AutoShiftRolledShiftedKeys) {
- TestDriver driver;
- KeymapKey key_a(0, 0, 0, KC_A);
- KeymapKey key_b(0, 0, 1, KC_B);
- set_keymap({key_a, key_b});
-
- EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
- { // Expect: "A, B, A, B".
- InSequence s;
- EXPECT_REPORT(driver, (KC_LSFT, KC_A));
- EXPECT_REPORT(driver, (KC_LSFT, KC_B));
- EXPECT_REPORT(driver, (KC_LSFT, KC_A));
- EXPECT_REPORT(driver, (KC_LSFT, KC_B));
- }
-
- caps_word_on();
-
- key_a.press(); // Overlapping taps: A down, B down, A up, B up.
- run_one_scan_loop();
- key_b.press();
- run_one_scan_loop();
- key_a.release();
- run_one_scan_loop();
- key_b.release();
- run_one_scan_loop();
-
- key_a.press(); // Nested taps: A down, B down, B up, A up.
- run_one_scan_loop();
- key_b.press();
- run_one_scan_loop();
- key_b.release();
- run_one_scan_loop();
- key_a.release();
- run_one_scan_loop();
-
- caps_word_off();
- VERIFY_AND_CLEAR(driver);
-}
-
-// Tests that with tap-hold keys with Retro Shift, letter keys are shifted by
-// Caps Word regardless of whether they are retroshifted.
-TEST_F(CapsWord, RetroShiftKeys) {
- TestDriver driver;
- KeymapKey key_modtap_a(0, 0, 0, LCTL_T(KC_A));
- KeymapKey key_layertap_b(0, 1, 0, LT(1, KC_B));
- set_keymap({key_modtap_a, key_layertap_b});
-
- EXPECT_EMPTY_OR_LSFT(driver).Times(AnyNumber());
- { // Expect: "B, A, B, A".
- InSequence s;
- EXPECT_REPORT(driver, (KC_LSFT, KC_B));
- EXPECT_REPORT(driver, (KC_LSFT, KC_A));
- EXPECT_REPORT(driver, (KC_LSFT, KC_B));
- EXPECT_REPORT(driver, (KC_LSFT, KC_A));
- }
-
- // Turn on Caps Word and type "B, A (long press), B (long press), A".
- caps_word_on();
-
- tap_key(key_layertap_b); // Tap B quickly.
- tap_key(key_modtap_a, TAPPING_TERM + 1); // Long press A.
- tap_key(key_layertap_b, TAPPING_TERM + 1); // Long press B.
- tap_key(key_modtap_a); // Tap A quickly.
-
- EXPECT_EQ(is_caps_word_on(), true);
- VERIFY_AND_CLEAR(driver);
-}
diff --git a/tests/caps_word/caps_word_unicodemap/config.h b/tests/caps_word/caps_word_unicodemap/config.h
deleted file mode 100644
index 0f770337b1..0000000000
--- a/tests/caps_word/caps_word_unicodemap/config.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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 .
-
-#pragma once
-
-#include "test_common.h"
-
-#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
diff --git a/tests/caps_word/caps_word_unicodemap/test.mk b/tests/caps_word/caps_word_unicodemap/test.mk
deleted file mode 100644
index 92bcba762c..0000000000
--- a/tests/caps_word/caps_word_unicodemap/test.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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 .
-
-CAPS_WORD_ENABLE = yes
-UNICODEMAP_ENABLE = yes
-
diff --git a/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp b/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp
deleted file mode 100644
index 21e5493526..0000000000
--- a/tests/caps_word/caps_word_unicodemap/test_caps_word_unicodemap.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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 .
-
-#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;
-
-extern "C" {
-enum unicode_names {
- ENDASH,
- EMDASH,
- DELTA_LOWERCASE,
- DELTA_UPPERCASE,
-};
-
-const uint32_t unicode_map[] PROGMEM = {
- [ENDASH] = 0x2013,
- [EMDASH] = 0x2014,
- [DELTA_LOWERCASE] = 0x03b4,
- [DELTA_UPPERCASE] = 0x0394,
-};
-
-#define U_DASH UP(ENDASH, EMDASH)
-#define U_DELTA UP(DELTA_LOWERCASE, DELTA_UPPERCASE)
-
-bool caps_word_press_user(uint16_t keycode) {
- switch (keycode) {
- // Keycodes that continue Caps Word, with shift applied.
- case U_DELTA:
- add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key.
- return true;
-
- // Keycodes that continue Caps Word, without shifting.
- case U_DASH:
- return true;
-
- default:
- return false; // Deactivate Caps Word.
- }
-}
-} // extern "C"
-
-class CapsWord : public TestFixture {
- public:
- void SetUp() override {
- caps_word_off();
- }
-};
-
-// Tests that typing U_DELTA while Caps Word is on sends the uppercase Delta.
-TEST_F(CapsWord, ShiftedUnicodeMapKey) {
- TestDriver driver;
- KeymapKey key_delta(0, 0, 0, U_DELTA);
- KeymapKey key_spc(0, 1, 0, KC_SPC);
- set_keymap({key_delta, key_spc});
-
- // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL.
- // clang-format off
- EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
- KeyboardReport(),
- KeyboardReport(KC_LSFT),
- KeyboardReport(KC_LCTL, KC_LSFT))))
- .Times(AnyNumber());
- // clang-format on
- { // Expect: "Uppercase Delta, space, lowercase delta".
- InSequence s;
- EXPECT_UNICODE(driver, unicode_map[DELTA_UPPERCASE]);
- EXPECT_REPORT(driver, (KC_SPC));
- EXPECT_UNICODE(driver, unicode_map[DELTA_LOWERCASE]);
- }
-
- // Turn on Caps Word and tap "delta, space, delta".
- caps_word_on();
- tap_keys(key_delta, key_spc, key_delta);
-
- EXPECT_EQ(is_caps_word_on(), false);
- VERIFY_AND_CLEAR(driver);
-}
-
-// Tests typing U_ENDASH while Caps Word is on.
-TEST_F(CapsWord, UnshiftedUnicodeMapKey) {
- TestDriver driver;
- KeymapKey key_dash(0, 0, 0, U_DASH);
- set_keymap({key_dash});
-
- // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL.
- // clang-format off
- EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
- KeyboardReport(),
- KeyboardReport(KC_LSFT),
- KeyboardReport(KC_LCTL, KC_LSFT))))
- .Times(AnyNumber());
- // clang-format on
- EXPECT_UNICODE(driver, unicode_map[ENDASH]);
-
- // Turn on Caps Word and tap U_DASH key.
- caps_word_on();
- tap_key(key_dash);
-
- EXPECT_EQ(is_caps_word_on(), true);
- VERIFY_AND_CLEAR(driver);
-}
diff --git a/tests/caps_word/unicodemap/config.h b/tests/caps_word/unicodemap/config.h
new file mode 100644
index 0000000000..0f770337b1
--- /dev/null
+++ b/tests/caps_word/unicodemap/config.h
@@ -0,0 +1,20 @@
+// 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 .
+
+#pragma once
+
+#include "test_common.h"
+
+#define UNICODE_SELECTED_MODES UNICODE_MODE_LINUX
diff --git a/tests/caps_word/unicodemap/test.mk b/tests/caps_word/unicodemap/test.mk
new file mode 100644
index 0000000000..92bcba762c
--- /dev/null
+++ b/tests/caps_word/unicodemap/test.mk
@@ -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 .
+
+CAPS_WORD_ENABLE = yes
+UNICODEMAP_ENABLE = yes
+
diff --git a/tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp b/tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp
new file mode 100644
index 0000000000..21e5493526
--- /dev/null
+++ b/tests/caps_word/unicodemap/test_caps_word_unicodemap.cpp
@@ -0,0 +1,121 @@
+// 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 .
+
+#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;
+
+extern "C" {
+enum unicode_names {
+ ENDASH,
+ EMDASH,
+ DELTA_LOWERCASE,
+ DELTA_UPPERCASE,
+};
+
+const uint32_t unicode_map[] PROGMEM = {
+ [ENDASH] = 0x2013,
+ [EMDASH] = 0x2014,
+ [DELTA_LOWERCASE] = 0x03b4,
+ [DELTA_UPPERCASE] = 0x0394,
+};
+
+#define U_DASH UP(ENDASH, EMDASH)
+#define U_DELTA UP(DELTA_LOWERCASE, DELTA_UPPERCASE)
+
+bool caps_word_press_user(uint16_t keycode) {
+ switch (keycode) {
+ // Keycodes that continue Caps Word, with shift applied.
+ case U_DELTA:
+ add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to next key.
+ return true;
+
+ // Keycodes that continue Caps Word, without shifting.
+ case U_DASH:
+ return true;
+
+ default:
+ return false; // Deactivate Caps Word.
+ }
+}
+} // extern "C"
+
+class CapsWord : public TestFixture {
+ public:
+ void SetUp() override {
+ caps_word_off();
+ }
+};
+
+// Tests that typing U_DELTA while Caps Word is on sends the uppercase Delta.
+TEST_F(CapsWord, ShiftedUnicodeMapKey) {
+ TestDriver driver;
+ KeymapKey key_delta(0, 0, 0, U_DELTA);
+ KeymapKey key_spc(0, 1, 0, KC_SPC);
+ set_keymap({key_delta, key_spc});
+
+ // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL.
+ // clang-format off
+ EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
+ KeyboardReport(),
+ KeyboardReport(KC_LSFT),
+ KeyboardReport(KC_LCTL, KC_LSFT))))
+ .Times(AnyNumber());
+ // clang-format on
+ { // Expect: "Uppercase Delta, space, lowercase delta".
+ InSequence s;
+ EXPECT_UNICODE(driver, unicode_map[DELTA_UPPERCASE]);
+ EXPECT_REPORT(driver, (KC_SPC));
+ EXPECT_UNICODE(driver, unicode_map[DELTA_LOWERCASE]);
+ }
+
+ // Turn on Caps Word and tap "delta, space, delta".
+ caps_word_on();
+ tap_keys(key_delta, key_spc, key_delta);
+
+ EXPECT_EQ(is_caps_word_on(), false);
+ VERIFY_AND_CLEAR(driver);
+}
+
+// Tests typing U_ENDASH while Caps Word is on.
+TEST_F(CapsWord, UnshiftedUnicodeMapKey) {
+ TestDriver driver;
+ KeymapKey key_dash(0, 0, 0, U_DASH);
+ set_keymap({key_dash});
+
+ // Allow any number of reports with no keys or only KC_LSFT and KC_LCTL.
+ // clang-format off
+ EXPECT_CALL(driver, send_keyboard_mock(AnyOf(
+ KeyboardReport(),
+ KeyboardReport(KC_LSFT),
+ KeyboardReport(KC_LCTL, KC_LSFT))))
+ .Times(AnyNumber());
+ // clang-format on
+ EXPECT_UNICODE(driver, unicode_map[ENDASH]);
+
+ // Turn on Caps Word and tap U_DASH key.
+ caps_word_on();
+ tap_key(key_dash);
+
+ EXPECT_EQ(is_caps_word_on(), true);
+ VERIFY_AND_CLEAR(driver);
+}
diff --git a/tests/tap_hold_configurations/default_mod_tap/test.mk b/tests/tap_hold_configurations/default_mod_tap/test.mk
index cfab996e0e..efecca2c22 100644
--- a/tests/tap_hold_configurations/default_mod_tap/test.mk
+++ b/tests/tap_hold_configurations/default_mod_tap/test.mk
@@ -15,4 +15,4 @@
# --------------------------------------------------------------------------------
# Keep this file, even if it is empty, as a marker that this folder contains tests
-# --------------------------------------------------------------------------------
\ No newline at end of file
+# --------------------------------------------------------------------------------
diff --git a/tests/tap_hold_configurations/permissive_hold/config.h b/tests/tap_hold_configurations/permissive_hold/config.h
index 2d5a9849e7..0031c6e5bc 100644
--- a/tests/tap_hold_configurations/permissive_hold/config.h
+++ b/tests/tap_hold_configurations/permissive_hold/config.h
@@ -18,4 +18,4 @@
#include "test_common.h"
-#define PERMISSIVE_HOLD
\ No newline at end of file
+#define PERMISSIVE_HOLD
diff --git a/tests/test_common/build.mk b/tests/test_common/build.mk
index aeb3057854..d7423bc78a 100644
--- a/tests/test_common/build.mk
+++ b/tests/test_common/build.mk
@@ -13,4 +13,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-CUSTOM_MATRIX=yes
\ No newline at end of file
+CUSTOM_MATRIX=yes
diff --git a/tests/test_common/main.cpp b/tests/test_common/main.cpp
index 0f4e320b07..ac481b8fba 100644
--- a/tests/test_common/main.cpp
+++ b/tests/test_common/main.cpp
@@ -29,4 +29,4 @@ int main(int argc, char **argv) {
init_logging();
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/tests/test_common/test_common.h b/tests/test_common/test_common.h
index 19ffcddcea..8b93c032b6 100644
--- a/tests/test_common/test_common.h
+++ b/tests/test_common/test_common.h
@@ -1,4 +1,4 @@
#pragma once
#define MATRIX_ROWS 4
-#define MATRIX_COLS 10
\ No newline at end of file
+#define MATRIX_COLS 10
--
cgit v1.2.3