Skip to content

Commit

Permalink
Fix and add unit tests for Caps Word to work with Unicode Map, Auto S…
Browse files Browse the repository at this point in the history
…hift, Retro Shift. (qmk#17284)

* Fix Caps Word and Unicode Map

* Tests for Caps Word + Auto Shift and Unicode Map.

* Fix formatting

* Add additional keyboard report expectation macros

This commit defines five test utilities, EXPECT_REPORT, EXPECT_UNICODE,
EXPECT_EMPTY_REPORT, EXPECT_ANY_REPORT and EXPECT_NO_REPORT for use with
TestDriver.

EXPECT_REPORT sets a gmock expectation that a given keyboard report will
be sent. For instance,

  EXPECT_REPORT(driver, (KC_LSFT, KC_A));

is shorthand for

  EXPECT_CALL(driver,
      send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));

EXPECT_UNICODE sets a gmock expectation that a given Unicode code point
will be sent using UC_LNX input mode. For instance for U+2013,

  EXPECT_UNICODE(driver, 0x2013);

expects the sequence of keys:

  "Ctrl+Shift+U, 2, 0, 1, 3, space".

EXPECT_EMPTY_REPORT sets a gmock expectation that a given keyboard
report will be sent. For instance

  EXPECT_EMPTY_REPORT(driver);

expects a single report without keypresses or modifiers.

EXPECT_ANY_REPORT sets a gmock expectation that a arbitrary keyboard
report will be sent, without matching its contents. For instance

  EXPECT_ANY_REPORT(driver).Times(1);

expects a single arbitrary keyboard report will be sent.

EXPECT_NO_REPORT sets a gmock expectation that no keyboard report will
be sent at all.

* Add tap_key() and tap_keys() to TestFixture.

This commit adds a `tap_key(key)` method to TestFixture that taps a
given KeymapKey, optionally with a specified delay between press and
release.

Similarly, the method `tap_keys(key_a, key_b, key_c)` taps a sequence of
KeymapKeys.

* Use EXPECT_REPORT, tap_keys, etc. in most tests.

This commit uses EXPECT_REPORT, EXPECT_UNICODE, EXPECT_EMPTY_REPORT,
EXPECT_NO_REPORT, tap_key() and tap_keys() test utilities from the
previous two commits in most tests. Particularly the EXPECT_REPORT
macro is frequently useful and makes a nice reduction in boilerplate
needed to express many tests.

Co-authored-by: David Kosorin <david@kosorin.net>
  • Loading branch information
2 people authored and zykrah committed Jul 2, 2022
1 parent 00e892c commit 8863f4a
Show file tree
Hide file tree
Showing 28 changed files with 686 additions and 295 deletions.
1 change: 1 addition & 0 deletions quantum/process_keycode/process_unicode_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ __attribute__((weak)) void unicode_input_start(void) {

unicode_saved_mods = get_mods(); // Save current mods
clear_mods(); // Unregister mods to start from a clean state
clear_weak_mods();

switch (unicode_config.input_mode) {
case UC_MAC:
Expand Down
6 changes: 6 additions & 0 deletions quantum/quantum.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ bool process_record_quantum_helper(uint16_t keycode, keyrecord_t *record) {
#ifdef TAP_DANCE_ENABLE
process_tap_dance(keycode, record) &&
#endif
#ifdef CAPS_WORD_ENABLE
process_caps_word(keycode, record) &&
#endif
#if defined(UNICODE_COMMON_ENABLE)
process_unicode_common(keycode, record) &&
#endif
Expand All @@ -318,6 +321,9 @@ bool process_record_quantum_helper(uint16_t keycode, keyrecord_t *record) {
#ifdef CAPS_WORD_ENABLE
process_caps_word(keycode, record) &&
#endif
#ifdef TERMINAL_ENABLE
process_terminal(keycode, record) &&
#endif
#ifdef SPACE_CADET_ENABLE
process_space_cadet(keycode, record) &&
#endif
Expand Down
16 changes: 8 additions & 8 deletions tests/auto_shift/test_auto_shift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ TEST_F(AutoShift, key_release_before_timeout) {
set_keymap({regular_key});

/* Press regular key */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
regular_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release regular key */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_A)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
EXPECT_REPORT(driver, (KC_A));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
Expand All @@ -55,16 +55,16 @@ TEST_F(AutoShift, key_release_after_timeout) {
set_keymap({regular_key});

/* Press regular key */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
regular_key.press();
idle_for(AUTO_SHIFT_TIMEOUT);
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release regular key */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT, KC_A)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_LSFT)));
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport()));
EXPECT_REPORT(driver, (KC_LSFT, KC_A));
EXPECT_REPORT(driver, (KC_LSFT));
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
}
}
54 changes: 27 additions & 27 deletions tests/basic/test_action_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ TEST_F(ActionLayer, MomentaryLayerDoesNothing) {
set_keymap({layer_key});

/* Press and release MO, nothing should happen. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.press();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.release();
run_one_scan_loop();
testing::Mock::VerifyAndClearExpectations(&driver);
Expand All @@ -151,28 +151,28 @@ TEST_F(ActionLayer, MomentaryLayerWithKeypress) {
set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});

/* Press MO. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Press key on layer 1 */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
EXPECT_REPORT(driver, (KC_B)).Times(1);
regular_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release key on layer 1 */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release MO */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
Expand All @@ -188,14 +188,14 @@ TEST_F(ActionLayer, ToggleLayerDoesNothing) {
set_keymap({layer_key});

/* Press TG. Layer state should not change as it's applied on release. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release TG. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
Expand All @@ -212,26 +212,26 @@ TEST_F(ActionLayer, ToggleLayerUpAndDown) {
set_keymap({toggle_layer_1_on_layer_0, toggle_layer_0_on_layer_1});

/* Toggle Layer 1. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
toggle_layer_1_on_layer_0.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
toggle_layer_1_on_layer_0.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Toggle Layer 0. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
toggle_layer_0_on_layer_1.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
toggle_layer_0_on_layer_1.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
Expand All @@ -247,13 +247,13 @@ TEST_F(ActionLayer, LayerTapToggleDoesNothing) {
set_keymap({layer_key});

/* Press and release TT. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
Expand All @@ -271,25 +271,25 @@ TEST_F(ActionLayer, LayerTapToggleWithKeypress) {
set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});

/* Press TT. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
EXPECT_REPORT(driver, (KC_B)).Times(1);
regular_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
Expand All @@ -307,7 +307,7 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) {
set_keymap({layer_key, regular_key, KeymapKey{1, 1, 0, KC_B}});

/* Tap TT five times . */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);

layer_key.press();
run_one_scan_loop();
Expand Down Expand Up @@ -346,13 +346,13 @@ TEST_F(ActionLayer, LayerTapToggleWithToggleWithKeypress) {

testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_B))).Times(1);
EXPECT_REPORT(driver, (KC_B)).Times(1);
regular_key.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
EXPECT_EMPTY_REPORT(driver);
regular_key.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
Expand All @@ -370,31 +370,31 @@ TEST_F(ActionLayer, LayerTapReleasedBeforeKeypressReleaseWithModifiers) {
set_keymap({layer_0_key_0, layer_1_key_1});

/* Press layer tap and wait for tapping term to switch to layer 1 */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(0);
EXPECT_NO_REPORT(driver);
layer_0_key_0.press();
idle_for(TAPPING_TERM);
EXPECT_TRUE(layer_state_is(0));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Press key with layer 1 mapping, result basically expected
* altough more reports are send then necessary. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT, KC_9))).Times(1);
EXPECT_REPORT(driver, (KC_RALT)).Times(1);
EXPECT_REPORT(driver, (KC_RALT, KC_9)).Times(1);
layer_1_key_1.press();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(1));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Release layer tap key, no report is send because key is still held. */
EXPECT_CALL(driver, send_keyboard_mock(_)).Times(0);
EXPECT_NO_REPORT(driver);
layer_0_key_0.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
testing::Mock::VerifyAndClearExpectations(&driver);

/* Unregister keycode and modifier. */
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport(KC_RALT))).Times(1);
EXPECT_CALL(driver, send_keyboard_mock(KeyboardReport())).Times(1);
EXPECT_REPORT(driver, (KC_RALT)).Times(1);
EXPECT_EMPTY_REPORT(driver);
layer_1_key_1.release();
run_one_scan_loop();
EXPECT_TRUE(layer_state_is(0));
Expand Down
Loading

0 comments on commit 8863f4a

Please sign in to comment.