Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for testing focus commands to the simulator #1454

Merged
merged 3 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
57 changes: 57 additions & 0 deletions testing/SimHarness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> 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
19 changes: 19 additions & 0 deletions testing/SimHarness.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include <cstddef> // for size_t
#include <cstdint> // for uint8_t
#include <vector>
#include <string>

#include "kaleidoscope/KeyAddr.h" // for KeyAddr
#include "testing/gtest.h" // IWYU pragma: keep
Expand All @@ -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<const uint8_t *>(str.c_str()), str.length());
}
void SendSerialData(const uint8_t *data, size_t length);
std::vector<uint8_t> 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;
};
Expand Down
44 changes: 44 additions & 0 deletions tests/simulator/serial/focus_version/focus_version.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// -*- mode: c++ -*-
// Copyright 2016 Keyboardio, inc. <[email protected]>
// 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();
}
6 changes: 6 additions & 0 deletions tests/simulator/serial/focus_version/sketch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cpu": {
"fqbn": "keyboardio:virtual:model01",
"port": ""
}
}
1 change: 1 addition & 0 deletions tests/simulator/serial/focus_version/sketch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default_fqbn: keyboardio:virtual:model01
28 changes: 28 additions & 0 deletions tests/simulator/serial/focus_version/test/testcase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "testing/setup-googletest.h"
#include "Kaleidoscope.h"
#include <iostream>
#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
Loading