From 267322c9ea9e7c5e4a7fe03da641ac7bcbf57156 Mon Sep 17 00:00:00 2001 From: GreenWizard Date: Sat, 30 Dec 2023 22:37:28 +0100 Subject: [PATCH] very big update. Reorganized the code, added a command processor, tests. --- .../tea_poor/lib/Arduino/ArduinoEnvironment.h | 15 ++++ .../RemoteControl.cpp | 0 .../RemoteControl.h | 0 .../WaterPumpController.cpp | 0 .../WaterPumpController.h | 0 .../lib/CommandProcessor/CommandProcessor.cpp | 58 ++++++++++++++ .../lib/CommandProcessor/CommandProcessor.h | 30 +++++++ .../WaterPumpScheduler.cpp | 7 +- .../WaterPumpScheduler.h | 17 ++-- .../tea_poor/lib/interfaces/IEnvironment.h | 13 +++ .../{WaterPump => interfaces}/IWaterPump.h | 0 .../lib/interfaces/IWaterPumpSchedulerAPI.h | 30 +++++++ controller/tea_poor/platformio.ini | 4 +- controller/tea_poor/src/main.cpp | 78 +++++------------- controller/tea_poor/src/secrets.h.example | 4 + controller/tea_poor/test/test_native/main.cpp | 13 +++ .../test_native/tests/CommandProcessor_test.h | 79 +++++++++++++++++++ .../WaterPumpScheduler_test.h} | 25 +----- .../test_native/tests/mocks/FakeEnvironment.h | 19 +++++ .../test_native/tests/mocks/FakeWaterPump.h | 18 +++++ .../tests/mocks/FakeWaterPumpSchedulerAPI.h | 26 ++++++ 21 files changed, 336 insertions(+), 100 deletions(-) create mode 100644 controller/tea_poor/lib/Arduino/ArduinoEnvironment.h rename controller/tea_poor/lib/{RemoteControl => Arduino}/RemoteControl.cpp (100%) rename controller/tea_poor/lib/{RemoteControl => Arduino}/RemoteControl.h (100%) rename controller/tea_poor/lib/{WaterPumpController => Arduino}/WaterPumpController.cpp (100%) rename controller/tea_poor/lib/{WaterPumpController => Arduino}/WaterPumpController.h (100%) create mode 100644 controller/tea_poor/lib/CommandProcessor/CommandProcessor.cpp create mode 100644 controller/tea_poor/lib/CommandProcessor/CommandProcessor.h rename controller/tea_poor/lib/{WaterPump => WaterPumpScheduler}/WaterPumpScheduler.cpp (86%) rename controller/tea_poor/lib/{WaterPump => WaterPumpScheduler}/WaterPumpScheduler.h (79%) create mode 100644 controller/tea_poor/lib/interfaces/IEnvironment.h rename controller/tea_poor/lib/{WaterPump => interfaces}/IWaterPump.h (100%) create mode 100644 controller/tea_poor/lib/interfaces/IWaterPumpSchedulerAPI.h create mode 100644 controller/tea_poor/test/test_native/main.cpp create mode 100644 controller/tea_poor/test/test_native/tests/CommandProcessor_test.h rename controller/tea_poor/test/test_native/{WaterPumpScheduler_test.cpp => tests/WaterPumpScheduler_test.h} (67%) create mode 100644 controller/tea_poor/test/test_native/tests/mocks/FakeEnvironment.h create mode 100644 controller/tea_poor/test/test_native/tests/mocks/FakeWaterPump.h create mode 100644 controller/tea_poor/test/test_native/tests/mocks/FakeWaterPumpSchedulerAPI.h diff --git a/controller/tea_poor/lib/Arduino/ArduinoEnvironment.h b/controller/tea_poor/lib/Arduino/ArduinoEnvironment.h new file mode 100644 index 0000000..bbb5a01 --- /dev/null +++ b/controller/tea_poor/lib/Arduino/ArduinoEnvironment.h @@ -0,0 +1,15 @@ +// Arduino environment +#ifndef ARDUINO_ENVIRONMENT_H +#define ARDUINO_ENVIRONMENT_H + +#include +#include + +class ArduinoEnvironment : public IEnvironment { + public: + unsigned long time() const override { + return millis(); + } +}; + +#endif // ARDUINO_ENVIRONMENT_H \ No newline at end of file diff --git a/controller/tea_poor/lib/RemoteControl/RemoteControl.cpp b/controller/tea_poor/lib/Arduino/RemoteControl.cpp similarity index 100% rename from controller/tea_poor/lib/RemoteControl/RemoteControl.cpp rename to controller/tea_poor/lib/Arduino/RemoteControl.cpp diff --git a/controller/tea_poor/lib/RemoteControl/RemoteControl.h b/controller/tea_poor/lib/Arduino/RemoteControl.h similarity index 100% rename from controller/tea_poor/lib/RemoteControl/RemoteControl.h rename to controller/tea_poor/lib/Arduino/RemoteControl.h diff --git a/controller/tea_poor/lib/WaterPumpController/WaterPumpController.cpp b/controller/tea_poor/lib/Arduino/WaterPumpController.cpp similarity index 100% rename from controller/tea_poor/lib/WaterPumpController/WaterPumpController.cpp rename to controller/tea_poor/lib/Arduino/WaterPumpController.cpp diff --git a/controller/tea_poor/lib/WaterPumpController/WaterPumpController.h b/controller/tea_poor/lib/Arduino/WaterPumpController.h similarity index 100% rename from controller/tea_poor/lib/WaterPumpController/WaterPumpController.h rename to controller/tea_poor/lib/Arduino/WaterPumpController.h diff --git a/controller/tea_poor/lib/CommandProcessor/CommandProcessor.cpp b/controller/tea_poor/lib/CommandProcessor/CommandProcessor.cpp new file mode 100644 index 0000000..c776abf --- /dev/null +++ b/controller/tea_poor/lib/CommandProcessor/CommandProcessor.cpp @@ -0,0 +1,58 @@ +#include "CommandProcessor.h" +#include +#include + +bool isValidIntNumber(const char *str, const int maxValue, const int minValue=0) { + const int len = strlen(str); + if (len < 1) return false; + // check that string contains only digits + // first character can be '-' for negative numbers + if ((str[0] != '-') && !isdigit(str[0])) return false; + for (int i = 1; i < len; i++) { + if (!isdigit(str[i])) return false; + } + // check that number is in range + const int value = atoi(str); + if (value < minValue) return false; + if (maxValue <= value) return false; + return true; +} + +std::string CommandProcessor::status() { + std::stringstream response; + response << "{"; + // send water threshold + response << "\"water threshold\": " << _waterPumpSafeThreshold << ", "; + // send water pump status + const auto waterPumpStatus = _waterPump->status(); + const auto now = _env->time(); + const auto timeLeft = waterPumpStatus.isRunning ? waterPumpStatus.stopTime - now : 0; + response + << "\"pump\": {" + << " \"running\": " << (waterPumpStatus.isRunning ? "true, " : "false, ") + << " \"time left\": " << timeLeft + << "}"; + // end of water pump status + /////////////////////////////////// + // send remote control status + // response << "\"remote control\": " << remoteControl.asJSONString(); + // end of JSON + response << "}"; + + return response.str(); +} + +std::string CommandProcessor::pour_tea(const char *milliseconds) { + if (!isValidIntNumber(milliseconds, _waterPumpSafeThreshold)) { + // send error message as JSON + return std::string("{ \"error\": \"invalid milliseconds value\" }"); + } + // start pouring tea + _waterPump->start( atoi(milliseconds), _env->time() ); + return status(); +} + +std::string CommandProcessor::stop() { + _waterPump->stop(); + return status(); +} \ No newline at end of file diff --git a/controller/tea_poor/lib/CommandProcessor/CommandProcessor.h b/controller/tea_poor/lib/CommandProcessor/CommandProcessor.h new file mode 100644 index 0000000..a7770a0 --- /dev/null +++ b/controller/tea_poor/lib/CommandProcessor/CommandProcessor.h @@ -0,0 +1,30 @@ +// CommandProcessor class definition +#ifndef COMMANDPROCESSOR_H +#define COMMANDPROCESSOR_H + +#include +#include +#include + +// This class is used to process incoming commands +class CommandProcessor { + public: + CommandProcessor( + int waterPumpSafeThreshold, + const IEnvironmentPtr env, + const IWaterPumpSchedulerAPIPtr waterPump + ) : + _waterPumpSafeThreshold(waterPumpSafeThreshold), + _env(env), + _waterPump(waterPump) + {} + + std::string status(); + std::string pour_tea(const char *milliseconds); + std::string stop(); + private: + const int _waterPumpSafeThreshold; + const IEnvironmentPtr _env; + const IWaterPumpSchedulerAPIPtr _waterPump; +}; +#endif // COMMANDPROCESSOR_H \ No newline at end of file diff --git a/controller/tea_poor/lib/WaterPump/WaterPumpScheduler.cpp b/controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.cpp similarity index 86% rename from controller/tea_poor/lib/WaterPump/WaterPumpScheduler.cpp rename to controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.cpp index eb9ae02..edf3634 100644 --- a/controller/tea_poor/lib/WaterPump/WaterPumpScheduler.cpp +++ b/controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.cpp @@ -29,9 +29,6 @@ void WaterPumpScheduler::tick(unsigned long currentTimeMs) { } } -WaterPumpScheduler::WaterPumpStatus WaterPumpScheduler::status() { - return { - _waterPump->isRunning(), - _stopTime - }; +WaterPumpStatus WaterPumpScheduler::status() { + return WaterPumpStatus(_waterPump->isRunning(), _stopTime); } \ No newline at end of file diff --git a/controller/tea_poor/lib/WaterPump/WaterPumpScheduler.h b/controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.h similarity index 79% rename from controller/tea_poor/lib/WaterPump/WaterPumpScheduler.h rename to controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.h index 84a6145..4e8aa66 100644 --- a/controller/tea_poor/lib/WaterPump/WaterPumpScheduler.h +++ b/controller/tea_poor/lib/WaterPumpScheduler/WaterPumpScheduler.h @@ -1,12 +1,13 @@ #ifndef WATERPUMPSCHEDULER_H #define WATERPUMPSCHEDULER_H -#include "IWaterPump.h" +#include +#include // This class is responsible for scheduling water pump // It is used to make sure that water pump is running for a limited time // It is also ensuring that water pump is stopped if not needed -class WaterPumpScheduler { +class WaterPumpScheduler : public IWaterPumpSchedulerAPI { private: IWaterPumpPtr _waterPump; unsigned long _stopTime = 0; @@ -18,16 +19,12 @@ class WaterPumpScheduler { ~WaterPumpScheduler(); void setup(); - void stop(); // for simplicity and testability we are passing current time as parameter - void start(unsigned long runTimeMs, unsigned long currentTimeMs); void tick(unsigned long currentTimeMs); - // pump status - struct WaterPumpStatus { - bool isRunning; - unsigned long stopTime; - }; - WaterPumpStatus status(); + // Public API + void start(unsigned long runTimeMs, unsigned long currentTimeMs) override; + void stop() override; + WaterPumpStatus status() override; }; #endif \ No newline at end of file diff --git a/controller/tea_poor/lib/interfaces/IEnvironment.h b/controller/tea_poor/lib/interfaces/IEnvironment.h new file mode 100644 index 0000000..1992884 --- /dev/null +++ b/controller/tea_poor/lib/interfaces/IEnvironment.h @@ -0,0 +1,13 @@ +#ifndef IENVIRONMENT_H +#define IENVIRONMENT_H + +#include + +class IEnvironment { + public: + virtual unsigned long time() const = 0; + virtual ~IEnvironment() {} +}; + +typedef std::shared_ptr IEnvironmentPtr; +#endif // IENVIRONMENT_H \ No newline at end of file diff --git a/controller/tea_poor/lib/WaterPump/IWaterPump.h b/controller/tea_poor/lib/interfaces/IWaterPump.h similarity index 100% rename from controller/tea_poor/lib/WaterPump/IWaterPump.h rename to controller/tea_poor/lib/interfaces/IWaterPump.h diff --git a/controller/tea_poor/lib/interfaces/IWaterPumpSchedulerAPI.h b/controller/tea_poor/lib/interfaces/IWaterPumpSchedulerAPI.h new file mode 100644 index 0000000..b82df7d --- /dev/null +++ b/controller/tea_poor/lib/interfaces/IWaterPumpSchedulerAPI.h @@ -0,0 +1,30 @@ +// IWaterPumpSchedulerAPI interface +#ifndef IWATERPUMPSCHEDULERAPI_H +#define IWATERPUMPSCHEDULERAPI_H + +#include +// pump status +struct WaterPumpStatus { +public: + bool isRunning; + unsigned long stopTime; + // copy constructor + WaterPumpStatus(const WaterPumpStatus &other) { + isRunning = other.isRunning; + stopTime = other.stopTime; + } + WaterPumpStatus(bool isRunning, unsigned long stopTime) : isRunning(isRunning), stopTime(stopTime) {} + // default constructor + WaterPumpStatus() : isRunning(false), stopTime(0) {} +}; + +class IWaterPumpSchedulerAPI { +public: + virtual ~IWaterPumpSchedulerAPI() {} + virtual void stop() = 0; + virtual void start(unsigned long runTimeMs, unsigned long currentTimeMs) = 0; + virtual WaterPumpStatus status() = 0; +}; + +using IWaterPumpSchedulerAPIPtr = std::shared_ptr; +#endif \ No newline at end of file diff --git a/controller/tea_poor/platformio.ini b/controller/tea_poor/platformio.ini index 82d27b9..fd827a9 100644 --- a/controller/tea_poor/platformio.ini +++ b/controller/tea_poor/platformio.ini @@ -28,9 +28,7 @@ build_flags = -Wall -Wextra -Wunused -static -static-libgcc -static-libstdc++ ; ignore libraries that are only for the Arduino -lib_ignore = - RemoteControl - WaterPumpController +lib_ignore = Arduino test_ignore = test_uno_r4_wifi [platformio] diff --git a/controller/tea_poor/src/main.cpp b/controller/tea_poor/src/main.cpp index b439390..3023273 100644 --- a/controller/tea_poor/src/main.cpp +++ b/controller/tea_poor/src/main.cpp @@ -3,94 +3,56 @@ #include #include #include +#include #include "secrets.h" #include +#include + +IEnvironmentPtr env = std::make_shared(); + // Setting up water pump -WaterPumpScheduler waterPump( +auto waterPump = std::make_shared( std::make_shared( WATER_PUMP_DIRECTION_PIN, WATER_PUMP_BRAKE_PIN, WATER_PUMP_POWER_PIN ) ); -// Just for safety reasons, we don't want to pour tea for too long -// Their is no reason to make it configurable and add unnecessary complexity -const int WATER_PUMP_SAFE_THRESHOLD = 10 * 1000; // setting up remote control RemoteControl remoteControl(WIFI_SSID, WIFI_PASSWORD); -void _sendSystemStatus(std::ostream& response) { - response << "{"; - // send water threshold - response << "\"water threshold\": " << WATER_PUMP_SAFE_THRESHOLD << ","; - // send water pump status - const auto waterPumpStatus = waterPump.status(); - const unsigned long timeLeft = - waterPumpStatus.isRunning ? - waterPumpStatus.stopTime - millis() : - 0; - response - << "\"pump\": {" - << " \"running\": " << (waterPumpStatus.isRunning ? "true, " : "false, ") - << " \"time left\": " << timeLeft - << "}"; - // end of water pump status - /////////////////////////////////// - // send remote control status - response << "\"remote control\": " << remoteControl.asJSONString(); - // end of JSON - response << "}"; -} - -bool isValidIntNumber(const char *str, const int maxValue, const int minValue=0) { - if (strlen(str) < 1) return false; - const int value = atoi(str); - if (value < minValue) return false; - if (maxValue <= value) return false; - return true; -} - -void pour_tea(const char *milliseconds, std::ostream &res) { - if (!isValidIntNumber(milliseconds, WATER_PUMP_SAFE_THRESHOLD)) { - // send error message as JSON - res << "{ \"error\": \"invalid milliseconds value\" }"; - return; - } - // start pouring tea - waterPump.start( atoi(milliseconds), millis() ); - _sendSystemStatus(res); -} +// build command processor +CommandProcessor commandProcessor( + WATER_PUMP_SAFE_THRESHOLD, + env, + waterPump +); void setup() { Serial.begin(9600); - waterPump.setup(); - // TODO: find a way to remove redundant code with string streams + waterPump->setup(); remoteControl.setup([](Application &app) { app.get("/pour_tea", [](Request &req, Response &res) { char milliseconds[64]; req.query("milliseconds", milliseconds, 64); - std::stringstream response; - pour_tea(milliseconds, response); - res.println(response.str().c_str()); + const auto response = commandProcessor.pour_tea(milliseconds); + res.print(response.c_str()); }); // stop water pump app.get("/stop", [](Request &req, Response &res) { - waterPump.stop(); - std::stringstream response; - _sendSystemStatus(response); - res.println(response.str().c_str()); + const auto response = commandProcessor.stop(); + res.print(response.c_str()); }); // get system status app.get("/status", [](Request &req, Response &res) { - std::stringstream response; - _sendSystemStatus(response); - res.println(response.str().c_str()); + const auto response = commandProcessor.status(); + res.print(response.c_str()); }); }); } void loop() { - waterPump.tick(millis()); + waterPump->tick(millis()); remoteControl.process(); }; \ No newline at end of file diff --git a/controller/tea_poor/src/secrets.h.example b/controller/tea_poor/src/secrets.h.example index 84d12c9..4fe08d5 100644 --- a/controller/tea_poor/src/secrets.h.example +++ b/controller/tea_poor/src/secrets.h.example @@ -11,4 +11,8 @@ const int WATER_PUMP_DIRECTION_PIN = 12; const int WATER_PUMP_BRAKE_PIN = 9; const int WATER_PUMP_POWER_PIN = 3; +// Just for safety reasons, we don't want to pour tea for too long +// Their is no reason to make it configurable and add unnecessary complexity +const int WATER_PUMP_SAFE_THRESHOLD = 10 * 1000; + #endif // SECRETS_H \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/main.cpp b/controller/tea_poor/test/test_native/main.cpp new file mode 100644 index 0000000..b6f09e9 --- /dev/null +++ b/controller/tea_poor/test/test_native/main.cpp @@ -0,0 +1,13 @@ +#include + +// include tests +#include "tests/WaterPumpScheduler_test.h" +#include "tests/CommandProcessor_test.h" + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); // Intentionally ignoring the return value + (void)result; // Silence unused variable warning + // Always return zero-code and allow PlatformIO to parse results + return 0; +} \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/tests/CommandProcessor_test.h b/controller/tea_poor/test/test_native/tests/CommandProcessor_test.h new file mode 100644 index 0000000..291f814 --- /dev/null +++ b/controller/tea_poor/test/test_native/tests/CommandProcessor_test.h @@ -0,0 +1,79 @@ +#include +#include +#include "mocks/FakeWaterPumpSchedulerAPI.h" +#include "mocks/FakeEnvironment.h" + +// test that pour_tea() method returns error message if milliseconds: +// - greater than threshold +// - less than 0 +// - empty string +// - not a number +TEST(CommandProcessor, pour_tea_invalid_milliseconds) { + const auto EXPECTED_ERROR_MESSAGE = "{ \"error\": \"invalid milliseconds value\" }"; + CommandProcessor commandProcessor(123, nullptr, nullptr); + + // array of invalid parameters + const char *PARAMS[] = { "1234", "-1", "", "abc" }; + for (auto param : PARAMS) { + const auto response = commandProcessor.pour_tea(param); + ASSERT_EQ(response, EXPECTED_ERROR_MESSAGE); + } +} + +// test that start pouring tea by calling pour_tea() method and its stops after T milliseconds +TEST(CommandProcessor, pour_tea) { + auto env = std::make_shared(); + env->time(2343); + auto waterPump = std::make_shared(); + CommandProcessor commandProcessor(10000, env, waterPump); + const auto response = commandProcessor.pour_tea("1234"); + ASSERT_EQ(waterPump->_log, "start(1234, 2343)\n"); +} + +// test that stop() method stops pouring tea +TEST(CommandProcessor, stop) { + auto env = std::make_shared(); + auto waterPump = std::make_shared(); + CommandProcessor commandProcessor(123, env, waterPump); + const auto response = commandProcessor.stop(); + ASSERT_EQ(waterPump->_log, "stop()\n"); +} + +// test that status() method returns JSON string with water pump status +TEST(CommandProcessor, status) { + auto env = std::make_shared(); + auto waterPump = std::make_shared(); + CommandProcessor commandProcessor(123, env, waterPump); + const auto response = commandProcessor.status(); + ASSERT_EQ(response, "{" + "\"water threshold\": 123, " + "\"pump\": {" + " \"running\": false, " + " \"time left\": 0" + "}" + "}" + ); +} + +// test that status() method returns JSON string with actual time left +TEST(CommandProcessor, status_running) { + auto env = std::make_shared(); + auto waterPump = std::make_shared(); + CommandProcessor commandProcessor(12345, env, waterPump); + + commandProcessor.pour_tea("1123"); + + env->time(123); + waterPump->_status.isRunning = true; + waterPump->_status.stopTime = 1123; + + const auto response = commandProcessor.status(); + ASSERT_EQ(response, "{" + "\"water threshold\": 12345, " + "\"pump\": {" + " \"running\": true, " + " \"time left\": 1000" + "}" + "}" + ); +} \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/WaterPumpScheduler_test.cpp b/controller/tea_poor/test/test_native/tests/WaterPumpScheduler_test.h similarity index 67% rename from controller/tea_poor/test/test_native/WaterPumpScheduler_test.cpp rename to controller/tea_poor/test/test_native/tests/WaterPumpScheduler_test.h index 2b3b40f..138541b 100644 --- a/controller/tea_poor/test/test_native/WaterPumpScheduler_test.cpp +++ b/controller/tea_poor/test/test_native/tests/WaterPumpScheduler_test.h @@ -1,22 +1,7 @@ -// I wasn't able to run tests at all. Run them locally and confirm that they are working. -// Its either a local problem or a problem with the configuration of the project. -// Further goes a sketch of the tests, but I wasn't able to run them. #include +#include "mocks/FakeWaterPump.h" #include -// Fake water pump -class FakeWaterPump : public IWaterPump { -private: - bool _isRunning = false; -public: - void setup() override { _isRunning = false; } - void start() override { _isRunning = true; } - void stop() override { _isRunning = false; } - - bool isRunning() const override { return _isRunning; } -}; -// End of fake water pump - // test that pump is stopping after given time TEST(WaterPumpScheduler, test_pump_stops_after_given_time) { // random time between 1 and 10 seconds @@ -61,12 +46,4 @@ TEST(WaterPumpScheduler, test_pump_is_periodically_forced_to_stop_after_given_ti waterPumpScheduler.tick(currentTimeMs); ASSERT_FALSE(fakeWaterPump->isRunning()); // pump should be stopped } -} - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); // Intentionally ignoring the return value - (void)result; // Silence unused variable warning - // Always return zero-code and allow PlatformIO to parse results - return 0; } \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/tests/mocks/FakeEnvironment.h b/controller/tea_poor/test/test_native/tests/mocks/FakeEnvironment.h new file mode 100644 index 0000000..51407f8 --- /dev/null +++ b/controller/tea_poor/test/test_native/tests/mocks/FakeEnvironment.h @@ -0,0 +1,19 @@ +#ifndef FAKE_ENVIRONMENT_H +#define FAKE_ENVIRONMENT_H + +#include + +class FakeEnvironment : public IEnvironment { +public: + unsigned long time() const override { + return _time; + } + + void time(unsigned long time) { + _time = time; + } +private: + unsigned long _time = 0; +}; + +#endif \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPump.h b/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPump.h new file mode 100644 index 0000000..2dcf154 --- /dev/null +++ b/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPump.h @@ -0,0 +1,18 @@ +#ifndef FAKE_WATER_PUMP_H +#define FAKE_WATER_PUMP_H + +#include + +// Fake water pump +class FakeWaterPump : public IWaterPump { +private: + bool _isRunning = false; +public: + void setup() override { _isRunning = false; } + void start() override { _isRunning = true; } + void stop() override { _isRunning = false; } + + bool isRunning() const override { return _isRunning; } +}; + +#endif // FAKE_WATER_PUMP_H \ No newline at end of file diff --git a/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPumpSchedulerAPI.h b/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPumpSchedulerAPI.h new file mode 100644 index 0000000..896046a --- /dev/null +++ b/controller/tea_poor/test/test_native/tests/mocks/FakeWaterPumpSchedulerAPI.h @@ -0,0 +1,26 @@ +// FakeWaterPumpSchedulerAPI.h is a mock class for WaterPumpSchedulerAPI.h +#ifndef FAKE_WATER_PUMP_SCHEDULER_API_H +#define FAKE_WATER_PUMP_SCHEDULER_API_H + +#include +#include + +class FakeWaterPumpSchedulerAPI : public IWaterPumpSchedulerAPI { +public: + void stop() override { + _log += "stop()\n"; + } + + void start(unsigned long runTimeMs, unsigned long currentTimeMs) override { + _log += "start(" + std::to_string(runTimeMs) + ", " + std::to_string(currentTimeMs) + ")\n"; + } + + WaterPumpStatus status() override { + return _status; + } + + WaterPumpStatus _status; + std::string _log; +}; + +#endif \ No newline at end of file