From 836e4af8aeb2510829fe1bc0300f73888c9412c2 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Tue, 6 Apr 2021 19:08:55 -0500 Subject: [PATCH] Update testcases for Macros plugin Signed-off-by: Michael Richters --- .../activation-order/activation-order.ino | 6 +- .../layers/activation-order/test.ktest | 145 ++++++++++++ .../layers/activation-order/test/testcase.cpp | 206 ------------------ tests/plugins/Macros/basic/basic.ino | 18 +- tests/plugins/Macros/basic/test.ktest | 97 +++++++++ tests/plugins/Macros/basic/test/testcase.cpp | 136 ------------ 6 files changed, 256 insertions(+), 352 deletions(-) create mode 100644 tests/features/layers/activation-order/test.ktest delete mode 100644 tests/features/layers/activation-order/test/testcase.cpp create mode 100644 tests/plugins/Macros/basic/test.ktest delete mode 100644 tests/plugins/Macros/basic/test/testcase.cpp diff --git a/tests/features/layers/activation-order/activation-order.ino b/tests/features/layers/activation-order/activation-order.ino index 60f39a09..7e9d491a 100644 --- a/tests/features/layers/activation-order/activation-order.ino +++ b/tests/features/layers/activation-order/activation-order.ino @@ -77,10 +77,10 @@ KEYMAPS( KALEIDOSCOPE_INIT_PLUGINS(Macros); -const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) { - switch (macroIndex) { +const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) { + switch (macro_id) { case 0: - if (keyToggledOn(keyState)) + if (keyToggledOn(event.state)) Layer.deactivate(0); else Layer.activate(0); diff --git a/tests/features/layers/activation-order/test.ktest b/tests/features/layers/activation-order/test.ktest new file mode 100644 index 00000000..a9ab0a09 --- /dev/null +++ b/tests/features/layers/activation-order/test.ktest @@ -0,0 +1,145 @@ +VERSION 1 + +KEYSWITCH TOP_LEFT 0 0 +KEYSWITCH TOP_RIGHT 0 15 +KEYSWITCH PALM_LEFT 3 6 +KEYSWITCH PALM_RIGHT 3 9 +KEYSWITCH LEFT_THUMB 3 7 + +# ============================================================================== +NAME Layer Activation Order base layer has not regressed + +RUN 4 ms +PRESS TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_0 + +RUN 4 ms +RELEASE TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report empty + +RUN 5 ms + +# ============================================================================== +NAME Layer Activation Order shift to layer 1 + +RUN 4 ms +PRESS PALM_LEFT +RUN 1 cycle + +RUN 4 ms +PRESS TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_1 + +RUN 4 ms +RELEASE TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report empty + +RUN 4 ms +RELEASE PALM_LEFT +RUN 1 cycle + +RUN 5 ms + +# ============================================================================== +NAME Layer Activation Order shifting with caching + +RUN 4 ms +PRESS TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_0 + +# activate layer 1 +RUN 4 ms +PRESS PALM_LEFT +RUN 1 cycle + +RUN 4 ms +PRESS TOP_RIGHT +RUN 1 cycle +EXPECT keyboard-report Key_0 Key_1 + +RUN 4 ms +RELEASE TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_1 + +RUN 4 ms +RELEASE TOP_RIGHT +RUN 1 cycle +EXPECT keyboard-report empty + +RUN 4 ms +PRESS TOP_RIGHT +RUN 1 cycle +EXPECT keyboard-report Key_1 + +RUN 4 ms +RELEASE TOP_RIGHT +RUN 1 cycle +EXPECT keyboard-report empty + +# deactivate layer 1 +RUN 4 ms +RELEASE PALM_LEFT +RUN 1 cycle + +RUN 5 ms + +# ============================================================================== +NAME Layer Activation Order ordering + +# activate layer 2 +RUN 4 ms +PRESS PALM_RIGHT +RUN 1 cycle + +RUN 4 ms +PRESS TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_2 + +# activate layer 1 (on top of layer 2) +RUN 4 ms +PRESS PALM_LEFT +RUN 1 cycle + +RUN 4 ms +PRESS TOP_RIGHT +RUN 1 cycle +EXPECT keyboard-report Key_1 Key_2 + +RUN 4 ms +RELEASE PALM_RIGHT +RELEASE PALM_LEFT +RELEASE TOP_RIGHT +RELEASE TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_1 +EXPECT keyboard-report empty + +RUN 5 ms + +# ============================================================================== +NAME Layer Activation Order layer 0 fallback + +# Use a Macro to deactivate layer 0 +RUN 4 ms +PRESS LEFT_THUMB +RUN 1 cycle + +RUN 4 ms +PRESS TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report Key_0 + +RUN 4 ms +RELEASE LEFT_THUMB +RELEASE TOP_LEFT +RUN 1 cycle +EXPECT keyboard-report empty + +RUN 5 ms diff --git a/tests/features/layers/activation-order/test/testcase.cpp b/tests/features/layers/activation-order/test/testcase.cpp deleted file mode 100644 index d1e39e25..00000000 --- a/tests/features/layers/activation-order/test/testcase.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- 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" - -SETUP_GOOGLETEST(); - -namespace kaleidoscope { -namespace testing { -namespace { - -using ::testing::IsEmpty; - -class LayerActivationOrder : public VirtualDeviceTest { - public: - const KeyAddr KEYSWITCH_TOP_LEFT = KeyAddr{0, 0}; // layer-dependent key - const KeyAddr KEYSWITCH_TOP_RIGHT = KeyAddr{0, 15}; // layer-dependent key - const KeyAddr KEYSWITCH_LEFT_PALM = KeyAddr{3, 6}; // ShiftToLayer(1) - const KeyAddr KEYSWITCH_RIGHT_PALM = KeyAddr{3, 9}; // ShiftToLayer(2) - const KeyAddr KEYSWITCH_LEFT_THUMB_RIGHTMOST = KeyAddr{3, 7}; // L0 deactivate macro - - const Key LAYER0_KEY = Key_0; - const Key LAYER1_KEY = Key_1; - const Key LAYER2_KEY = Key_2; - - void pressKeyswitch(const KeyAddr& addr) { - sim_.Press(addr.row(), addr.col()); - } - - void releaseKeyswitch(const KeyAddr& addr) { - sim_.Release(addr.row(), addr.col()); - } - - auto pressKeyswitchAndRunCycle(const KeyAddr& addr) { - pressKeyswitch(addr); - return RunCycle(); - } - - auto releaseKeyswitchAndRunCycle(const KeyAddr& addr) { - releaseKeyswitch(addr); - return RunCycle(); - } - - void assertSingleKeyboardReportContaining(std::unique_ptr &state, Key k) { - ASSERT_EQ(state->HIDReports()->Keyboard().size(), 1); - EXPECT_THAT( - state->HIDReports()->Keyboard(0).ActiveKeycodes(), - Contains(k)); - } - - void assertSingleKeyboardReportNotContaining(std::unique_ptr &state, Key k) { - ASSERT_EQ(state->HIDReports()->Keyboard().size(), 1); - EXPECT_THAT( - state->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::Not(Contains(k))); - } - - void assertSingleEmptyReport(std::unique_ptr &state) { - ASSERT_EQ(state->HIDReports()->Keyboard().size(), 1); - EXPECT_THAT( - state->HIDReports()->Keyboard(0).ActiveKeycodes(), - IsEmpty()); - } - - void assertNoReport(std::unique_ptr &state) { - ASSERT_EQ(state->HIDReports()->Keyboard().size(), 0); - } - - void assertNoReportAfterCycle() { - auto state = RunCycle(); - assertNoReport(state); - } - - void TestPressAndRelease(const KeyAddr& addr, Key k) { - auto state = pressKeyswitchAndRunCycle(addr); - assertSingleKeyboardReportContaining(state, k); - - state = releaseKeyswitchAndRunCycle(addr); - assertSingleEmptyReport(state); - - assertNoReportAfterCycle(); - } -}; - -TEST_F(LayerActivationOrder, BaseLayerHasNotRegressed) { - TestPressAndRelease(KEYSWITCH_TOP_LEFT, LAYER0_KEY); -} - -TEST_F(LayerActivationOrder, ShifToLayerOne) { - // Pressing (KEYSWITCH_LEFT_PALM) shifts to Layer 1, and we stay there until release. - auto state = pressKeyswitchAndRunCycle(KEYSWITCH_LEFT_PALM); - TestPressAndRelease(KEYSWITCH_TOP_LEFT, LAYER1_KEY); - - // Releasing (KEYSWITCH_LEFT_PALM) gets us back to the base layer - state = releaseKeyswitchAndRunCycle(KEYSWITCH_LEFT_PALM); - TestPressAndRelease(KEYSWITCH_TOP_LEFT, LAYER0_KEY); -} - -TEST_F(LayerActivationOrder, ShiftingWithCaching) { - // Pressing (KEYSWITCH_TOP_LEFT) will activate the key on layer 0 - auto state = pressKeyswitchAndRunCycle(KEYSWITCH_TOP_LEFT); - assertSingleKeyboardReportContaining(state, LAYER0_KEY); - - // Pressing (KEYSWITCH_LEFT_PALM) will switch to Layer 1 - state = pressKeyswitchAndRunCycle(KEYSWITCH_LEFT_PALM); - - // ...since we're still pressing (KEYSWITCH_TOP_LEFT), and there was no change - // in the HID states, we shouldn't emit a report. - assertNoReport(state); - - // Pressing (KEYSWITCH_TOP_RIGHT), the report shall contain keys from both - // layer 0 and layer1, because we started holding the layer 0 key prior to - // switching layers, so it's code should remain cached. - state = pressKeyswitchAndRunCycle(KEYSWITCH_TOP_RIGHT); - assertSingleKeyboardReportContaining(state, LAYER0_KEY); - assertSingleKeyboardReportContaining(state, LAYER1_KEY); - - // Releasing (KEYSWITCH_TOP_LEFT), the report should now contain the key from - // layer1 only, and should not contain the layer0 key anymore. - state = releaseKeyswitchAndRunCycle(KEYSWITCH_TOP_LEFT); - assertSingleKeyboardReportContaining(state, LAYER1_KEY); - assertSingleKeyboardReportNotContaining(state, LAYER0_KEY); - - // Release (KEYSWITCH_TOP_RIGHT) - state = releaseKeyswitchAndRunCycle(KEYSWITCH_TOP_RIGHT); - - // Test the layer 1 key in isolation again - TestPressAndRelease(KEYSWITCH_TOP_LEFT, LAYER1_KEY); - - // Release the layer key as well. - state = releaseKeyswitchAndRunCycle(KEYSWITCH_LEFT_PALM); - - // Since the layer key release is internal to us, we shouldn't send a report. - assertNoReport(state); -} - -TEST_F(LayerActivationOrder, Ordering) { - // Pressing (KEYSWITCH_RIGHT_PALM) will switch to Layer 2 - auto state = pressKeyswitchAndRunCycle(KEYSWITCH_RIGHT_PALM); - - // Pressing (KEYSWITCH_TOP_LEFT) will activate a key on layer 2 - state = pressKeyswitchAndRunCycle(KEYSWITCH_TOP_LEFT); - assertSingleKeyboardReportContaining(state, LAYER2_KEY); - - // Pressing (KEYSWITCH_LEFT_PALM) will activate Layer 1 - state = pressKeyswitchAndRunCycle(KEYSWITCH_LEFT_PALM); - - // Pressing (KEYSWITCH_TOP_RIGHT) will activate the layer 1 key now, due to - // activation ordering. - state = pressKeyswitchAndRunCycle(KEYSWITCH_TOP_RIGHT); - - // We should have both the layer 1 and the layer 2 key active, because we're - // holding both. - assertSingleKeyboardReportContaining(state, LAYER1_KEY); - assertSingleKeyboardReportContaining(state, LAYER2_KEY); - - // Releaseing all held keys, we should get an empty report. - releaseKeyswitch(KEYSWITCH_TOP_LEFT); - releaseKeyswitch(KEYSWITCH_TOP_RIGHT); - releaseKeyswitch(KEYSWITCH_LEFT_PALM); - releaseKeyswitch(KEYSWITCH_RIGHT_PALM); - state = RunCycle(); - - assertSingleEmptyReport(state); - - // One more cycle, and we should generate no report at all - state = RunCycle(); - assertNoReport(state); -} - -TEST_F(LayerActivationOrder, LayerZero) { - // Pressing the rightmost of the left thumb keys should deactivate layer 0 - auto state = pressKeyswitchAndRunCycle(KEYSWITCH_LEFT_THUMB_RIGHTMOST); - - // Pressing KEYSWITCH_TOP_LEFT should fall back to activating the key on layer 0 - state = pressKeyswitchAndRunCycle(KEYSWITCH_TOP_LEFT); - assertSingleKeyboardReportContaining(state, LAYER0_KEY); - - // Releasing all keys should generate a single empty report - releaseKeyswitch(KEYSWITCH_TOP_LEFT); - releaseKeyswitch(KEYSWITCH_LEFT_THUMB_RIGHTMOST); - state = RunCycle(); - - assertSingleEmptyReport(state); - - // Afterwards, we should generate no more reports. - state = RunCycle(); - assertNoReport(state); -} - -} // namespace -} // namespace testing -} // namespace kaleidoscope diff --git a/tests/plugins/Macros/basic/basic.ino b/tests/plugins/Macros/basic/basic.ino index 59c552ff..d69bd1db 100644 --- a/tests/plugins/Macros/basic/basic.ino +++ b/tests/plugins/Macros/basic/basic.ino @@ -21,7 +21,7 @@ KEYMAPS( [0] = KEYMAP_STACKED ( - M(0), M(1), M(255), ___, ___, ___, ___, + M(0), M(1), M(255), M(2), M(3), ___, ___, Key_X, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, @@ -40,17 +40,21 @@ KEYMAPS( ) // *INDENT-ON* -const macro_t *macroAction(uint8_t index, uint8_t key_state) { - if (keyToggledOn(key_state)) { - switch (index) { +const macro_t *macroAction(uint8_t macro_id, KeyEvent &event) { + if (keyToggledOn(event.state)) { + switch (macro_id) { case 0: - Kaleidoscope.hid().keyboard().pressKey(Key_A); + Macros.type(PSTR("a")); break; case 1: - Kaleidoscope.hid().keyboard().pressKey(Key_B); + Macros.type(PSTR("abc")); break; + case 2: + return MACRO(D(A), T(C), U(A), T(B)); + case 3: + return MACRO(D(A), D(B)); case 255: - Kaleidoscope.hid().keyboard().pressKey(Key_C); + Macros.type(PSTR("c")); break; } } diff --git a/tests/plugins/Macros/basic/test.ktest b/tests/plugins/Macros/basic/test.ktest new file mode 100644 index 00000000..07d735ce --- /dev/null +++ b/tests/plugins/Macros/basic/test.ktest @@ -0,0 +1,97 @@ +VERSION 1 + +KEYSWITCH M_0 0 0 +KEYSWITCH M_1 0 1 +KEYSWITCH M_2 0 2 +KEYSWITCH M_3 0 3 +KEYSWITCH M_4 0 4 +KEYSWITCH X 1 0 + +# ============================================================================== +NAME Macro index 0 + +RUN 5 ms +PRESS M_0 +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +RELEASE M_0 +RUN 1 cycle + +# ============================================================================== +NAME Macro index 1 + +RUN 5 ms +PRESS M_1 +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` +EXPECT keyboard-report empty # Report should be empty +EXPECT keyboard-report Key_B # Report should contain only `B` +EXPECT keyboard-report empty # Report should be empty +EXPECT keyboard-report Key_C # Report should contain only `C` +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +RELEASE M_1 +RUN 1 cycle + +# ============================================================================== +NAME Macro index 2 + +RUN 5 ms +PRESS M_3 +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` +EXPECT keyboard-report Key_A Key_C # Report should contain `A` & `C` +EXPECT keyboard-report Key_A # Report should contain only `A` +EXPECT keyboard-report empty # Report should be empty +EXPECT keyboard-report Key_B # Report should contain only `B` +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +RELEASE M_3 +RUN 1 cycle + +# ============================================================================== +NAME Macro index 3 + +RUN 5 ms +PRESS M_4 +RUN 1 cycle +EXPECT keyboard-report Key_A # Report should contain only `A` +EXPECT keyboard-report Key_A Key_B # Report should contain `A` & `B` + +RUN 5 ms +RELEASE M_4 +RUN 1 cycle +EXPECT keyboard-report Key_B # Report should contain only `B` +EXPECT keyboard-report empty # Report should be empty +RUN 1 cycle + +# ============================================================================== +NAME Macro index 255 + +RUN 5 ms +PRESS M_2 +RUN 1 cycle +EXPECT keyboard-report Key_C # Report should contain only `C` +EXPECT keyboard-report empty # Report should be empty + +RUN 5 ms +RELEASE M_2 +RUN 1 cycle + +# ============================================================================== +NAME Macros other key + +RUN 5 ms +PRESS X +RUN 1 cycle +EXPECT keyboard-report Key_X # Report should contain only `X` + +RUN 5 ms +RELEASE X +RUN 1 cycle +EXPECT keyboard-report empty # Report should be empty diff --git a/tests/plugins/Macros/basic/test/testcase.cpp b/tests/plugins/Macros/basic/test/testcase.cpp deleted file mode 100644 index e23c5d52..00000000 --- a/tests/plugins/Macros/basic/test/testcase.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- 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" - -SETUP_GOOGLETEST(); - -namespace kaleidoscope { -namespace testing { -namespace { - -constexpr KeyAddr addr_macro_A{0, 0}; -constexpr KeyAddr addr_macro_B{0, 1}; -constexpr KeyAddr addr_macro_C{0, 2}; -constexpr KeyAddr addr_macro_X{0, 3}; -constexpr KeyAddr addr_X{1, 0}; - -class MacrosBasic : public VirtualDeviceTest { - protected: - std::set expected_keycodes_ = {}; - std::unique_ptr state_ = nullptr; -}; - -TEST_F(MacrosBasic, MacroIndex_0) { - - sim_.Press(addr_macro_A); - state_ = RunCycle(); - expected_keycodes_.insert(Key_A.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one HID report"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should include only `A`"; - - sim_.Release(addr_macro_A); - state_ = RunCycle(); - expected_keycodes_.erase(Key_A.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one report after letter key release"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should be empty"; -} - -TEST_F(MacrosBasic, MacroIndex_1) { - - sim_.Press(addr_macro_B); - state_ = RunCycle(); - expected_keycodes_.insert(Key_B.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one HID report"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should include only `B`"; - - sim_.Release(addr_macro_B); - state_ = RunCycle(); - expected_keycodes_.erase(Key_B.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one report after letter key release"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should be empty"; -} - -TEST_F(MacrosBasic, MacroIndex_255) { - - sim_.Press(addr_macro_C); - state_ = RunCycle(); - expected_keycodes_.insert(Key_C.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one HID report"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should include only `C`"; - - state_ = RunCycle(); - expected_keycodes_.erase(Key_C.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one report in the next cycle"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should be empty"; - - sim_.Release(addr_macro_C); - state_ = RunCycle(); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 0) - << "There should be no report after release"; -} - -TEST_F(MacrosBasic, NonMacrosKey) { - - sim_.Press(addr_X); - state_ = RunCycle(); - expected_keycodes_.insert(Key_X.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one HID report"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should include only `X`"; - - sim_.Release(addr_X); - state_ = RunCycle(); - expected_keycodes_.erase(Key_X.getKeyCode()); - - ASSERT_EQ(state_->HIDReports()->Keyboard().size(), 1) - << "There should be one report after letter key release"; - EXPECT_THAT(state_->HIDReports()->Keyboard(0).ActiveKeycodes(), - ::testing::ElementsAreArray(expected_keycodes_)) - << "The report should be empty"; -} - -} // namespace -} // namespace testing -} // namespace kaleidoscope