diff --git a/plugins/Kaleidoscope-FirmwareVersion/src/kaleidoscope/plugin/FirmwareVersion.h b/plugins/Kaleidoscope-FirmwareVersion/src/kaleidoscope/plugin/FirmwareVersion.h index e6b4ec64dd..3ab3c88bfb 100644 --- a/plugins/Kaleidoscope-FirmwareVersion/src/kaleidoscope/plugin/FirmwareVersion.h +++ b/plugins/Kaleidoscope-FirmwareVersion/src/kaleidoscope/plugin/FirmwareVersion.h @@ -41,9 +41,9 @@ class FirmwareVersion : public Plugin { return EventHandlerResult::OK; #ifdef KALEIDOSCOPE_FIRMWARE_VERSION - ::Focus.send(F(KALEIDOSCOPE_FIRMWARE_VERSION)); + ::Focus.sendRaw(F(KALEIDOSCOPE_FIRMWARE_VERSION)); #else - ::Focus.send(F("0.0.0")); + ::Focus.sendRaw(F("0.0.0")); #endif return EventHandlerResult::OK; diff --git a/testing/SimHarness.cpp b/testing/SimHarness.cpp index 7f716d67f3..1817469294 100644 --- a/testing/SimHarness.cpp +++ b/testing/SimHarness.cpp @@ -75,6 +75,63 @@ uint8_t SimHarness::CycleTime() const { return millis_per_cycle_; } +// Serial support implementation +void SimHarness::ProcessSerialInput() { + // This will be called by RunCycle() to process any pending serial input + // The actual processing is handled by the virtual HardwareSerial implementation +} + +void SimHarness::SendSerialData(const uint8_t *data, size_t length) { + // Get direct access to the virtual device's serial port + auto &serial = Serial; + serial.injectInput(data, length); +} + +std::vector SimHarness::GetSerialOutput() { + // Get direct access to the virtual device's serial port + auto &serial = Serial; + return serial.getOutputBuffer(); +} + +// Focus protocol helper implementations +std::string SimHarness::SendFocusCommand(const std::string &command) { + // Ensure command ends with newline + std::string cmd = command; + if (cmd.empty() || cmd.back() != '\n') { + cmd += '\n'; + } + + // Send command + SendString(cmd); + + // Run cycles until we get a complete response + // (ends with \r\n.\r\n) + std::string response; + size_t max_cycles = 100; // Prevent infinite loops + size_t cycles = 0; + + while (cycles++ < max_cycles) { + RunCycle(); + response = GetSerialOutputAsString(); + if (IsFocusResponse(response)) break; + } + + return StripFocusTerminator(response); +} + +bool SimHarness::IsFocusResponse(const std::string &response) { + static const std::string terminator = "\r\n.\r\n"; + return response.length() >= terminator.length() && + response.substr(response.length() - terminator.length()) == terminator; +} + +std::string SimHarness::StripFocusTerminator(const std::string &response) { + static const std::string terminator = "\r\n.\r\n"; + if (IsFocusResponse(response)) { + return response.substr(0, response.length() - terminator.length()); + } + return response; +} } // namespace testing } // namespace kaleidoscope diff --git a/testing/SimHarness.h b/testing/SimHarness.h index 424a43cab1..f070b19102 100644 --- a/testing/SimHarness.h +++ b/testing/SimHarness.h @@ -18,6 +18,8 @@ #include // for size_t #include // for uint8_t +#include +#include #include "kaleidoscope/KeyAddr.h" // for KeyAddr #include "testing/gtest.h" // IWYU pragma: keep @@ -37,6 +39,23 @@ class SimHarness { void SetCycleTime(uint8_t millis); uint8_t CycleTime() const; + // Serial support + void ProcessSerialInput(); + void SendString(const std::string &str) { + SendSerialData(reinterpret_cast(str.c_str()), str.length()); + } + void SendSerialData(const uint8_t *data, size_t length); + std::vector GetSerialOutput(); + std::string GetSerialOutputAsString() { + auto output = GetSerialOutput(); + return std::string(output.begin(), output.end()); + } + + // Focus protocol helpers + std::string SendFocusCommand(const std::string &command); + static bool IsFocusResponse(const std::string &response); + static std::string StripFocusTerminator(const std::string &response); + private: uint8_t millis_per_cycle_ = 1; }; diff --git a/tests/simulator/serial/focus_version/focus_version.ino b/tests/simulator/serial/focus_version/focus_version.ino new file mode 100644 index 0000000000..bc15fbb67e --- /dev/null +++ b/tests/simulator/serial/focus_version/focus_version.ino @@ -0,0 +1,44 @@ +// -*- mode: c++ -*- +// Copyright 2016 Keyboardio, inc. +// See "LICENSE" for license details + +#include "Kaleidoscope.h" +#include "Kaleidoscope-FocusSerial.h" + +#define KALEIDOSCOPE_FIRMWARE_VERSION "0.1.2" + +#include "Kaleidoscope-FirmwareVersion.h" +// *INDENT-OFF* +// *INDENT-OFF* + +KEYMAPS( + [0] = KEYMAP_STACKED + ( + XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX + ,XXX + + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX ,XXX + ,XXX ,XXX ,XXX ,XXX + ,XXX + ) +) // KEYMAPS( + +// *INDENT-ON* + + +KALEIDOSCOPE_INIT_PLUGINS(Focus, FirmwareVersion); + +void setup() { + Kaleidoscope.setup(); +} + +void loop() { + Kaleidoscope.loop(); +} \ No newline at end of file diff --git a/tests/simulator/serial/focus_version/sketch.json b/tests/simulator/serial/focus_version/sketch.json new file mode 100644 index 0000000000..9931687ee5 --- /dev/null +++ b/tests/simulator/serial/focus_version/sketch.json @@ -0,0 +1,6 @@ +{ + "cpu": { + "fqbn": "keyboardio:virtual:model01", + "port": "" + } +} \ No newline at end of file diff --git a/tests/simulator/serial/focus_version/sketch.yaml b/tests/simulator/serial/focus_version/sketch.yaml new file mode 100644 index 0000000000..4d94810065 --- /dev/null +++ b/tests/simulator/serial/focus_version/sketch.yaml @@ -0,0 +1 @@ +default_fqbn: keyboardio:virtual:model01 diff --git a/tests/simulator/serial/focus_version/test/testcase.cpp b/tests/simulator/serial/focus_version/test/testcase.cpp new file mode 100644 index 0000000000..896385ec22 --- /dev/null +++ b/tests/simulator/serial/focus_version/test/testcase.cpp @@ -0,0 +1,28 @@ +#include "testing/setup-googletest.h" +#include "Kaleidoscope.h" +#include +#include "gmock/gmock.h" // For matchers like Eq() + +SETUP_GOOGLETEST(); + +namespace kaleidoscope { +namespace testing { +namespace { + +class FocusVersionCommand : public VirtualDeviceTest {}; + +TEST_F(FocusVersionCommand, SendVersionCommand) { + // Run a cycle to initialize + RunCycle(); + + // Send version command and get response using new helper + auto response = sim_.SendFocusCommand("version"); + + // Response should be exactly the version number + EXPECT_THAT(response, ::testing::Eq("0.1.2")) + << "Expected version response '0.1.2', got: '" << response << "'"; +} + +} // namespace +} // namespace testing +} // namespace kaleidoscope \ No newline at end of file