a24bdccee0580d1263733bc7e66e4e4f97713f19
- Author
- Stefan Kerkmann <karlk90@pm.me>
- Committer
- GitHub <noreply@github.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/Makefile b/Makefile
2index c221cb89e02189e8c1b656413c025576d37b5402..88f430619e39f866744b3498e183de59c7d603c2 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -378,11 +378,12 @@ define PARSE_ALL_KEYMAPS
6 endef
7
8 define BUILD_TEST
9- TEST_NAME := $1
10+ TEST_PATH := $1
11+ TEST_NAME := $$(notdir $$(TEST_PATH))
12 MAKE_TARGET := $2
13 COMMAND := $1
14 MAKE_CMD := $$(MAKE) -r -R -C $(ROOT_DIR) -f build_test.mk $$(MAKE_TARGET)
15- MAKE_VARS := TEST=$$(TEST_NAME) FULL_TESTS="$$(FULL_TESTS)"
16+ MAKE_VARS := TEST=$$(TEST_NAME) TEST_PATH=$$(TEST_PATH) FULL_TESTS="$$(FULL_TESTS)"
17 MAKE_MSG := $$(MSG_MAKE_TEST)
18 $$(eval $$(call BUILD))
19 ifneq ($$(MAKE_TARGET),clean)
20@@ -406,7 +407,7 @@ define PARSE_TEST
21 ifeq ($$(TEST_NAME),all)
22 MATCHED_TESTS := $$(TEST_LIST)
23 else
24- MATCHED_TESTS := $$(foreach TEST,$$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME),$$(TEST)),$$(TEST),))
25+ MATCHED_TESTS := $$(foreach TEST, $$(TEST_LIST),$$(if $$(findstring $$(TEST_NAME), $$(notdir $$(TEST))), $$(TEST),))
26 endif
27 $$(foreach TEST,$$(MATCHED_TESTS),$$(eval $$(call BUILD_TEST,$$(TEST),$$(TEST_TARGET))))
28 endef
29diff --git a/build_full_test.mk b/build_full_test.mk
30index f8030cb0600db6aa1eb467ba2c02a2bbc2530198..4cd1ac61b53fd2d93e7729f3a7927853c756c605 100644
31--- a/build_full_test.mk
32+++ b/build_full_test.mk
33@@ -13,21 +13,24 @@
34 # You should have received a copy of the GNU General Public License
35 # along with this program. If not, see <http://www.gnu.org/licenses/>.
36
37-#include $(TMK_PATH)/protocol.mk
38+$(TEST)_INC := \
39+ tests\test_common\common_config.h
40
41-TEST_PATH=tests/$(TEST)
42-
43-$(TEST)_SRC= \
44- $(TEST_PATH)/keymap.c \
45+$(TEST)_SRC := \
46 $(TMK_COMMON_SRC) \
47 $(QUANTUM_SRC) \
48 $(SRC) \
49+ tests/test_common/keymap.c \
50 tests/test_common/matrix.c \
51 tests/test_common/test_driver.cpp \
52 tests/test_common/keyboard_report_util.cpp \
53- tests/test_common/test_fixture.cpp
54-$(TEST)_SRC += $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
55+ tests/test_common/test_fixture.cpp \
56+ tests/test_common/test_keymap_key.cpp \
57+ tests/test_common/test_logger.cpp \
58+ $(patsubst $(ROOTDIR)/%,%,$(wildcard $(TEST_PATH)/*.cpp))
59+
60+$(TEST)_DEFS := $(TMK_COMMON_DEFS) $(OPT_DEFS)
61+
62+$(TEST)_CONFIG := $(TEST_PATH)/config.h
63
64-$(TEST)_DEFS=$(TMK_COMMON_DEFS) $(OPT_DEFS)
65-$(TEST)_CONFIG=$(TEST_PATH)/config.h
66-VPATH+=$(TOP_DIR)/tests/test_common
67+VPATH += $(TOP_DIR)/tests/test_common
68diff --git a/build_test.mk b/build_test.mk
69index 36cb7936edd6094f97327d7b7f8134566abd8cb5..136a0455f01c87a6dd98204df9e476f88b675dd7 100644
70--- a/build_test.mk
71+++ b/build_test.mk
72@@ -16,14 +16,14 @@ TEST_OBJ = $(BUILD_DIR)/test_obj
73 OUTPUTS := $(TEST_OBJ)/$(TEST) $(GTEST_OUTPUT)
74
75 GTEST_INC := \
76- $(LIB_PATH)/googletest/googletest/include\
77- $(LIB_PATH)/googletest/googlemock/include\
78+ $(LIB_PATH)/googletest/googletest/include \
79+ $(LIB_PATH)/googletest/googlemock/include
80
81-GTEST_INTERNAL_INC :=\
82- $(LIB_PATH)/googletest/googletest\
83+GTEST_INTERNAL_INC := \
84+ $(LIB_PATH)/googletest/googletest \
85 $(LIB_PATH)/googletest/googlemock
86
87-$(GTEST_OUTPUT)_SRC :=\
88+$(GTEST_OUTPUT)_SRC := \
89 googletest/src/gtest-all.cc\
90 googlemock/src/gmock-all.cc
91
92@@ -33,9 +33,9 @@ $(GTEST_OUTPUT)_INC := $(GTEST_INC) $(GTEST_INTERNAL_INC)
93 LDFLAGS += -lstdc++ -lpthread -shared-libgcc
94 CREATE_MAP := no
95
96-VPATH +=\
97- $(LIB_PATH)/googletest\
98- $(LIB_PATH)/googlemock\
99+VPATH += \
100+ $(LIB_PATH)/googletest \
101+ $(LIB_PATH)/googlemock \
102 $(LIB_PATH)/printf
103
104 all: elf
105@@ -49,7 +49,8 @@ CONSOLE_ENABLE = yes
106 endif
107
108 ifneq ($(filter $(FULL_TESTS),$(TEST)),)
109-include tests/$(TEST)/rules.mk
110+include tests/test_common/build.mk
111+include $(TEST_PATH)/test.mk
112 endif
113
114 include common_features.mk
115diff --git a/testlist.mk b/testlist.mk
116index cff784dad61dcc3551d1be8d5659dea212df1638..d2bb571be64f562d7adff1d46c4c6e979460146b 100644
117--- a/testlist.mk
118+++ b/testlist.mk
119@@ -1,5 +1,5 @@
120-TEST_LIST = $(notdir $(patsubst %/rules.mk,%,$(wildcard $(ROOT_DIR)/tests/*/rules.mk)))
121-FULL_TESTS := $(TEST_LIST)
122+TEST_LIST = $(sort $(patsubst %/test.mk,%, $(shell find $(ROOT_DIR)tests -type f -name test.mk)))
123+FULL_TESTS := $(notdir $(TEST_LIST))
124
125 include $(QUANTUM_PATH)/debounce/tests/testlist.mk
126 include $(QUANTUM_PATH)/encoder/tests/testlist.mk
127diff --git a/tests/auto_shift/config.h b/tests/auto_shift/config.h
128new file mode 100644
129index 0000000000000000000000000000000000000000..4f343b45299531730d47ae5e07d11cc8fde5702d
130--- /dev/null
131+++ b/tests/auto_shift/config.h
132@@ -0,0 +1,19 @@
133+/* Copyright 2021 Stefan Kerkmann
134+ *
135+ * This program is free software: you can redistribute it and/or modify
136+ * it under the terms of the GNU General Public License as published by
137+ * the Free Software Foundation, either version 2 of the License, or
138+ * (at your option) any later version.
139+ *
140+ * This program is distributed in the hope that it will be useful,
141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143+ * GNU General Public License for more details.
144+ *
145+ * You should have received a copy of the GNU General Public License
146+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
147+ */
148+
149+#pragma once
150+
151+#include "test_common.h"
152diff --git a/tests/auto_shift/test.mk b/tests/auto_shift/test.mk
153new file mode 100644
154index 0000000000000000000000000000000000000000..4259c606e472940f512b0d092e351d34cb7a02c9
155--- /dev/null
156+++ b/tests/auto_shift/test.mk
157@@ -0,0 +1,20 @@
158+# Copyright 2021 Stefan Kerkmann
159+#
160+# This program is free software: you can redistribute it and/or modify
161+# it under the terms of the GNU General Public License as published by
162+# the Free Software Foundation, either version 2 of the License, or
163+# (at your option) any later version.
164+#
165+# This program is distributed in the hope that it will be useful,
166+# but WITHOUT ANY WARRANTY; without even the implied warranty of
167+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
168+# GNU General Public License for more details.
169+#
170+# You should have received a copy of the GNU General Public License
171+# along with this program. If not, see <http://www.gnu.org/licenses/>.
172+
173+# --------------------------------------------------------------------------------
174+# Keep this file, even if it is empty, as a marker that this folder contains tests
175+# --------------------------------------------------------------------------------
176+
177+AUTO_SHIFT_ENABLE = yes
178diff --git a/tests/auto_shift/test_auto_shift.cpp b/tests/auto_shift/test_auto_shift.cpp
179new file mode 100644
180index 0000000000000000000000000000000000000000..9c5ed9a8326a829f5a053c6bb1b405612230ff51
181--- /dev/null
182+++ b/tests/auto_shift/test_auto_shift.cpp
183@@ -0,0 +1,73 @@
184+/* Copyright 2021 Stefan Kerkmann
185+ *
186+ * This program is free software: you can redistribute it and/or modify
187+ * it under the terms of the GNU General Public License as published by
188+ * the Free Software Foundation, either version 2 of the License, or
189+ * (at your option) any later version.
190+ *
191+ * This program is distributed in the hope that it will be useful,
192+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
193+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
194+ * GNU General Public License for more details.
195+ *
196+ * You should have received a copy of the GNU General Public License
197+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
198+ */
199+
200+#include "keyboard_report_util.hpp"
201+#include "keycode.h"
202+#include "test_common.hpp"
203+#include "action_tapping.h"
204+#include "test_fixture.hpp"
205+#include "test_keymap_key.hpp"
206+
207+using testing::_;
208+using testing::InSequence;
209+
210+class AutoShift : public TestFixture {};
211+
212+TEST_F(AutoShift, key_release_before_timeout) {
213+ TestDriver driver;
214+ InSequence s;
215+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
216+
217+ set_keymap({regular_key});
218+
219+ /* Press regular key */
220+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
221+ regular_key.press();
222+ run_one_scan_loop();
223+ testing::Mock::VerifyAndClearExpectations(&driver);
224+
225+ /* Release regular key */
226+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
227+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
228+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
229+ regular_key.release();
230+ run_one_scan_loop();
231+ testing::Mock::VerifyAndClearExpectations(&driver);
232+}
233+
234+TEST_F(AutoShift, key_release_after_timeout) {
235+ TestDriver driver;
236+ InSequence s;
237+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
238+
239+ set_keymap({regular_key});
240+
241+ /* Press regular key */
242+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
243+ regular_key.press();
244+ idle_for(AUTO_SHIFT_TIMEOUT);
245+ testing::Mock::VerifyAndClearExpectations(&driver);
246+
247+ /* Release regular key */
248+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
249+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
250+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
251+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
252+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
253+ regular_key.release();
254+ run_one_scan_loop();
255+ testing::Mock::VerifyAndClearExpectations(&driver);
256+}
257diff --git a/tests/basic/config.h b/tests/basic/config.h
258index 99bd62d991c4bf6bc4228cc3548277b1d1f9a1ae..85fa9d691d08ab9d119d707f96247cbabea4c5e7 100644
259--- a/tests/basic/config.h
260+++ b/tests/basic/config.h
261@@ -16,5 +16,4 @@
262
263 #pragma once
264
265-#define MATRIX_ROWS 4
266-#define MATRIX_COLS 10
267+#include "test_common.h"
268diff --git a/tests/basic/keymap.c b/tests/basic/keymap.c
269deleted file mode 100644
270index 2b5747abb7cbcf61090e2be466f2504b88b0980f..0000000000000000000000000000000000000000
271--- a/tests/basic/keymap.c
272+++ /dev/null
273@@ -1,45 +0,0 @@
274-/* Copyright 2017 Fred Sundvik
275- *
276- * This program is free software: you can redistribute it and/or modify
277- * it under the terms of the GNU General Public License as published by
278- * the Free Software Foundation, either version 2 of the License, or
279- * (at your option) any later version.
280- *
281- * This program is distributed in the hope that it will be useful,
282- * but WITHOUT ANY WARRANTY; without even the implied warranty of
283- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284- * GNU General Public License for more details.
285- *
286- * You should have received a copy of the GNU General Public License
287- * along with this program. If not, see <http://www.gnu.org/licenses/>.
288- */
289-
290-#include "quantum.h"
291-
292-// Don't rearrange keys as existing tests might rely on the order
293-// Col2, Row 0 has to be KC_NO, because tests rely on it
294-
295-#define COMBO1 RSFT(LCTL(KC_O))
296-
297-const uint16_t PROGMEM
298- keymaps[][MATRIX_ROWS][MATRIX_COLS] =
299- {
300- [0] =
301- {
302- // 0 1 2 3 4 5 6 7 8 9
303- {KC_A, KC_B, KC_NO, KC_LSFT, KC_RSFT, KC_LCTL, COMBO1, SFT_T(KC_P), M(0), KC_NO},
304- {KC_EQL, KC_PLUS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
305- {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
306- {KC_C, KC_D, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
307- },
308-};
309-
310-const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
311- if (record->event.pressed) {
312- switch (id) {
313- case 0:
314- return MACRO(D(LSFT), T(H), U(LSFT), T(E), T(L), T(L), T(O), T(SPACE), W(100), D(LSFT), T(W), U(LSFT), I(10), T(O), T(R), T(L), T(D), D(LSFT), T(1), U(LSFT), END);
315- }
316- }
317- return MACRO_NONE;
318-};
319diff --git a/tests/basic/test.mk b/tests/basic/test.mk
320new file mode 100644
321index 0000000000000000000000000000000000000000..29690d1adf7b4530aeed9679a8194b1271437623
322--- /dev/null
323+++ b/tests/basic/test.mk
324@@ -0,0 +1,18 @@
325+# Copyright 2017 Fred Sundvik
326+#
327+# This program is free software: you can redistribute it and/or modify
328+# it under the terms of the GNU General Public License as published by
329+# the Free Software Foundation, either version 2 of the License, or
330+# (at your option) any later version.
331+#
332+# This program is distributed in the hope that it will be useful,
333+# but WITHOUT ANY WARRANTY; without even the implied warranty of
334+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
335+# GNU General Public License for more details.
336+#
337+# You should have received a copy of the GNU General Public License
338+# along with this program. If not, see <http://www.gnu.org/licenses/>.
339+
340+# --------------------------------------------------------------------------------
341+# Keep this file, even if it is empty, as a marker that this folder contains tests
342+# --------------------------------------------------------------------------------
343diff --git a/tests/basic/test_action_layer.cpp b/tests/basic/test_action_layer.cpp
344index d00a0859b9c66d87ef92ecbc72b2a6d509b35b4d..1b12d13642fe18b6e84a42ea2ac4adfcfa1407f1 100644
345--- a/tests/basic/test_action_layer.cpp
346+++ b/tests/basic/test_action_layer.cpp
347@@ -14,39 +14,54 @@
348 * along with this program. If not, see <http://www.gnu.org/licenses/>.
349 */
350
351+#include "gtest/gtest.h"
352+#include "keyboard_report_util.hpp"
353 #include "test_common.hpp"
354
355 using testing::_;
356-using testing::Return;
357+using testing::InSequence;
358
359 class ActionLayer : public TestFixture {};
360
361-// TEST_F(ActionLayer, LayerStateDBG) {
362-// layer_state_set(0);
363-// }
364-
365-// TEST_F(ActionLayer, LayerStateSet) {
366-// layer_state_set(0);
367-// EXPECT_EQ(layer_state, 0);
368-// layer_state_set(0b001100);
369-// EXPECT_EQ(layer_state, 0b001100);
370-// }
371-
372-// TEST_F(ActionLayer, LayerStateIs) {
373-// layer_state_set(0);
374-// EXPECT_EQ(layer_state_is(0), true);
375-// EXPECT_EQ(layer_state_is(1), true);
376-// layer_state_set(1);
377-// EXPECT_EQ(layer_state_is(0), true);
378-// EXPECT_EQ(layer_state_is(1), true);
379-// layer_state_set(2);
380-// EXPECT_EQ(layer_state_is(0), false);
381-// EXPECT_EQ(layer_state_is(1), false);
382-// EXPECT_EQ(layer_state_is(2), true);
383-// }
384+TEST_F(ActionLayer, LayerStateDBG) {
385+ TestDriver driver;
386+
387+ layer_state_set(0);
388+
389+ testing::Mock::VerifyAndClearExpectations(&driver);
390+}
391+
392+TEST_F(ActionLayer, LayerStateSet) {
393+ TestDriver driver;
394+
395+ layer_state_set(0);
396+ EXPECT_EQ(layer_state, 0);
397+ layer_state_set(0b001100);
398+ EXPECT_EQ(layer_state, 0b001100);
399+
400+ testing::Mock::VerifyAndClearExpectations(&driver);
401+}
402+
403+TEST_F(ActionLayer, LayerStateIs) {
404+ TestDriver driver;
405+
406+ layer_state_set(0);
407+ EXPECT_EQ(layer_state_is(0), true);
408+ EXPECT_EQ(layer_state_is(1), false);
409+ layer_state_set(1);
410+ EXPECT_EQ(layer_state_is(0), true);
411+ EXPECT_EQ(layer_state_is(1), false);
412+ layer_state_set(2);
413+ EXPECT_EQ(layer_state_is(0), false);
414+ EXPECT_EQ(layer_state_is(1), true);
415+ EXPECT_EQ(layer_state_is(2), false);
416+
417+ testing::Mock::VerifyAndClearExpectations(&driver);
418+}
419
420 TEST_F(ActionLayer, LayerStateCmp) {
421- uint32_t prev_layer;
422+ TestDriver driver;
423+ uint32_t prev_layer;
424
425 prev_layer = 0;
426 EXPECT_EQ(layer_state_cmp(prev_layer, 0), true);
427@@ -60,33 +75,339 @@ TEST_F(ActionLayer, LayerStateCmp) {
428 EXPECT_EQ(layer_state_cmp(prev_layer, 0), false);
429 EXPECT_EQ(layer_state_cmp(prev_layer, 1), true);
430 EXPECT_EQ(layer_state_cmp(prev_layer, 2), false);
431+
432+ testing::Mock::VerifyAndClearExpectations(&driver);
433+}
434+
435+TEST_F(ActionLayer, LayerClear) {
436+ TestDriver driver;
437+
438+ layer_clear();
439+ EXPECT_EQ(layer_state, 0);
440+
441+ testing::Mock::VerifyAndClearExpectations(&driver);
442+}
443+
444+TEST_F(ActionLayer, LayerMove) {
445+ TestDriver driver;
446+
447diff --git a/tests/basic/test_keypress.cpp b/tests/basic/test_keypress.cpp
448index cf839f8c16d5afdf2816c9a5c371bebfba1ac5a0..1c175c9d56a7e0c0dd58e70c4d877d6294c2b410 100644
449--- a/tests/basic/test_keypress.cpp
450+++ b/tests/basic/test_keypress.cpp
451@@ -14,11 +14,11 @@
452 * along with this program. If not, see <http://www.gnu.org/licenses/>.
453 */
454
455+#include "keycode.h"
456 #include "test_common.hpp"
457
458 using testing::_;
459 using testing::InSequence;
460-using testing::Return;
461
462 class KeyPress : public TestFixture {};
463
464@@ -30,96 +30,157 @@ TEST_F(KeyPress, SendKeyboardIsNotCalledWhenNoKeyIsPressed) {
465
466 TEST_F(KeyPress, CorrectKeyIsReportedWhenPressed) {
467 TestDriver driver;
468- press_key(0, 0);
469- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
470+ auto key = KeymapKey(0, 0, 0, KC_A);
471+
472+ set_keymap({key});
473+
474+ key.press();
475+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key.report_code)));
476 keyboard_task();
477- release_key(0, 0);
478+
479+ key.release();
480 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
481 keyboard_task();
482 }
483
484+TEST_F(KeyPress, ANonMappedKeyDoesNothing) {
485+ TestDriver driver;
486+ auto key = KeymapKey(0, 0, 0, KC_NO);
487+
488+ set_keymap({key});
489+
490+ key.press();
491+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
492+ keyboard_task();
493+ keyboard_task();
494+}
495+
496 TEST_F(KeyPress, CorrectKeysAreReportedWhenTwoKeysArePressed) {
497 TestDriver driver;
498- press_key(1, 0);
499- press_key(0, 3);
500+ auto key_b = KeymapKey(0, 0, 0, KC_B);
501+ auto key_c = KeymapKey(0, 1, 1, KC_C);
502+
503+ set_keymap({key_b, key_c});
504+
505+ key_b.press();
506+ key_c.press();
507 // Note that QMK only processes one key at a time
508 // See issue #1476 for more information
509- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B)));
510+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code)));
511 keyboard_task();
512- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B, KC_C)));
513+
514+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_b.report_code, key_c.report_code)));
515 keyboard_task();
516- release_key(1, 0);
517- release_key(0, 3);
518+
519+ key_b.release();
520+ key_c.release();
521 // Note that the first key released is the first one in the matrix order
522- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_C)));
523- keyboard_task();
524- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
525+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(key_c.report_code)));
526 keyboard_task();
527-}
528
529-TEST_F(KeyPress, ANonMappedKeyDoesNothing) {
530- TestDriver driver;
531- press_key(2, 0);
532- EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
533- keyboard_task();
534+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
535 keyboard_task();
536 }
537
538 TEST_F(KeyPress, LeftShiftIsReportedCorrectly) {
539 TestDriver driver;
540- press_key(3, 0);
541- press_key(0, 0);
542+ auto key_a = KeymapKey(0, 0, 0, KC_A);
543+ auto key_lsft = KeymapKey(0, 3, 0, KC_LSFT);
544+
545+ set_keymap({key_a, key_lsft});
546+
547+ key_lsft.press();
548+ key_a.press();
549+
550 // Unfortunately modifiers are also processed in the wrong order
551diff --git a/tests/basic/test_macro.cpp b/tests/basic/test_macro.cpp
552index 1ac6f473fc819d5d4cdceb9ad6f873c18a09e7eb..ae2f3b32e3fb0b3def641f5a58593e05f4deab9f 100644
553--- a/tests/basic/test_macro.cpp
554+++ b/tests/basic/test_macro.cpp
555@@ -24,10 +24,25 @@ class Macro : public TestFixture {};
556
557 #define AT_TIME(t) WillOnce(InvokeWithoutArgs([current_time]() { EXPECT_EQ(timer_elapsed32(current_time), t); }))
558
559+extern "C" const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
560+ if (record->event.pressed) {
561+ switch (id) {
562+ case 0:
563+ return MACRO(D(LSFT), T(H), U(LSFT), T(E), T(L), T(L), T(O), T(SPACE), W(100), D(LSFT), T(W), U(LSFT), I(10), T(O), T(R), T(L), T(D), D(LSFT), T(1), U(LSFT), END);
564+ }
565+ }
566+ return MACRO_NONE;
567+};
568+
569 TEST_F(Macro, PlayASimpleMacro) {
570 TestDriver driver;
571 InSequence s;
572- press_key(8, 0);
573+ auto key_macro = KeymapKey(0, 8, 0, M(0));
574+
575+ set_keymap({key_macro});
576+
577+ key_macro.press();
578+
579 uint32_t current_time = timer_read32();
580 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(0);
581 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT, KC_H))).AT_TIME(0);
582@@ -68,4 +83,6 @@ TEST_F(Macro, PlayASimpleMacro) {
583 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT))).AT_TIME(210);
584 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).AT_TIME(220);
585 run_one_scan_loop();
586+
587+ key_macro.release();
588 }
589diff --git a/tests/basic/test_one_shot_keys.cpp b/tests/basic/test_one_shot_keys.cpp
590new file mode 100644
591index 0000000000000000000000000000000000000000..98178912e4cc47d2d2a0e57c24d134f91902a4be
592--- /dev/null
593+++ b/tests/basic/test_one_shot_keys.cpp
594@@ -0,0 +1,197 @@
595+/* Copyright 2021 Stefan Kerkmann
596+ *
597+ * This program is free software: you can redistribute it and/or modify
598+ * it under the terms of the GNU General Public License as published by
599+ * the Free Software Foundation, either version 2 of the License, or
600+ * (at your option) any later version.
601+ *
602+ * This program is distributed in the hope that it will be useful,
603+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
604+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
605+ * GNU General Public License for more details.
606+ *
607+ * You should have received a copy of the GNU General Public License
608+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
609+ */
610+
611+#include "action_util.h"
612+#include "keyboard_report_util.hpp"
613+#include "test_common.hpp"
614+
615+using testing::_;
616+using testing::InSequence;
617+
618+class OneShot : public TestFixture {};
619+class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {};
620+
621+TEST_F(OneShot, OSMWithoutAdditionalKeypressDoesNothing) {
622+ TestDriver driver;
623+ auto osm_key = KeymapKey(0, 0, 0, OSM(MOD_LSFT), KC_LSFT);
624+
625+ set_keymap({osm_key});
626+
627+ /* Press and release OSM key*/
628+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
629+ osm_key.press();
630+ run_one_scan_loop();
631+ osm_key.release();
632+ run_one_scan_loop();
633+ testing::Mock::VerifyAndClearExpectations(&driver);
634+
635+ /* OSM are added when an actual report is send */
636+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code)));
637+ send_keyboard_report();
638+ testing::Mock::VerifyAndClearExpectations(&driver);
639+
640+ /* Make unit-test pass */
641+ clear_oneshot_mods();
642+}
643+
644+#if defined(ONESHOT_TIMEOUT)
645+
646+TEST_P(OneShotParametrizedTestFixture, OSMExpiredDoesNothing) {
647+ TestDriver driver;
648+ KeymapKey osm_key = GetParam().first;
649+ KeymapKey regular_key = GetParam().second;
650+
651+ set_keymap({osm_key, regular_key});
652+
653+ /* Press and release OSM */
654+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
655+ osm_key.press();
656+ run_one_scan_loop();
657+ osm_key.release();
658+ idle_for(ONESHOT_TIMEOUT);
659+ testing::Mock::VerifyAndClearExpectations(&driver);
660+
661+ /* Press regular key */
662+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code))).Times(1);
663+ regular_key.press();
664+ run_one_scan_loop();
665+ testing::Mock::VerifyAndClearExpectations(&driver);
666+
667+ /* Release regular key */
668+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
669+ regular_key.release();
670+ run_one_scan_loop();
671+ testing::Mock::VerifyAndClearExpectations(&driver);
672+}
673+
674+#endif
675+
676+TEST_P(OneShotParametrizedTestFixture, OSMWithAdditionalKeypress) {
677+ TestDriver driver;
678+ KeymapKey osm_key = GetParam().first;
679+ KeymapKey regular_key = GetParam().second;
680+
681+ set_keymap({osm_key, regular_key});
682+
683+ /* Press and release OSM */
684+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
685+ osm_key.press();
686+ run_one_scan_loop();
687+ osm_key.release();
688+ run_one_scan_loop();
689+ testing::Mock::VerifyAndClearExpectations(&driver);
690+
691+ /* Press regular key */
692+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code, regular_key.report_code))).Times(1);
693+ regular_key.press();
694diff --git a/tests/basic/test_tapping.cpp b/tests/basic/test_tapping.cpp
695index 88ab97eb6e69bdd20c6a9fe1fdfb575dd2730f0a..e4a7e4a9f3f0df3c834f5e2d5f5c829dac7db9ea 100644
696--- a/tests/basic/test_tapping.cpp
697+++ b/tests/basic/test_tapping.cpp
698@@ -14,8 +14,11 @@
699 * along with this program. If not, see <http://www.gnu.org/licenses/>.
700 */
701
702+#include "keyboard_report_util.hpp"
703+#include "keycode.h"
704 #include "test_common.hpp"
705 #include "action_tapping.h"
706+#include "test_keymap_key.hpp"
707
708 using testing::_;
709 using testing::InSequence;
710@@ -25,14 +28,19 @@ class Tapping : public TestFixture {};
711 TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) {
712 TestDriver driver;
713 InSequence s;
714+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
715+
716+ set_keymap({key_shift_hold_p_tap});
717
718- press_key(7, 0);
719 // Tapping keys does nothing on press
720+ key_shift_hold_p_tap.press();
721 EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
722 run_one_scan_loop();
723- release_key(7, 0);
724+
725 // First we get the key press
726+ key_shift_hold_p_tap.release();
727 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
728+
729 // Then the release
730 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
731 run_one_scan_loop();
732@@ -41,12 +49,21 @@ TEST_F(Tapping, TapA_SHFT_T_KeyReportsKey) {
733 TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) {
734 TestDriver driver;
735 InSequence s;
736+ auto mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P));
737+
738+ set_keymap({mod_tap_hold_key});
739+
740+ mod_tap_hold_key.press();
741
742- press_key(7, 0);
743 // Tapping keys does nothing on press
744 EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
745 idle_for(TAPPING_TERM);
746- EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LEFT_SHIFT)));
747+
748+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
749+ run_one_scan_loop();
750+
751+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
752+ mod_tap_hold_key.release();
753 run_one_scan_loop();
754 }
755
756@@ -54,12 +71,16 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
757 // See issue #1478 for more information
758 TestDriver driver;
759 InSequence s;
760+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
761+
762+ set_keymap({key_shift_hold_p_tap});
763
764- press_key(7, 0);
765 // Tapping keys does nothing on press
766+ key_shift_hold_p_tap.press();
767 EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
768 run_one_scan_loop();
769- release_key(7, 0);
770+ key_shift_hold_p_tap.release();
771+
772 // First we get the key press
773 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
774 // Then the release
775@@ -67,19 +88,20 @@ TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
776 run_one_scan_loop();
777
778 // This sends KC_P, even if it should do nothing
779- press_key(7, 0);
780+ key_shift_hold_p_tap.press();
781 // This test should not succed if everything works correctly
782 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
783 run_one_scan_loop();
784- release_key(7, 0);
785+
786+ key_shift_hold_p_tap.release();
787 EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
788 idle_for(TAPPING_TERM + 1);
789
790 // On the other hand, nothing is sent if we are outside the tapping term
791- press_key(7, 0);
792+ key_shift_hold_p_tap.press();
793 EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
794 run_one_scan_loop();
795- release_key(7, 0);
796+ key_shift_hold_p_tap.release();
797
798diff --git a/tests/tap_hold_configurations/default_mod_tap/config.h b/tests/tap_hold_configurations/default_mod_tap/config.h
799new file mode 100644
800index 0000000000000000000000000000000000000000..5955b8600a8750f244ef051d401a201c2dea5a76
801--- /dev/null
802+++ b/tests/tap_hold_configurations/default_mod_tap/config.h
803@@ -0,0 +1,21 @@
804+/* Copyright 2021 Stefan Kerkmann
805+ *
806+ * This program is free software: you can redistribute it and/or modify
807+ * it under the terms of the GNU General Public License as published by
808+ * the Free Software Foundation, either version 2 of the License, or
809+ * (at your option) any later version.
810+ *
811+ * This program is distributed in the hope that it will be useful,
812+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
813+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
814+ * GNU General Public License for more details.
815+ *
816+ * You should have received a copy of the GNU General Public License
817+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
818+ */
819+
820+#pragma once
821+
822+#include "test_common.h"
823+
824+#define IGNORE_MOD_TAP_INTERRUPT
825diff --git a/tests/tap_hold_configurations/default_mod_tap/test.mk b/tests/tap_hold_configurations/default_mod_tap/test.mk
826new file mode 100644
827index 0000000000000000000000000000000000000000..cfab996e0ef819205d9c1662559032fab99b8c1c
828--- /dev/null
829+++ b/tests/tap_hold_configurations/default_mod_tap/test.mk
830@@ -0,0 +1,18 @@
831+# Copyright 2021 Stefan Kerkmann
832+#
833+# This program is free software: you can redistribute it and/or modify
834+# it under the terms of the GNU General Public License as published by
835+# the Free Software Foundation, either version 2 of the License, or
836+# (at your option) any later version.
837+#
838+# This program is distributed in the hope that it will be useful,
839+# but WITHOUT ANY WARRANTY; without even the implied warranty of
840+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
841+# GNU General Public License for more details.
842+#
843+# You should have received a copy of the GNU General Public License
844+# along with this program. If not, see <http://www.gnu.org/licenses/>.
845+
846+# --------------------------------------------------------------------------------
847+# Keep this file, even if it is empty, as a marker that this folder contains tests
848+# --------------------------------------------------------------------------------
849diff --git a/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp
850new file mode 100644
851index 0000000000000000000000000000000000000000..90befcdffd1553c44c48ae90ccc10e6a3e6e3249
852--- /dev/null
853+++ b/tests/tap_hold_configurations/default_mod_tap/test_tap_hold.cpp
854@@ -0,0 +1,230 @@
855+/* Copyright 2021 Stefan Kerkmann
856+ *
857+ * This program is free software: you can redistribute it and/or modify
858+ * it under the terms of the GNU General Public License as published by
859+ * the Free Software Foundation, either version 2 of the License, or
860+ * (at your option) any later version.
861+ *
862+ * This program is distributed in the hope that it will be useful,
863+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
864+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
865+ * GNU General Public License for more details.
866+ *
867+ * You should have received a copy of the GNU General Public License
868+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
869+ */
870+
871+#include "keyboard_report_util.hpp"
872+#include "keycode.h"
873+#include "test_common.hpp"
874+#include "action_tapping.h"
875+#include "test_fixture.hpp"
876+#include "test_keymap_key.hpp"
877+
878+using testing::_;
879+using testing::InSequence;
880+
881+class DefaultTapHold : public TestFixture {};
882+
883+TEST_F(DefaultTapHold, tap_regular_key_while_mod_tap_key_is_held) {
884+ TestDriver driver;
885+ InSequence s;
886+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
887+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
888+
889+ set_keymap({mod_tap_hold_key, regular_key});
890+
891+ /* Press mod-tap-hold key. */
892+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
893+ mod_tap_hold_key.press();
894+ run_one_scan_loop();
895+ testing::Mock::VerifyAndClearExpectations(&driver);
896+
897+ /* Press regular key. */
898+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
899+ regular_key.press();
900+ run_one_scan_loop();
901+ testing::Mock::VerifyAndClearExpectations(&driver);
902+
903+ /* Release regular key. */
904+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
905+ regular_key.release();
906+ run_one_scan_loop();
907+ testing::Mock::VerifyAndClearExpectations(&driver);
908+
909+ /* Release mod-tap-hold key. */
910+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
911+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A)));
912+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
913+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
914+ mod_tap_hold_key.release();
915+ run_one_scan_loop();
916+ testing::Mock::VerifyAndClearExpectations(&driver);
917+
918+ /* Idle for tapping term of mod tap hold key. */
919+ idle_for(TAPPING_TERM - 3);
920+ testing::Mock::VerifyAndClearExpectations(&driver);
921+}
922+
923+TEST_F(DefaultTapHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
924+ TestDriver driver;
925+ InSequence s;
926+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
927+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
928+
929+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
930+
931+ /* Press first mod-tap-hold key */
932+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
933+ first_mod_tap_hold_key.press();
934+ run_one_scan_loop();
935+ testing::Mock::VerifyAndClearExpectations(&driver);
936+
937+ /* Press second tap-hold key */
938+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
939+ second_mod_tap_hold_key.press();
940+ run_one_scan_loop();
941+ testing::Mock::VerifyAndClearExpectations(&driver);
942+
943+ /* Release second tap-hold key */
944+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
945+ second_mod_tap_hold_key.release();
946+ run_one_scan_loop();
947+ testing::Mock::VerifyAndClearExpectations(&driver);
948+
949+ /* Release first mod-tap-hold key */
950+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
951+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P, KC_A)));
952+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
953+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
954diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h
955new file mode 100644
956index 0000000000000000000000000000000000000000..5955b8600a8750f244ef051d401a201c2dea5a76
957--- /dev/null
958+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/config.h
959@@ -0,0 +1,21 @@
960+/* Copyright 2021 Stefan Kerkmann
961+ *
962+ * This program is free software: you can redistribute it and/or modify
963+ * it under the terms of the GNU General Public License as published by
964+ * the Free Software Foundation, either version 2 of the License, or
965+ * (at your option) any later version.
966+ *
967+ * This program is distributed in the hope that it will be useful,
968+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
969+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
970+ * GNU General Public License for more details.
971+ *
972+ * You should have received a copy of the GNU General Public License
973+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
974+ */
975+
976+#pragma once
977+
978+#include "test_common.h"
979+
980+#define IGNORE_MOD_TAP_INTERRUPT
981diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk
982new file mode 100644
983index 0000000000000000000000000000000000000000..efecca2c22f09099d78348c694cede8d28467229
984--- /dev/null
985+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test.mk
986@@ -0,0 +1,18 @@
987+# Copyright 2021 Stefan Kerkmann
988+#
989+# This program is free software: you can redistribute it and/or modify
990+# it under the terms of the GNU General Public License as published by
991+# the Free Software Foundation, either version 2 of the License, or
992+# (at your option) any later version.
993+#
994+# This program is distributed in the hope that it will be useful,
995+# but WITHOUT ANY WARRANTY; without even the implied warranty of
996+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
997+# GNU General Public License for more details.
998+#
999+# You should have received a copy of the GNU General Public License
1000+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1001+
1002+# --------------------------------------------------------------------------------
1003+# Keep this file, even if it is empty, as a marker that this folder contains tests
1004+# --------------------------------------------------------------------------------
1005diff --git a/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp
1006new file mode 100644
1007index 0000000000000000000000000000000000000000..1702d604d319e1ea9d6d0a4359d7ca15352a3019
1008--- /dev/null
1009+++ b/tests/tap_hold_configurations/ignore_mod_tap_interrupt/test_tap_hold.cpp
1010@@ -0,0 +1,136 @@
1011+/* Copyright 2021 Stefan Kerkmann
1012+ *
1013+ * This program is free software: you can redistribute it and/or modify
1014+ * it under the terms of the GNU General Public License as published by
1015+ * the Free Software Foundation, either version 2 of the License, or
1016+ * (at your option) any later version.
1017+ *
1018+ * This program is distributed in the hope that it will be useful,
1019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1021+ * GNU General Public License for more details.
1022+ *
1023+ * You should have received a copy of the GNU General Public License
1024+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1025+ */
1026+
1027+#include "keyboard_report_util.hpp"
1028+#include "keycode.h"
1029+#include "test_common.hpp"
1030+#include "action_tapping.h"
1031+#include "test_fixture.hpp"
1032+#include "test_keymap_key.hpp"
1033+
1034+using testing::_;
1035+using testing::InSequence;
1036+
1037+class IgnoreModTapInterrupt : public TestFixture {};
1038+
1039+TEST_F(IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) {
1040+ TestDriver driver;
1041+ InSequence s;
1042+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1043+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
1044+
1045+ set_keymap({mod_tap_hold_key, regular_key});
1046+
1047+ /* Press mod-tap-hold key */
1048+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1049+ mod_tap_hold_key.press();
1050+ run_one_scan_loop();
1051+ testing::Mock::VerifyAndClearExpectations(&driver);
1052+
1053+ /* Press regular key */
1054+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1055+ regular_key.press();
1056+ run_one_scan_loop();
1057+ testing::Mock::VerifyAndClearExpectations(&driver);
1058+
1059+ /* Release regular key */
1060+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1061+ regular_key.release();
1062+ run_one_scan_loop();
1063+ testing::Mock::VerifyAndClearExpectations(&driver);
1064+
1065+ /* Release mod-tap-hold key */
1066+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1067+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
1068+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1069+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1070+ mod_tap_hold_key.release();
1071+ run_one_scan_loop();
1072+ testing::Mock::VerifyAndClearExpectations(&driver);
1073+}
1074+
1075+TEST_F(IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) {
1076+ TestDriver driver;
1077+ InSequence s;
1078+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1079+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
1080+
1081+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
1082+
1083+ /* Press first mod-tap-hold key */
1084+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1085+ first_mod_tap_hold_key.press();
1086+ run_one_scan_loop();
1087+ testing::Mock::VerifyAndClearExpectations(&driver);
1088+
1089+ /* Press second tap-hold key */
1090+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1091+ second_mod_tap_hold_key.press();
1092+ run_one_scan_loop();
1093+ testing::Mock::VerifyAndClearExpectations(&driver);
1094+
1095+ /* Release second tap-hold key */
1096+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1097+ second_mod_tap_hold_key.release();
1098+ run_one_scan_loop();
1099+ testing::Mock::VerifyAndClearExpectations(&driver);
1100+
1101+ /* Release first mod-tap-hold key */
1102+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1103+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A, KC_P)));
1104+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1105+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1106+ first_mod_tap_hold_key.release();
1107+ run_one_scan_loop();
1108+ testing::Mock::VerifyAndClearExpectations(&driver);
1109+}
1110diff --git a/tests/tap_hold_configurations/permissive_hold/config.h b/tests/tap_hold_configurations/permissive_hold/config.h
1111new file mode 100644
1112index 0000000000000000000000000000000000000000..2d5a9849e7d7c72a68542b3905b3c2a037f3d25f
1113--- /dev/null
1114+++ b/tests/tap_hold_configurations/permissive_hold/config.h
1115@@ -0,0 +1,21 @@
1116+/* Copyright 2021 Stefan Kerkmann
1117+ *
1118+ * This program is free software: you can redistribute it and/or modify
1119+ * it under the terms of the GNU General Public License as published by
1120+ * the Free Software Foundation, either version 2 of the License, or
1121+ * (at your option) any later version.
1122+ *
1123+ * This program is distributed in the hope that it will be useful,
1124+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1125+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1126+ * GNU General Public License for more details.
1127+ *
1128+ * You should have received a copy of the GNU General Public License
1129+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1130+ */
1131+
1132+#pragma once
1133+
1134+#include "test_common.h"
1135+
1136+#define PERMISSIVE_HOLD
1137diff --git a/tests/tap_hold_configurations/permissive_hold/test.mk b/tests/tap_hold_configurations/permissive_hold/test.mk
1138new file mode 100644
1139index 0000000000000000000000000000000000000000..efecca2c22f09099d78348c694cede8d28467229
1140--- /dev/null
1141+++ b/tests/tap_hold_configurations/permissive_hold/test.mk
1142@@ -0,0 +1,18 @@
1143+# Copyright 2021 Stefan Kerkmann
1144+#
1145+# This program is free software: you can redistribute it and/or modify
1146+# it under the terms of the GNU General Public License as published by
1147+# the Free Software Foundation, either version 2 of the License, or
1148+# (at your option) any later version.
1149+#
1150+# This program is distributed in the hope that it will be useful,
1151+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1152+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1153+# GNU General Public License for more details.
1154+#
1155+# You should have received a copy of the GNU General Public License
1156+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1157+
1158+# --------------------------------------------------------------------------------
1159+# Keep this file, even if it is empty, as a marker that this folder contains tests
1160+# --------------------------------------------------------------------------------
1161diff --git a/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp
1162new file mode 100644
1163index 0000000000000000000000000000000000000000..aa71ec397f8af136a618a616243830471de37b9b
1164--- /dev/null
1165+++ b/tests/tap_hold_configurations/permissive_hold/test_one_shot_keys.cpp
1166@@ -0,0 +1,76 @@
1167+/* Copyright 2021 Stefan Kerkmann
1168+ *
1169+ * This program is free software: you can redistribute it and/or modify
1170+ * it under the terms of the GNU General Public License as published by
1171+ * the Free Software Foundation, either version 2 of the License, or
1172+ * (at your option) any later version.
1173+ *
1174+ * This program is distributed in the hope that it will be useful,
1175+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1176+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1177+ * GNU General Public License for more details.
1178+ *
1179+ * You should have received a copy of the GNU General Public License
1180+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1181+ */
1182+
1183+#include "action_util.h"
1184+#include "keyboard_report_util.hpp"
1185+#include "test_common.hpp"
1186+
1187+using testing::_;
1188+using testing::InSequence;
1189+
1190+class OneShot : public TestFixture {};
1191+class OneShotParametrizedTestFixture : public ::testing::WithParamInterface<std::pair<KeymapKey, KeymapKey>>, public OneShot {};
1192+
1193+TEST_P(OneShotParametrizedTestFixture, OSMAsRegularModifierWithAdditionalKeypress) {
1194+ TestDriver driver;
1195+ KeymapKey osm_key = GetParam().first;
1196+ KeymapKey regular_key = GetParam().second;
1197+
1198+ set_keymap({osm_key, regular_key});
1199+
1200+ /* Press OSM */
1201+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1202+ osm_key.press();
1203+ run_one_scan_loop();
1204+ testing::Mock::VerifyAndClearExpectations(&driver);
1205+
1206+ /* Press regular key */
1207+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1208+ regular_key.press();
1209+ run_one_scan_loop();
1210+ testing::Mock::VerifyAndClearExpectations(&driver);
1211+
1212+ /* Release regular key */
1213+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(osm_key.report_code))).Times(2);
1214+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(regular_key.report_code, osm_key.report_code))).Times(1);
1215+ regular_key.release();
1216+ run_one_scan_loop();
1217+ testing::Mock::VerifyAndClearExpectations(&driver);
1218+
1219+ /* Release OSM */
1220+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
1221+ osm_key.release();
1222+ run_one_scan_loop();
1223+ testing::Mock::VerifyAndClearExpectations(&driver);
1224+}
1225+
1226+// clang-format off
1227+
1228+INSTANTIATE_TEST_CASE_P(
1229+ OneShotModifierTests,
1230+ OneShotParametrizedTestFixture,
1231+ ::testing::Values(
1232+ /* first is osm key, second is regular key. */
1233+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LSFT), KC_LSFT}, KeymapKey{0, 1, 1, KC_A}),
1234+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LCTL), KC_LCTL}, KeymapKey{0, 1, 1, KC_A}),
1235+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LALT), KC_LALT}, KeymapKey{0, 1, 1, KC_A}),
1236+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_LGUI), KC_LGUI}, KeymapKey{0, 1, 1, KC_A}),
1237+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RCTL), KC_RCTL}, KeymapKey{0, 1, 1, KC_A}),
1238+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RSFT), KC_RSFT}, KeymapKey{0, 1, 1, KC_A}),
1239+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RALT), KC_RALT}, KeymapKey{0, 1, 1, KC_A}),
1240+ std::make_pair(KeymapKey{0, 0, 0, OSM(MOD_RGUI), KC_RGUI}, KeymapKey{0, 1, 1, KC_A})
1241+ ));
1242+// clang-format on
1243diff --git a/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp
1244new file mode 100644
1245index 0000000000000000000000000000000000000000..ab9dd1518bb2f2efee321c7437c505a467fead49
1246--- /dev/null
1247+++ b/tests/tap_hold_configurations/permissive_hold/test_tap_hold.cpp
1248@@ -0,0 +1,132 @@
1249+/* Copyright 2021 Stefan Kerkmann
1250+ *
1251+ * This program is free software: you can redistribute it and/or modify
1252+ * it under the terms of the GNU General Public License as published by
1253+ * the Free Software Foundation, either version 2 of the License, or
1254+ * (at your option) any later version.
1255+ *
1256+ * This program is distributed in the hope that it will be useful,
1257+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1258+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1259+ * GNU General Public License for more details.
1260+ *
1261+ * You should have received a copy of the GNU General Public License
1262+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1263+ */
1264+
1265+#include "keyboard_report_util.hpp"
1266+#include "keycode.h"
1267+#include "test_common.hpp"
1268+#include "action_tapping.h"
1269+#include "test_fixture.hpp"
1270+#include "test_keymap_key.hpp"
1271+
1272+using testing::_;
1273+using testing::InSequence;
1274+class PermissiveHold : public TestFixture {};
1275+
1276+TEST_F(PermissiveHold, tap_regular_key_while_mod_tap_key_is_held) {
1277+ TestDriver driver;
1278+ InSequence s;
1279+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1280+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
1281+
1282+ set_keymap({mod_tap_hold_key, regular_key});
1283+
1284+ /* Press mod-tap-hold key */
1285+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1286+ mod_tap_hold_key.press();
1287+ run_one_scan_loop();
1288+ testing::Mock::VerifyAndClearExpectations(&driver);
1289+
1290+ /* Press regular key */
1291+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1292+ regular_key.press();
1293+ run_one_scan_loop();
1294+ testing::Mock::VerifyAndClearExpectations(&driver);
1295+
1296+ /* Release regular key */
1297+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
1298+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, regular_key.report_code)));
1299+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
1300+ regular_key.release();
1301+ run_one_scan_loop();
1302+ testing::Mock::VerifyAndClearExpectations(&driver);
1303+
1304+ /* Release mod-tap-hold key */
1305+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1306+ mod_tap_hold_key.release();
1307+ run_one_scan_loop();
1308+ testing::Mock::VerifyAndClearExpectations(&driver);
1309+}
1310+
1311+TEST_F(PermissiveHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
1312+ TestDriver driver;
1313+ InSequence s;
1314+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1315+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
1316+
1317+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
1318+
1319+ /* Press first mod-tap-hold key */
1320+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1321+ first_mod_tap_hold_key.press();
1322+ run_one_scan_loop();
1323+ testing::Mock::VerifyAndClearExpectations(&driver);
1324+
1325+ /* Press second mod-tap-hold key */
1326+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1327+ second_mod_tap_hold_key.press();
1328+ run_one_scan_loop();
1329+ testing::Mock::VerifyAndClearExpectations(&driver);
1330+
1331+ /* Release second mod-tap-hold key */
1332+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
1333+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT, second_mod_tap_hold_key.report_code)));
1334+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
1335+ second_mod_tap_hold_key.release();
1336+ run_one_scan_loop();
1337+ testing::Mock::VerifyAndClearExpectations(&driver);
1338+
1339+ /* Release first mod-tap-hold key */
1340+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1341+ first_mod_tap_hold_key.release();
1342+ run_one_scan_loop();
1343+ testing::Mock::VerifyAndClearExpectations(&driver);
1344+}
1345+
1346+TEST_F(PermissiveHold, tap_regular_key_while_layer_tap_key_is_held) {
1347+ TestDriver driver;
1348diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h
1349new file mode 100644
1350index 0000000000000000000000000000000000000000..a6abd50bbee792c480fefcbf1e015c84231a7540
1351--- /dev/null
1352+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/config.h
1353@@ -0,0 +1,22 @@
1354+/* Copyright 2021 Stefan Kerkmann
1355+ *
1356+ * This program is free software: you can redistribute it and/or modify
1357+ * it under the terms of the GNU General Public License as published by
1358+ * the Free Software Foundation, either version 2 of the License, or
1359+ * (at your option) any later version.
1360+ *
1361+ * This program is distributed in the hope that it will be useful,
1362+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1363+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1364+ * GNU General Public License for more details.
1365+ *
1366+ * You should have received a copy of the GNU General Public License
1367+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1368+ */
1369+
1370+#pragma once
1371+
1372+#include "test_common.h"
1373+
1374+#define IGNORE_MOD_TAP_INTERRUPT
1375+#define PERMISSIVE_HOLD
1376diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk
1377new file mode 100644
1378index 0000000000000000000000000000000000000000..efecca2c22f09099d78348c694cede8d28467229
1379--- /dev/null
1380+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test.mk
1381@@ -0,0 +1,18 @@
1382+# Copyright 2021 Stefan Kerkmann
1383+#
1384+# This program is free software: you can redistribute it and/or modify
1385+# it under the terms of the GNU General Public License as published by
1386+# the Free Software Foundation, either version 2 of the License, or
1387+# (at your option) any later version.
1388+#
1389+# This program is distributed in the hope that it will be useful,
1390+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1391+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1392+# GNU General Public License for more details.
1393+#
1394+# You should have received a copy of the GNU General Public License
1395+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1396+
1397+# --------------------------------------------------------------------------------
1398+# Keep this file, even if it is empty, as a marker that this folder contains tests
1399+# --------------------------------------------------------------------------------
1400diff --git a/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp
1401new file mode 100644
1402index 0000000000000000000000000000000000000000..67f394653f3a76964d5d0ce8c9fb71865b4cb642
1403--- /dev/null
1404+++ b/tests/tap_hold_configurations/permissive_hold_ignore_mod_tap_interrupt/test_tap_hold.cpp
1405@@ -0,0 +1,134 @@
1406+
1407+/* Copyright 2021 Stefan Kerkmann
1408+ *
1409+ * This program is free software: you can redistribute it and/or modify
1410+ * it under the terms of the GNU General Public License as published by
1411+ * the Free Software Foundation, either version 2 of the License, or
1412+ * (at your option) any later version.
1413+ *
1414+ * This program is distributed in the hope that it will be useful,
1415+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1416+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1417+ * GNU General Public License for more details.
1418+ *
1419+ * You should have received a copy of the GNU General Public License
1420+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1421+ */
1422+
1423+#include "keyboard_report_util.hpp"
1424+#include "keycode.h"
1425+#include "test_common.hpp"
1426+#include "action_tapping.h"
1427+#include "test_fixture.hpp"
1428+#include "test_keymap_key.hpp"
1429+
1430+using testing::_;
1431+using testing::InSequence;
1432+
1433+class PermissiveHold_IgnoreModTapInterrupt : public TestFixture {};
1434+
1435+TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_regular_key_while_mod_tap_key_is_held) {
1436+ TestDriver driver;
1437+ InSequence s;
1438+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1439+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
1440+
1441+ set_keymap({mod_tap_hold_key, regular_key});
1442+
1443+ /* Press mod-tap-hold key */
1444+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1445+ mod_tap_hold_key.press();
1446+ run_one_scan_loop();
1447+ testing::Mock::VerifyAndClearExpectations(&driver);
1448+
1449+ /* Press regular key */
1450+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1451+ regular_key.press();
1452+ run_one_scan_loop();
1453+ testing::Mock::VerifyAndClearExpectations(&driver);
1454+
1455+ /* Release regular key */
1456+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1457+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
1458+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1459+ regular_key.release();
1460+ run_one_scan_loop();
1461+ testing::Mock::VerifyAndClearExpectations(&driver);
1462+
1463+ /* Release mod-tap-hold key */
1464+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1465+ mod_tap_hold_key.release();
1466+ run_one_scan_loop();
1467+ testing::Mock::VerifyAndClearExpectations(&driver);
1468+}
1469+
1470+TEST_F(PermissiveHold_IgnoreModTapInterrupt, tap_mod_tap_key_while_mod_tap_key_is_held) {
1471+ TestDriver driver;
1472+ InSequence s;
1473+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1474+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
1475+
1476+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
1477+
1478+ /* Press first mod-tap-hold key */
1479+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1480+ first_mod_tap_hold_key.press();
1481+ run_one_scan_loop();
1482+ testing::Mock::VerifyAndClearExpectations(&driver);
1483+
1484+ /* Press second tap-hold key */
1485+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1486+ second_mod_tap_hold_key.press();
1487+ run_one_scan_loop();
1488+ testing::Mock::VerifyAndClearExpectations(&driver);
1489+
1490+ /* Release second tap-hold key */
1491+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1492+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
1493+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1494+ second_mod_tap_hold_key.release();
1495+ run_one_scan_loop();
1496+ testing::Mock::VerifyAndClearExpectations(&driver);
1497+
1498+ /* Release first mod-tap-hold key */
1499+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1500+ first_mod_tap_hold_key.release();
1501+ run_one_scan_loop();
1502+ testing::Mock::VerifyAndClearExpectations(&driver);
1503+}
1504+
1505diff --git a/tests/tap_hold_configurations/retro_tapping/config.h b/tests/tap_hold_configurations/retro_tapping/config.h
1506new file mode 100644
1507index 0000000000000000000000000000000000000000..4b38f2644b83d3df0a7deea08dd9cc5b8a5c623b
1508--- /dev/null
1509+++ b/tests/tap_hold_configurations/retro_tapping/config.h
1510@@ -0,0 +1,21 @@
1511+/* Copyright 2021 Stefan Kerkmann
1512+ *
1513+ * This program is free software: you can redistribute it and/or modify
1514+ * it under the terms of the GNU General Public License as published by
1515+ * the Free Software Foundation, either version 2 of the License, or
1516+ * (at your option) any later version.
1517+ *
1518+ * This program is distributed in the hope that it will be useful,
1519+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1520+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1521+ * GNU General Public License for more details.
1522+ *
1523+ * You should have received a copy of the GNU General Public License
1524+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1525+ */
1526+
1527+#pragma once
1528+
1529+#include "test_common.h"
1530+
1531+#define RETRO_TAPPING
1532diff --git a/tests/tap_hold_configurations/retro_tapping/test.mk b/tests/tap_hold_configurations/retro_tapping/test.mk
1533new file mode 100644
1534index 0000000000000000000000000000000000000000..efecca2c22f09099d78348c694cede8d28467229
1535--- /dev/null
1536+++ b/tests/tap_hold_configurations/retro_tapping/test.mk
1537@@ -0,0 +1,18 @@
1538+# Copyright 2021 Stefan Kerkmann
1539+#
1540+# This program is free software: you can redistribute it and/or modify
1541+# it under the terms of the GNU General Public License as published by
1542+# the Free Software Foundation, either version 2 of the License, or
1543+# (at your option) any later version.
1544+#
1545+# This program is distributed in the hope that it will be useful,
1546+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1547+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1548+# GNU General Public License for more details.
1549+#
1550+# You should have received a copy of the GNU General Public License
1551+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1552+
1553+# --------------------------------------------------------------------------------
1554+# Keep this file, even if it is empty, as a marker that this folder contains tests
1555+# --------------------------------------------------------------------------------
1556diff --git a/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp
1557new file mode 100644
1558index 0000000000000000000000000000000000000000..59ae77f78119ad329201c2592bf4147b47b50a7a
1559--- /dev/null
1560+++ b/tests/tap_hold_configurations/retro_tapping/test_tap_hold.cpp
1561@@ -0,0 +1,52 @@
1562+
1563+/* Copyright 2021 Stefan Kerkmann
1564+ *
1565+ * This program is free software: you can redistribute it and/or modify
1566+ * it under the terms of the GNU General Public License as published by
1567+ * the Free Software Foundation, either version 2 of the License, or
1568+ * (at your option) any later version.
1569+ *
1570+ * This program is distributed in the hope that it will be useful,
1571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1573+ * GNU General Public License for more details.
1574+ *
1575+ * You should have received a copy of the GNU General Public License
1576+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1577+ */
1578+
1579+#include "keyboard_report_util.hpp"
1580+#include "keycode.h"
1581+#include "test_common.hpp"
1582+#include "action_tapping.h"
1583+#include "test_fixture.hpp"
1584+#include "test_keymap_key.hpp"
1585+
1586+using testing::_;
1587+using testing::InSequence;
1588+
1589+class RetroTapping : public TestFixture {};
1590+
1591+TEST_F(RetroTapping, tap_and_hold_mod_tap_hold_key) {
1592+ TestDriver driver;
1593+ InSequence s;
1594+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1595+
1596+ set_keymap({mod_tap_hold_key});
1597+
1598+ /* Press mod-tap-hold key. */
1599+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1600+ mod_tap_hold_key.press();
1601+ idle_for(TAPPING_TERM);
1602+ testing::Mock::VerifyAndClearExpectations(&driver);
1603+
1604+ /* Release mod-tap-hold key. */
1605+ /* TODO: Why is LSHIFT send at all? */
1606+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSHIFT)));
1607+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1608+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1609+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1610+ mod_tap_hold_key.release();
1611+ run_one_scan_loop();
1612+ testing::Mock::VerifyAndClearExpectations(&driver);
1613+}
1614diff --git a/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp
1615new file mode 100644
1616index 0000000000000000000000000000000000000000..cf23df8317186a010549dc82a44657372cb89f2c
1617--- /dev/null
1618+++ b/tests/tap_hold_configurations/retro_tapping/test_tapping.cpp
1619@@ -0,0 +1,112 @@
1620+/* Copyright 2021 Stefan Kerkmann
1621+ *
1622+ * This program is free software: you can redistribute it and/or modify
1623+ * it under the terms of the GNU General Public License as published by
1624+ * the Free Software Foundation, either version 2 of the License, or
1625+ * (at your option) any later version.
1626+ *
1627+ * This program is distributed in the hope that it will be useful,
1628+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1629+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1630+ * GNU General Public License for more details.
1631+ *
1632+ * You should have received a copy of the GNU General Public License
1633+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1634+ */
1635+
1636+#include "keyboard_report_util.hpp"
1637+#include "keycode.h"
1638+#include "test_common.hpp"
1639+#include "action_tapping.h"
1640+#include "test_keymap_key.hpp"
1641+
1642+using testing::_;
1643+using testing::InSequence;
1644+
1645+class Tapping : public TestFixture {};
1646+
1647+TEST_F(Tapping, HoldA_SHFT_T_KeyReportsShift) {
1648+ TestDriver driver;
1649+ InSequence s;
1650+ auto mod_tap_hold_key = KeymapKey(0, 7, 0, SFT_T(KC_P));
1651+
1652+ set_keymap({mod_tap_hold_key});
1653+
1654+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1655+ mod_tap_hold_key.press();
1656+ idle_for(TAPPING_TERM);
1657+ testing::Mock::VerifyAndClearExpectations(&driver);
1658+
1659+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1660+ run_one_scan_loop();
1661+ testing::Mock::VerifyAndClearExpectations(&driver);
1662+
1663+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1664+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1665+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1666+ mod_tap_hold_key.release();
1667+ run_one_scan_loop();
1668+ testing::Mock::VerifyAndClearExpectations(&driver);
1669+}
1670+
1671+TEST_F(Tapping, ANewTapWithinTappingTermIsBuggy) {
1672+ TestDriver driver;
1673+ InSequence s;
1674+ auto key_shift_hold_p_tap = KeymapKey(0, 7, 0, SFT_T(KC_P));
1675+
1676+ set_keymap({key_shift_hold_p_tap});
1677+
1678+ /* Press mod_tap_hold key */
1679+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1680+ key_shift_hold_p_tap.press();
1681+ run_one_scan_loop();
1682+ testing::Mock::VerifyAndClearExpectations(&driver);
1683+
1684+ /* Release mod_tap_hold key */
1685+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1686+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1687+ key_shift_hold_p_tap.release();
1688+ run_one_scan_loop();
1689+ testing::Mock::VerifyAndClearExpectations(&driver);
1690+
1691+ /* Press mod_tap_hold key again */
1692+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1693+ key_shift_hold_p_tap.press();
1694+ run_one_scan_loop();
1695+ testing::Mock::VerifyAndClearExpectations(&driver);
1696+
1697+ /* Release mod_tap_hold key again */
1698+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1699+ key_shift_hold_p_tap.release();
1700+ idle_for(TAPPING_TERM + 1);
1701+ testing::Mock::VerifyAndClearExpectations(&driver);
1702+
1703+ /* Press mod_tap_hold key again */
1704+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1705+ key_shift_hold_p_tap.press();
1706+ run_one_scan_loop();
1707+ testing::Mock::VerifyAndClearExpectations(&driver);
1708+
1709+ /* Release mod_tap_hold key again */
1710+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_P)));
1711+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1712+ key_shift_hold_p_tap.release();
1713+ idle_for(TAPPING_TERM + 1);
1714+ testing::Mock::VerifyAndClearExpectations(&driver);
1715+
1716+ /* Press mod_tap_hold key again */
1717+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1718+ key_shift_hold_p_tap.press();
1719diff --git a/tests/tap_hold_configurations/tapping_force_hold/config.h b/tests/tap_hold_configurations/tapping_force_hold/config.h
1720new file mode 100644
1721index 0000000000000000000000000000000000000000..3b4646338a3054aa404da289b7c4c68baa855488
1722--- /dev/null
1723+++ b/tests/tap_hold_configurations/tapping_force_hold/config.h
1724@@ -0,0 +1,21 @@
1725+/* Copyright 2021 Stefan Kerkmann
1726+ *
1727+ * This program is free software: you can redistribute it and/or modify
1728+ * it under the terms of the GNU General Public License as published by
1729+ * the Free Software Foundation, either version 2 of the License, or
1730+ * (at your option) any later version.
1731+ *
1732+ * This program is distributed in the hope that it will be useful,
1733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1735+ * GNU General Public License for more details.
1736+ *
1737+ * You should have received a copy of the GNU General Public License
1738+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1739+ */
1740+
1741+#pragma once
1742+
1743+#include "test_common.h"
1744+
1745+#define TAPPING_FORCE_HOLD
1746diff --git a/tests/tap_hold_configurations/tapping_force_hold/test.mk b/tests/tap_hold_configurations/tapping_force_hold/test.mk
1747new file mode 100644
1748index 0000000000000000000000000000000000000000..efecca2c22f09099d78348c694cede8d28467229
1749--- /dev/null
1750+++ b/tests/tap_hold_configurations/tapping_force_hold/test.mk
1751@@ -0,0 +1,18 @@
1752+# Copyright 2021 Stefan Kerkmann
1753+#
1754+# This program is free software: you can redistribute it and/or modify
1755+# it under the terms of the GNU General Public License as published by
1756+# the Free Software Foundation, either version 2 of the License, or
1757+# (at your option) any later version.
1758+#
1759+# This program is distributed in the hope that it will be useful,
1760+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1761+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1762+# GNU General Public License for more details.
1763+#
1764+# You should have received a copy of the GNU General Public License
1765+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1766+
1767+# --------------------------------------------------------------------------------
1768+# Keep this file, even if it is empty, as a marker that this folder contains tests
1769+# --------------------------------------------------------------------------------
1770diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp
1771new file mode 100644
1772index 0000000000000000000000000000000000000000..02416eed7365f18302c2eac201c8ff6f07f19a2a
1773--- /dev/null
1774+++ b/tests/tap_hold_configurations/tapping_force_hold/test_action_layer.cpp
1775@@ -0,0 +1,81 @@
1776+/* Copyright 2021 Stefan Kerkmann
1777+ *
1778+ * This program is free software: you can redistribute it and/or modify
1779+ * it under the terms of the GNU General Public License as published by
1780+ * the Free Software Foundation, either version 2 of the License, or
1781+ * (at your option) any later version.
1782+ *
1783+ * This program is distributed in the hope that it will be useful,
1784+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1785+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1786+ * GNU General Public License for more details.
1787+ *
1788+ * You should have received a copy of the GNU General Public License
1789+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1790+ */
1791+
1792+#include "keyboard_report_util.hpp"
1793+#include "test_common.hpp"
1794+
1795+using testing::_;
1796+using testing::InSequence;
1797+
1798+class ActionLayer : public TestFixture {};
1799+
1800+TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) {
1801+ TestDriver driver;
1802+ KeymapKey layer_key = KeymapKey{0, 0, 0, TT(1)};
1803+
1804+ /* These keys must have the same position in the matrix, only the layer is different. */
1805+ KeymapKey regular_key = KeymapKey{0, 1, 0, KC_A};
1806+ set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});
1807+
1808+ /* Tap TT five times . */
1809+ /* TODO: QMK currently sends an empty report even if nothing needs to be reported to the host! */
1810+ /* TODO: Tapping Force Hold breaks TT */
1811+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(10);
1812+
1813+ layer_key.press();
1814+ run_one_scan_loop();
1815+ layer_key.release();
1816+ run_one_scan_loop();
1817+ expect_layer_state(0);
1818+
1819+ layer_key.press();
1820+ run_one_scan_loop();
1821+ layer_key.release();
1822+ run_one_scan_loop();
1823+ expect_layer_state(0);
1824+
1825+ layer_key.press();
1826+ run_one_scan_loop();
1827+ layer_key.release();
1828+ run_one_scan_loop();
1829+ expect_layer_state(0);
1830+
1831+ layer_key.press();
1832+ run_one_scan_loop();
1833+ layer_key.release();
1834+ run_one_scan_loop();
1835+ expect_layer_state(0);
1836+
1837+ layer_key.press();
1838+ run_one_scan_loop();
1839+ layer_key.release();
1840+ run_one_scan_loop();
1841+ expect_layer_state(0);
1842+
1843+ testing::Mock::VerifyAndClearExpectations(&driver);
1844+
1845+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A))).Times(1);
1846+ regular_key.press();
1847+ run_one_scan_loop();
1848+ expect_layer_state(0);
1849+ testing::Mock::VerifyAndClearExpectations(&driver);
1850+
1851+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
1852+ regular_key.release();
1853+ run_one_scan_loop();
1854+ expect_layer_state(0);
1855+ testing::Mock::VerifyAndClearExpectations(&driver);
1856+}
1857diff --git a/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp
1858new file mode 100644
1859index 0000000000000000000000000000000000000000..cb6842961724dca048652e0a4c283d7dcf42c38b
1860--- /dev/null
1861+++ b/tests/tap_hold_configurations/tapping_force_hold/test_tap_hold.cpp
1862@@ -0,0 +1,215 @@
1863+
1864+/* Copyright 2021 Stefan Kerkmann
1865+ *
1866+ * This program is free software: you can redistribute it and/or modify
1867+ * it under the terms of the GNU General Public License as published by
1868+ * the Free Software Foundation, either version 2 of the License, or
1869+ * (at your option) any later version.
1870+ *
1871+ * This program is distributed in the hope that it will be useful,
1872+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1873+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1874+ * GNU General Public License for more details.
1875+ *
1876+ * You should have received a copy of the GNU General Public License
1877+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1878+ */
1879+
1880+#include "keyboard_report_util.hpp"
1881+#include "keycode.h"
1882+#include "test_common.hpp"
1883+#include "action_tapping.h"
1884+#include "test_fixture.hpp"
1885+#include "test_keymap_key.hpp"
1886+
1887+using testing::_;
1888+using testing::InSequence;
1889+
1890+class TappingForceHold : public TestFixture {};
1891+
1892+TEST_F(TappingForceHold, tap_regular_key_while_mod_tap_key_is_held) {
1893+ TestDriver driver;
1894+ InSequence s;
1895+ auto mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1896+ auto regular_key = KeymapKey(0, 2, 0, KC_A);
1897+
1898+ set_keymap({mod_tap_hold_key, regular_key});
1899+
1900+ /* Press mod-tap-hold key. */
1901+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1902+ mod_tap_hold_key.press();
1903+ run_one_scan_loop();
1904+ testing::Mock::VerifyAndClearExpectations(&driver);
1905+
1906+ /* Press regular key. */
1907+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1908+ regular_key.press();
1909+ run_one_scan_loop();
1910+ testing::Mock::VerifyAndClearExpectations(&driver);
1911+
1912+ /* Release regular key. */
1913+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1914+ regular_key.release();
1915+ run_one_scan_loop();
1916+ testing::Mock::VerifyAndClearExpectations(&driver);
1917+
1918+ /* Release mod-tap-hold key. */
1919+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1920+ mod_tap_hold_key.release();
1921+ run_one_scan_loop();
1922+ testing::Mock::VerifyAndClearExpectations(&driver);
1923+
1924+ /* Idle for tapping term of mod tap hold key. */
1925+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1926+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
1927+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1928+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
1929+ idle_for(TAPPING_TERM - 3);
1930+ testing::Mock::VerifyAndClearExpectations(&driver);
1931+}
1932+
1933+TEST_F(TappingForceHold, tap_mod_tap_key_while_mod_tap_key_is_held) {
1934+ TestDriver driver;
1935+ InSequence s;
1936+ auto first_mod_tap_hold_key = KeymapKey(0, 1, 0, SFT_T(KC_P));
1937+ auto second_mod_tap_hold_key = KeymapKey(0, 2, 0, RSFT_T(KC_A));
1938+
1939+ set_keymap({first_mod_tap_hold_key, second_mod_tap_hold_key});
1940+
1941+ /* Press first mod-tap-hold key */
1942+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1943+ first_mod_tap_hold_key.press();
1944+ run_one_scan_loop();
1945+ testing::Mock::VerifyAndClearExpectations(&driver);
1946+
1947+ /* Press second tap-hold key */
1948+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1949+ second_mod_tap_hold_key.press();
1950+ run_one_scan_loop();
1951+ testing::Mock::VerifyAndClearExpectations(&driver);
1952+
1953+ /* Release second tap-hold key */
1954+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
1955+ second_mod_tap_hold_key.release();
1956+ run_one_scan_loop();
1957+ testing::Mock::VerifyAndClearExpectations(&driver);
1958+
1959+ /* Release first mod-tap-hold key */
1960+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
1961+ first_mod_tap_hold_key.release();
1962diff --git a/tests/basic/rules.mk b/tests/test_common/build.mk
1963rename from tests/basic/rules.mk
1964rename to tests/test_common/build.mk
1965index 9fb5d436109604765e9f0d930f61f307705f4008..aeb30578549a2205ee695f7ec64349a206343564 100644
1966--- a/tests/basic/rules.mk
1967+++ b/tests/test_common/build.mk
1968@@ -1,4 +1,4 @@
1969-# Copyright 2017 Fred Sundvik
1970+# Copyright 2021 Stefan Kerkmann
1971 #
1972 # This program is free software: you can redistribute it and/or modify
1973 # it under the terms of the GNU General Public License as published by
1974@@ -13,4 +13,4 @@
1975 # You should have received a copy of the GNU General Public License
1976 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1977
1978-CUSTOM_MATRIX=yes
1979+CUSTOM_MATRIX=yes
1980diff --git a/tests/test_common/keyboard_report_util.cpp b/tests/test_common/keyboard_report_util.cpp
1981index f73cf239e0505c5102d1b4c5e06830e34a1abf42..e148c76beb7ed8e5a9f6b85990db478575f32ecb 100644
1982--- a/tests/test_common/keyboard_report_util.cpp
1983+++ b/tests/test_common/keyboard_report_util.cpp
1984@@ -44,16 +44,21 @@ bool operator==(const report_keyboard_t& lhs, const report_keyboard_t& rhs) {
1985 return lhs.mods == rhs.mods && lhskeys == rhskeys;
1986 }
1987
1988-std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& value) {
1989- stream << "Keyboard report:" << std::endl;
1990- stream << "Mods: " << (uint32_t)value.mods << std::endl;
1991- stream << "Keys: ";
1992+std::ostream& operator<<(std::ostream& stream, const report_keyboard_t& report) {
1993+ auto keys = get_keys(report);
1994+
1995 // TODO: This should probably print friendly names for the keys
1996- for (uint32_t k : get_keys(value)) {
1997- stream << k << " ";
1998+ stream << "Keyboard Report: Mods (" << (uint32_t)report.mods << ") Keys (";
1999+
2000+ for (auto key = keys.cbegin(); key != keys.cend();) {
2001+ stream << +(*key);
2002+ key++;
2003+ if (key != keys.cend()) {
2004+ stream << ",";
2005+ }
2006 }
2007- stream << std::endl;
2008- return stream;
2009+
2010+ return stream << ")" << std::endl;
2011 }
2012
2013 KeyboardReportMatcher::KeyboardReportMatcher(const std::vector<uint8_t>& keys) {
2014diff --git a/tests/test_common/keymap.c b/tests/test_common/keymap.c
2015new file mode 100644
2016index 0000000000000000000000000000000000000000..fc3a56a0073f34ad12762f59dadfaa810cec8a39
2017--- /dev/null
2018+++ b/tests/test_common/keymap.c
2019@@ -0,0 +1,33 @@
2020+/* Copyright 2017 Fred Sundvik
2021+ *
2022+ * This program is free software: you can redistribute it and/or modify
2023+ * it under the terms of the GNU General Public License as published by
2024+ * the Free Software Foundation, either version 2 of the License, or
2025+ * (at your option) any later version.
2026+ *
2027+ * This program is distributed in the hope that it will be useful,
2028+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2029+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2030+ * GNU General Public License for more details.
2031+ *
2032+ * You should have received a copy of the GNU General Public License
2033+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2034+ */
2035+
2036+#include "quantum.h"
2037+
2038+// clang-format off
2039+
2040+const uint16_t PROGMEM
2041+ keymaps[][MATRIX_ROWS][MATRIX_COLS] =
2042+ {
2043+ [0] =
2044+ {
2045+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
2046+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
2047+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
2048+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
2049+ },
2050+};
2051+
2052+// clang-format on
2053diff --git a/tests/test_common/test_common.h b/tests/test_common/test_common.h
2054new file mode 100644
2055index 0000000000000000000000000000000000000000..19ffcddceaec2cc3caf34ec5f9f647818e7b7caa
2056--- /dev/null
2057+++ b/tests/test_common/test_common.h
2058@@ -0,0 +1,4 @@
2059+#pragma once
2060+
2061+#define MATRIX_ROWS 4
2062+#define MATRIX_COLS 10
2063diff --git a/tests/test_common/test_driver.cpp b/tests/test_common/test_driver.cpp
2064index 84e249d838e523b016bccdb60bf3c888d7eb5975..2fa2b6a2e791a28b83307ca2af77c7fd1ae0603b 100644
2065--- a/tests/test_common/test_driver.cpp
2066+++ b/tests/test_common/test_driver.cpp
2067@@ -27,7 +27,10 @@ TestDriver::~TestDriver() { m_this = nullptr; }
2068
2069 uint8_t TestDriver::keyboard_leds(void) { return m_this->m_leds; }
2070
2071-void TestDriver::send_keyboard(report_keyboard_t* report) { m_this->send_keyboard_mock(*report); }
2072+void TestDriver::send_keyboard(report_keyboard_t* report) {
2073+ test_logger.trace() << *report;
2074+ m_this->send_keyboard_mock(*report);
2075+}
2076
2077 void TestDriver::send_mouse(report_mouse_t* report) { m_this->send_mouse_mock(*report); }
2078
2079diff --git a/tests/test_common/test_driver.hpp b/tests/test_common/test_driver.hpp
2080index f86308df95e1f9f7a1595d3f8a2f8d92a4dcecc6..f9197b3634b0cbf0e4db82809ea39c55f476df15 100644
2081--- a/tests/test_common/test_driver.hpp
2082+++ b/tests/test_common/test_driver.hpp
2083@@ -20,25 +20,26 @@
2084 #include <stdint.h>
2085 #include "host.h"
2086 #include "keyboard_report_util.hpp"
2087-
2088+#include "test_logger.hpp"
2089
2090 class TestDriver {
2091-public:
2092+ public:
2093 TestDriver();
2094 ~TestDriver();
2095 void set_leds(uint8_t leds) { m_leds = leds; }
2096
2097- MOCK_METHOD1(send_keyboard_mock, void (report_keyboard_t&));
2098- MOCK_METHOD1(send_mouse_mock, void (report_mouse_t&));
2099- MOCK_METHOD1(send_system_mock, void (uint16_t));
2100- MOCK_METHOD1(send_consumer_mock, void (uint16_t));
2101-private:
2102- static uint8_t keyboard_leds(void);
2103- static void send_keyboard(report_keyboard_t *report);
2104- static void send_mouse(report_mouse_t* report);
2105- static void send_system(uint16_t data);
2106- static void send_consumer(uint16_t data);
2107- host_driver_t m_driver;
2108- uint8_t m_leds = 0;
2109+ MOCK_METHOD1(send_keyboard_mock, void(report_keyboard_t&));
2110+ MOCK_METHOD1(send_mouse_mock, void(report_mouse_t&));
2111+ MOCK_METHOD1(send_system_mock, void(uint16_t));
2112+ MOCK_METHOD1(send_consumer_mock, void(uint16_t));
2113+
2114+ private:
2115+ static uint8_t keyboard_leds(void);
2116+ static void send_keyboard(report_keyboard_t* report);
2117+ static void send_mouse(report_mouse_t* report);
2118+ static void send_system(uint16_t data);
2119+ static void send_consumer(uint16_t data);
2120+ host_driver_t m_driver;
2121+ uint8_t m_leds = 0;
2122 static TestDriver* m_this;
2123 };
2124diff --git a/tests/test_common/test_fixture.cpp b/tests/test_common/test_fixture.cpp
2125index e041df7128df9e59e48622ea1a4266932619c0bf..0601b171913786a5b7df045f239fc6ae73183200 100644
2126--- a/tests/test_common/test_fixture.cpp
2127+++ b/tests/test_common/test_fixture.cpp
2128@@ -1,26 +1,48 @@
2129 #include "test_fixture.hpp"
2130+#include <algorithm>
2131+#include <cstdint>
2132+#include <cstdio>
2133+#include <cstdlib>
2134+#include "gmock/gmock-cardinalities.h"
2135 #include "gmock/gmock.h"
2136+#include "gtest/gtest.h"
2137+#include "keyboard_report_util.hpp"
2138+#include "keycode.h"
2139 #include "test_driver.hpp"
2140+#include "test_logger.hpp"
2141 #include "test_matrix.h"
2142-#include "keyboard.h"
2143-#include "action.h"
2144-#include "action_tapping.h"
2145+#include "test_keymap_key.hpp"
2146
2147 extern "C" {
2148+#include "action.h"
2149+#include "action_tapping.h"
2150+#include "action_util.h"
2151+#include "action_layer.h"
2152 #include "debug.h"
2153 #include "eeconfig.h"
2154-#include "action_layer.h"
2155+#include "keyboard.h"
2156+#include "keymap.h"
2157
2158 void set_time(uint32_t t);
2159 void advance_time(uint32_t ms);
2160 }
2161
2162 using testing::_;
2163-using testing::AnyNumber;
2164-using testing::Between;
2165-using testing::Return;
2166+
2167+/* This is used for dynamic dispatching keymap_key_to_keycode calls to the current active test_fixture. */
2168+TestFixture* TestFixture::m_this = nullptr;
2169+
2170+/* Override weak QMK function to allow the usage of isolated per-test keymaps in unit-tests.
2171+ * The actual call is dynamicaly dispatched to the current active test fixture, which in turn has it's own keymap. */
2172+extern "C" uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t position) {
2173+ uint16_t keycode;
2174+ TestFixture::m_this->get_keycode(layer, position, &keycode);
2175+ return keycode;
2176+}
2177
2178 void TestFixture::SetUpTestCase() {
2179+ test_logger.info() << "TestFixture setup-up start." << std::endl;
2180+
2181 // The following is enough to bootstrap the values set in main
2182 eeconfig_init_quantum();
2183 eeconfig_update_debug(debug_config.raw);
2184@@ -28,23 +50,99 @@ void TestFixture::SetUpTestCase() {
2185 TestDriver driver;
2186 EXPECT_CALL(driver, send_keyboard_mock(_));
2187 keyboard_init();
2188+
2189+ test_logger.info() << "TestFixture setup-up end." << std::endl;
2190 }
2191
2192 void TestFixture::TearDownTestCase() {}
2193
2194-TestFixture::TestFixture() {}
2195+TestFixture::TestFixture() { m_this = this; }
2196
2197 TestFixture::~TestFixture() {
2198+ test_logger.info() << "TestFixture clean-up start." << std::endl;
2199 TestDriver driver;
2200- // Run for a while to make sure all keys are completely released
2201- EXPECT_CALL(driver, send_keyboard_mock(_)).Times(AnyNumber());
2202- layer_clear();
2203+
2204+ EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(2);
2205+
2206+ /* Reset keyboard state. */
2207 clear_all_keys();
2208- idle_for(TAPPING_TERM + 10);
2209+
2210+ clear_keyboard();
2211+
2212+ clear_oneshot_mods();
2213+ clear_oneshot_locked_mods();
2214+ reset_oneshot_layer();
2215+
2216+ layer_clear();
2217+
2218+#if defined(SWAP_HANDS_ENABLE)
2219+ clear_oneshot_swaphands();
2220+#endif
2221+
2222+ idle_for(TAPPING_TERM * 10);
2223+ testing::Mock::VerifyAndClearExpectations(&driver);
2224+
2225+ /* Verify that the matrix really is cleared */
2226+ EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
2227+ idle_for(TAPPING_TERM * 10);
2228diff --git a/tests/test_common/test_fixture.hpp b/tests/test_common/test_fixture.hpp
2229index 340503665b67f60b0bed9c38e7576b221408acba..73b5d8d3e8e53ab4cc2aacee0544b790dc7c1881 100644
2230--- a/tests/test_common/test_fixture.hpp
2231+++ b/tests/test_common/test_fixture.hpp
2232@@ -16,15 +16,34 @@
2233
2234 #pragma once
2235
2236+#include <cstdint>
2237+#include <unordered_map>
2238+#include <optional>
2239 #include "gtest/gtest.h"
2240+#include "keyboard.h"
2241+#include "test_keymap_key.hpp"
2242
2243 class TestFixture : public testing::Test {
2244-public:
2245+ public:
2246+ static TestFixture* m_this;
2247+
2248 TestFixture();
2249 ~TestFixture();
2250 static void SetUpTestCase();
2251 static void TearDownTestCase();
2252
2253+ void set_keymap(std::initializer_list<KeymapKey> keycodes);
2254+ void add_key(const KeymapKey key);
2255+
2256+ const KeymapKey* find_key(const layer_t layer_t, const keypos_t position) const;
2257+ void get_keycode(const layer_t layer, const keypos_t position, uint16_t* result) const;
2258+
2259 void run_one_scan_loop();
2260 void idle_for(unsigned ms);
2261+
2262+ void expect_layer_state(layer_t layer) const;
2263+
2264+ protected:
2265+ void print_test_log() const;
2266+ std::vector<KeymapKey> keymap;
2267 };
2268diff --git a/tests/test_common/test_keymap_key.cpp b/tests/test_common/test_keymap_key.cpp
2269new file mode 100644
2270index 0000000000000000000000000000000000000000..878ae097bfa21f7fc0b2164b2368593b3d22c736
2271--- /dev/null
2272+++ b/tests/test_common/test_keymap_key.cpp
2273@@ -0,0 +1,30 @@
2274+/* Copyright 2021 Stefan Kerkmann
2275+ *
2276+ * This program is free software: you can redistribute it and/or modify
2277+ * it under the terms of the GNU General Public License as published by
2278+ * the Free Software Foundation, either version 2 of the License, or
2279+ * (at your option) any later version.
2280+ *
2281+ * This program is distributed in the hope that it will be useful,
2282+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2283+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2284+ * GNU General Public License for more details.
2285+ *
2286+ * You should have received a copy of the GNU General Public License
2287+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2288+ */
2289+
2290+#include "test_keymap_key.hpp"
2291+#include "test_logger.hpp"
2292+#include "gtest/gtest-message.h"
2293+#include "gtest/gtest.h"
2294+
2295+void KeymapKey::press() {
2296+ test_logger.trace() << "Key pressed: (" << +this->position.col << "," << +this->position.row << ")" << std::endl;
2297+ press_key(this->position.col, this->position.row);
2298+}
2299+
2300+void KeymapKey::release() {
2301+ test_logger.trace() << "Key released: (" << +this->position.col << "," << +this->position.row << ")" << std::endl;
2302+ release_key(this->position.col, this->position.row);
2303+}
2304diff --git a/tests/test_common/test_keymap_key.hpp b/tests/test_common/test_keymap_key.hpp
2305new file mode 100644
2306index 0000000000000000000000000000000000000000..7861cb4a324e9845744dc090d557936649250108
2307--- /dev/null
2308+++ b/tests/test_common/test_keymap_key.hpp
2309@@ -0,0 +1,46 @@
2310+/* Copyright 2021 Stefan Kerkmann
2311+ *
2312+ * This program is free software: you can redistribute it and/or modify
2313+ * it under the terms of the GNU General Public License as published by
2314+ * the Free Software Foundation, either version 2 of the License, or
2315+ * (at your option) any later version.
2316+ *
2317+ * This program is distributed in the hope that it will be useful,
2318+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2319+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2320+ * GNU General Public License for more details.
2321+ *
2322+ * You should have received a copy of the GNU General Public License
2323+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2324+ */
2325+
2326+#pragma once
2327+
2328+extern "C" {
2329+#include "keyboard.h"
2330+#include "test_matrix.h"
2331+}
2332+
2333+#include <cassert>
2334+
2335+typedef uint8_t layer_t;
2336+
2337+struct KeymapKey {
2338+ KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(keycode) { validate(); }
2339+ KeymapKey(layer_t layer, uint8_t col, uint8_t row, uint16_t keycode, uint16_t report_code) : layer(layer), position({.col = col, .row = row}), code(keycode), report_code(report_code) { validate(); }
2340+
2341+ void press();
2342+ void release();
2343+
2344+ const layer_t layer;
2345+ const keypos_t position;
2346+ const uint16_t code;
2347+ /* Sometimes the keycode does not match the code that is send in the usb report, so we provide it here. */
2348+ const uint16_t report_code;
2349+
2350+ private:
2351+ void validate() {
2352+ assert(position.col <= MATRIX_COLS);
2353+ assert(position.row <= MATRIX_ROWS);
2354+ }
2355+};
2356diff --git a/tests/test_common/test_logger.cpp b/tests/test_common/test_logger.cpp
2357new file mode 100644
2358index 0000000000000000000000000000000000000000..959fdde5ec56987cde6f6e9c75bdfdda97b06eba
2359--- /dev/null
2360+++ b/tests/test_common/test_logger.cpp
2361@@ -0,0 +1,39 @@
2362+/* Copyright 2021 Stefan Kerkmann
2363+ *
2364+ * This program is free software: you can redistribute it and/or modify
2365+ * it under the terms of the GNU General Public License as published by
2366+ * the Free Software Foundation, either version 2 of the License, or
2367+ * (at your option) any later version.
2368+ *
2369+ * This program is distributed in the hope that it will be useful,
2370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2372+ * GNU General Public License for more details.
2373+ *
2374+ * You should have received a copy of the GNU General Public License
2375+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2376+ */
2377+
2378+#include <iostream>
2379+#include "test_logger.hpp"
2380+
2381+TestLogger test_logger;
2382+
2383+TestLogger& TestLogger::info() {
2384+ *this << "[ INFO ] ";
2385+ return *this;
2386+}
2387+
2388+TestLogger& TestLogger::trace() {
2389+ *this << "[ TRACE ] ";
2390+ return *this;
2391+}
2392+
2393+TestLogger& TestLogger::error() {
2394+ *this << "[ ERROR ] ";
2395+ return *this;
2396+}
2397+
2398+void TestLogger::reset() { this->m_log.str(""); };
2399+
2400+void TestLogger::print_log() { std::cerr << this->m_log.str(); }
2401diff --git a/tests/test_common/test_logger.hpp b/tests/test_common/test_logger.hpp
2402new file mode 100644
2403index 0000000000000000000000000000000000000000..348af7fab860a088a08574252fd642b5de4aed6f
2404--- /dev/null
2405+++ b/tests/test_common/test_logger.hpp
2406@@ -0,0 +1,35 @@
2407+/* Copyright 2021 Stefan Kerkmann
2408+ *
2409+ * This program is free software: you can redistribute it and/or modify
2410+ * it under the terms of the GNU General Public License as published by
2411+ * the Free Software Foundation, either version 2 of the License, or
2412+ * (at your option) any later version.
2413+ *
2414+ * This program is distributed in the hope that it will be useful,
2415+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2416+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2417+ * GNU General Public License for more details.
2418+ *
2419+ * You should have received a copy of the GNU General Public License
2420+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2421+ */
2422+
2423+#pragma once
2424+
2425+#include <ostream>
2426+#include <sstream>
2427+
2428+class TestLogger : public std::ostream {
2429+ public:
2430+ TestLogger() : std::ostream(&m_log){};
2431+ TestLogger& info();
2432+ TestLogger& trace();
2433+ TestLogger& error();
2434+ void print_log();
2435+ void reset();
2436+
2437+ private:
2438+ std::stringbuf m_log;
2439+};
2440+
2441+extern TestLogger test_logger;