add combo buffer tests

This commit is contained in:
John Wilmes
2025-08-19 15:45:59 -05:00
parent 63c607db1c
commit a0cf215605
8 changed files with 210 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "test_common.h"
#define COMBO_BUFFER_LENGTH 2

View File

@@ -0,0 +1,6 @@
# Copyright 2025 @johnwilmes
# SPDX-License-Identifier: GPL-2.0-or-later
COMBO_ENABLE = yes
INTROSPECTION_KEYMAP_C = test_combo_buffer.c

View File

@@ -0,0 +1,37 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#include "keyboard_report_util.hpp"
#include "keycode.h"
#include "test_common.h"
#include "test_common.hpp"
#include "test_driver.hpp"
#include "test_fixture.hpp"
#include "test_keymap_key.hpp"
using testing::_;
using testing::InSequence;
extern bool combo_override;
class ComboBuffer : public TestFixture {};
TEST_F(ComboBuffer, combo_active_buffer_overflow) {
TestDriver driver;
KeymapKey key_a(0, 0, 0, KC_A);
KeymapKey key_b(0, 1, 0, KC_B);
KeymapKey key_c(0, 2, 0, KC_C);
KeymapKey key_d(0, 3, 0, KC_D);
KeymapKey key_e(0, 4, 0, KC_E);
KeymapKey key_f(0, 5, 0, KC_F);
set_keymap({key_a, key_b, key_c, key_d, key_e, key_f});
EXPECT_REPORT(driver, (KC_1));
EXPECT_REPORT(driver, (KC_1, KC_2));
EXPECT_REPORT(driver, (KC_2));
EXPECT_REPORT(driver, (KC_2, KC_3));
EXPECT_REPORT(driver, (KC_3));
EXPECT_EMPTY_REPORT(driver);
tap_combo({key_a, key_b, key_c, key_d, key_e, key_f});
VERIFY_AND_CLEAR(driver);
}

View File

@@ -0,0 +1,18 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
#include "stdio.h"
enum combos {ab_1, cd_2, ef_3};
uint16_t const ab_1_combo[] = {KC_A, KC_B, COMBO_END};
uint16_t const cd_2_combo[] = {KC_C, KC_D, COMBO_END};
uint16_t const ef_3_combo[] = {KC_E, KC_F, COMBO_END};
// clang-format off
combo_t key_combos[] = {
[ab_1] = COMBO(ab_1_combo, KC_1),
[cd_2] = COMBO(cd_2_combo, KC_2),
[ef_3] = COMBO(ef_3_combo, KC_3),
};
// clang-format on

View File

@@ -0,0 +1,9 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "test_common.h"
#define COMBO_KEY_BUFFER_LENGTH 4
#define COMBO_CONTIGUOUS_PER_COMBO

View File

@@ -0,0 +1,6 @@
# Copyright 2025 @johnwilmes
# SPDX-License-Identifier: GPL-2.0-or-later
COMBO_ENABLE = yes
INTROSPECTION_KEYMAP_C = test_combo_key_buffer.c

View File

@@ -0,0 +1,103 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#include "keyboard_report_util.hpp"
#include "keycode.h"
#include "test_common.h"
#include "test_common.hpp"
#include "test_driver.hpp"
#include "test_fixture.hpp"
#include "test_keymap_key.hpp"
using testing::_;
using testing::InSequence;
extern bool combo_override;
class ComboKeyBuffer : public TestFixture {};
TEST_F(ComboKeyBuffer, combo_key_buffer) {
TestDriver driver;
KeymapKey key_a(0, 0, 0, KC_A);
KeymapKey key_b(0, 1, 0, KC_B);
KeymapKey key_i(0, 2, 0, KC_I);
KeymapKey key_j(0, 3, 0, KC_J);
KeymapKey key_k(0, 4, 0, KC_K);
KeymapKey key_a2(0, 5, 0, KC_A);
set_keymap({key_a, key_b, key_i, key_j, key_k, key_a2});
EXPECT_REPORT(driver, (KC_1)).Times(2);
EXPECT_REPORT(driver, (KC_1, KC_I));
EXPECT_REPORT(driver, (KC_1, KC_I, KC_J));
EXPECT_REPORT(driver, (KC_1, KC_J));
EXPECT_EMPTY_REPORT(driver);
tap_combo({key_a, key_i, key_j, key_b});
VERIFY_AND_CLEAR(driver);
// buffer overflow prevents combo from firing
EXPECT_REPORT(driver, (KC_A));
EXPECT_REPORT(driver, (KC_A, KC_I));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J, KC_K));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J, KC_K, KC_B));
EXPECT_REPORT(driver, (KC_I, KC_J, KC_K, KC_B));
EXPECT_REPORT(driver, (KC_J, KC_K, KC_B));
EXPECT_REPORT(driver, (KC_K, KC_B));
EXPECT_REPORT(driver, (KC_B));
EXPECT_EMPTY_REPORT(driver);
tap_combo({key_a, key_i, key_j, key_k, key_b});
VERIFY_AND_CLEAR(driver);
// buffer overflow prevents combo from firing initially, fires with a second key press
EXPECT_REPORT(driver, (KC_A)).Times(2);
EXPECT_REPORT(driver, (KC_A, KC_I));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J, KC_K));
EXPECT_REPORT(driver, (KC_A, KC_I, KC_J, KC_K, KC_1));
// the first KC_A release is consumed by the active combo even though it is a different position
EXPECT_REPORT(driver, (KC_A, KC_J, KC_K, KC_1));
EXPECT_REPORT(driver, (KC_A, KC_K, KC_1));
EXPECT_REPORT(driver, (KC_A, KC_1));
EXPECT_EMPTY_REPORT(driver);
for (KeymapKey key : {key_a, key_i, key_j, key_k, key_b, key_a2}) {
key.press();
run_one_scan_loop();
}
for (KeymapKey key : {key_a, key_i, key_j, key_k, key_b, key_a2}) {
key.release();
run_one_scan_loop();
}
VERIFY_AND_CLEAR(driver);
}
TEST_F(ComboKeyBuffer, combo_key_buffer_blocked) {
TestDriver driver;
KeymapKey key_a(0, 0, 0, KC_A);
KeymapKey key_b(0, 1, 0, KC_B);
KeymapKey key_i(0, 2, 0, KC_I);
KeymapKey key_j(0, 3, 0, KC_J);
KeymapKey key_k(0, 4, 0, KC_K);
KeymapKey key_x(0, 5, 0, KC_X);
set_keymap({key_a, key_b, key_i, key_j, key_k, key_x});
// If the key buffer doesn't overflow, we wait for ABX to fire
EXPECT_REPORT(driver, (KC_2)).Times(2);
EXPECT_REPORT(driver, (KC_I, KC_2));
EXPECT_EMPTY_REPORT(driver);
tap_combo({key_a, key_b, key_i, key_x});
VERIFY_AND_CLEAR(driver);
// If the key buffer overflows, we just use AB
EXPECT_REPORT(driver, (KC_1));
EXPECT_REPORT(driver, (KC_1, KC_I));
EXPECT_REPORT(driver, (KC_1, KC_I, KC_J));
EXPECT_REPORT(driver, (KC_1, KC_I, KC_J, KC_K));
EXPECT_REPORT(driver, (KC_1, KC_I, KC_J, KC_K, KC_X));
EXPECT_REPORT(driver, (KC_I, KC_J, KC_K, KC_X));
EXPECT_REPORT(driver, (KC_J, KC_K, KC_X));
EXPECT_REPORT(driver, (KC_K, KC_X));
EXPECT_REPORT(driver, (KC_X));
EXPECT_EMPTY_REPORT(driver);
tap_combo({key_a, key_b, key_i, key_j, key_k, key_x});
VERIFY_AND_CLEAR(driver);
}

View File

@@ -0,0 +1,23 @@
// Copyright 2025 @johnwilmes
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
#include "stdio.h"
enum combos {ab_1, abx_2};
uint16_t const ab_1_combo[] = {KC_A, KC_B, COMBO_END};
uint16_t const abx_2_combo[] = {KC_A, KC_B, KC_X, COMBO_END};
// clang-format off
combo_t key_combos[] = {
[ab_1] = COMBO(ab_1_combo, KC_1),
[abx_2] = COMBO(abx_2_combo, KC_2),
};
// clang-format on
bool is_combo_contiguous(uint16_t index, combo_t *combo, keyrecord_t *record, uint8_t n_unpressed_keys) {
return false; // No combos are contiguous in this test
}