diff --git a/tests/issues/1107/1107.ino b/tests/issues/1107/QueueLeaker/QueueLeaker.ino similarity index 100% rename from tests/issues/1107/1107.ino rename to tests/issues/1107/QueueLeaker/QueueLeaker.ino diff --git a/tests/issues/1107/sketch.json b/tests/issues/1107/QueueLeaker/sketch.json similarity index 100% rename from tests/issues/1107/sketch.json rename to tests/issues/1107/QueueLeaker/sketch.json diff --git a/tests/issues/1107/test/testcase.cpp b/tests/issues/1107/QueueLeaker/test/testcase.cpp similarity index 54% rename from tests/issues/1107/test/testcase.cpp rename to tests/issues/1107/QueueLeaker/test/testcase.cpp index ea4b3e28..75ae1adb 100644 --- a/tests/issues/1107/test/testcase.cpp +++ b/tests/issues/1107/QueueLeaker/test/testcase.cpp @@ -45,53 +45,13 @@ class KeyAddrEventQueueLeak : public VirtualDeviceTest { }; TEST_F(KeyAddrEventQueueLeak, TimeIsConsistent) { - assertTimeElapses(1); - assertTimeElapses(1); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); - assertTimeElapses(10); + // Basic test every cycle + for (int i = 0; i < 10; ++i) + assertTimeElapses(1); + + // Guarantee underflow in case of signed integer length + for (int i = 0; i < 50; ++i) + assertTimeElapses(10); } } // namespace diff --git a/tests/issues/1107/Qukeys/Qukeys.ino b/tests/issues/1107/Qukeys/Qukeys.ino new file mode 100644 index 00000000..74264835 --- /dev/null +++ b/tests/issues/1107/Qukeys/Qukeys.ino @@ -0,0 +1,77 @@ +/* -*- mode: c++ -*- + * Copyright (C) 2022 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include + +#include "./common.h" + +// *INDENT-OFF* +KEYMAPS( + [0] = KEYMAP_STACKED + ( + Key_A, Key_B, ___, ___, ___, ___, ___, + SFT_T(X), CTL_T(Y), ___, ___, ___, ___, ___, + Key_C, Key_D, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___, + + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, ___, ___, ___, + ___, ___, ___, ___, + ___ + ), +) +// *INDENT-ON* + +#include + +namespace kaleidoscope { +namespace plugin { + +class QueueLeaker : public Plugin { + public: + EventHandlerResult afterEachCycle() { + queue_.shift(); + return EventHandlerResult::OK; + } + private: + KeyAddrEventQueue<8> queue_; +}; + +} // namespace plugin +} // namespace kaleidoscope + +kaleidoscope::plugin::QueueLeaker QueueLeaker; + +KALEIDOSCOPE_INIT_PLUGINS(Qukeys, QueueLeaker); + +void setup() { + Qukeys.setHoldTimeout(kaleidoscope::testing::QUKEYS_HOLD_TIMEOUT); + Qukeys.setOverlapThreshold(kaleidoscope::testing::QUKEYS_OVERLAP_THRESHOLD); + Qukeys.setMinimumHoldTime(kaleidoscope::testing::QUKEYS_MINIMUM_HOLD_TIME); + Qukeys.setMinimumPriorInterval(kaleidoscope::testing::QUKEYS_MIN_PRIOR_INTERVAL); + Qukeys.setMaxIntervalForTapRepeat(kaleidoscope::testing::QUKEYS_MAX_INTERVAL_FOR_TAP_REPEAT); + + Kaleidoscope.setup(); +} + +void loop() { + Kaleidoscope.loop(); +} diff --git a/tests/issues/1107/Qukeys/common.h b/tests/issues/1107/Qukeys/common.h new file mode 100644 index 00000000..2707c775 --- /dev/null +++ b/tests/issues/1107/Qukeys/common.h @@ -0,0 +1,33 @@ +// -*- mode: c++ -*- + +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2021 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include + +namespace kaleidoscope { +namespace testing { + +constexpr uint16_t QUKEYS_HOLD_TIMEOUT = 10; +constexpr uint8_t QUKEYS_OVERLAP_THRESHOLD = 0; +constexpr uint8_t QUKEYS_MINIMUM_HOLD_TIME = 0; +constexpr uint8_t QUKEYS_MIN_PRIOR_INTERVAL = 0; +constexpr uint8_t QUKEYS_MAX_INTERVAL_FOR_TAP_REPEAT = 0; + +} // namespace testing +} // namespace kaleidoscope diff --git a/tests/issues/1107/Qukeys/sketch.json b/tests/issues/1107/Qukeys/sketch.json new file mode 100644 index 00000000..8cc86922 --- /dev/null +++ b/tests/issues/1107/Qukeys/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:virtual:model01", + "port": "" + } +} diff --git a/tests/issues/1107/Qukeys/test/testcase.cpp b/tests/issues/1107/Qukeys/test/testcase.cpp new file mode 100644 index 00000000..2d7e58d5 --- /dev/null +++ b/tests/issues/1107/Qukeys/test/testcase.cpp @@ -0,0 +1,81 @@ +/* -*- mode: c++ -*- + * Copyright (C) 2020 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "testing/setup-googletest.h" + +#include "../common.h" + +SETUP_GOOGLETEST(); + +namespace kaleidoscope { +namespace testing { +namespace { + +constexpr KeyAddr key_addr_A{0, 0}; +constexpr KeyAddr key_addr_B{0, 1}; +constexpr KeyAddr key_addr_X{1, 0}; +constexpr KeyAddr key_addr_Y{1, 1}; + +using ::testing::IsEmpty; + +class QukeysIssue1107 : public VirtualDeviceTest { + protected: + std::set expected_keycodes_ = {}; + std::unique_ptr state_ = nullptr; + public: + void testDelayedTimeout() { + state_ = RunCycle(); + + // Press `X` + sim_.Press(key_addr_X); + state_ = RunCycle(); + + ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 0) + << "There should be no HID report after the qukey is pressed"; + + // Record time at start + uint32_t start = Kaleidoscope.millisAtCycleStart(); + + uint8_t n = QUKEYS_HOLD_TIMEOUT + 1; + while (n-- > 0) + millis(); + + // Release `X` + sim_.Release(key_addr_X); + state_ = RunCycle(); + + // Record time at end + uint32_t end = Kaleidoscope.millisAtCycleStart(); + + ASSERT_EQ((end - start), (QUKEYS_HOLD_TIMEOUT + 2)) + << "Only one millisecond should be registered elapsed per cycle"; + + ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 2) + << "There should be two HID reports after the release of a timed-out qukey"; + } +}; + +TEST_F(QukeysIssue1107, DelayedTimeoutRelease) { + for (int i = 0; i < 10; ++i) + testDelayedTimeout(); + + state_ = RunCycle(); + ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 0); +} + +} // namespace +} // namespace testing +} // namespace kaleidoscope