From 68288a9866b53f4e2a496686d8c785597865c333 Mon Sep 17 00:00:00 2001 From: Zach Radlicz Date: Wed, 9 Apr 2025 14:20:41 -0500 Subject: [PATCH 1/2] cherry pick li710 changes into new branch refactored li710 for unit testing missed a 0x21 instead of 0x20 updated Li710 tests for the direct measuremetn refactor removed haar for testing put haar back in removed haar corectly this time replaced the adr in the diag str fixed observed li710 issues --- lib/Driver_-_Sensor | 2 +- src/FlightControl_Demo.cpp | 8 +- src/hardware/SDI12TalonAdapter.h | 54 ++++ test/CMakeLists.txt | 11 +- test/mocks/MockSDI12Talon.h | 39 +++ test/mocks/Particle.h | 408 ++++++++++++++++++++++-- test/unit/Driver_-_Li710/Li710Test.cpp | 423 +++++++++++++++++++++++++ 7 files changed, 908 insertions(+), 37 deletions(-) create mode 100644 src/hardware/SDI12TalonAdapter.h create mode 100644 test/mocks/MockSDI12Talon.h create mode 100644 test/unit/Driver_-_Li710/Li710Test.cpp diff --git a/lib/Driver_-_Sensor b/lib/Driver_-_Sensor index d13c2ac..afef963 160000 --- a/lib/Driver_-_Sensor +++ b/lib/Driver_-_Sensor @@ -1 +1 @@ -Subproject commit d13c2ac5771b446bc8010937e9218b6a80fe0ff7 +Subproject commit afef96338232e397656a907ce12338a4c9cad288 diff --git a/src/FlightControl_Demo.cpp b/src/FlightControl_Demo.cpp index 377d772..dc84e28 100644 --- a/src/FlightControl_Demo.cpp +++ b/src/FlightControl_Demo.cpp @@ -59,6 +59,9 @@ int configurePowerSave(int desiredPowerSaveMode); #include #include +#include "hardware/SDI12TalonAdapter.h" +#include "platform/ParticleTimeProvider.h" + const String firmwareVersion = "2.9.11"; const String schemaVersion = "2.2.9"; @@ -75,6 +78,7 @@ I2CTalon i2c(0, 0x21); //Instantiate I2C talon with alt - null port and hardware SDI12Talon sdi12(0, 0x14); //Instantiate SDI12 talon with alt - null port and hardware v1.4 PCAL9535A ioAlpha(0x20); PCAL9535A ioBeta(0x21); +SDI12TalonAdapter realSdi12(sdi12); String globalNodeID = ""; //Store current node ID @@ -114,7 +118,7 @@ TDR315H soil2(sdi12, 0, 0); //Instantiate soil sensor with default ports and unk TDR315H soil3(sdi12, 0, 0); //Instantiate soil sensor with default ports and unknown version, pass over SDI12 Talon interface Hedorah gas(0, 0, 0x10); //Instantiate CO2 sensor with default ports and v1.0 hardware // T9602 humidity(0, 0, 0x00); //Instantiate Telair T9602 with default ports and version v0.0 -LI710 et(sdi12, 0, 0); //Instantiate ET sensor with default ports and unknown version, pass over SDI12 Talon interface +LI710 et(realTimeProvider, realSdi12, 0, 0); //Instantiate ET sensor with default ports and unknown version, pass over SDI12 Talon interface BaroVue10 campPressure(sdi12, 0, 0x00); // Instantiate Barovue10 with default ports and v0.0 hardware const uint8_t numSensors = 7; //Number must match the number of objects defined in `sensors` array @@ -1077,7 +1081,7 @@ int wakeSensors() for(int s = 0; s < numSensors; s++) { if(sensors[s]->getTalonPort() != 0) { logger.enableData(sensors[s]->getTalonPort(), true); //Turn on data for given port - sensors[s]->wake(); //Wake each sensor + sensors[s]->wake(realTimeProvider); //Wake each sensor logger.enableData(sensors[s]->getTalonPort(), false); //Turn data back off for given port } } diff --git a/src/hardware/SDI12TalonAdapter.h b/src/hardware/SDI12TalonAdapter.h new file mode 100644 index 0000000..70bc2ee --- /dev/null +++ b/src/hardware/SDI12TalonAdapter.h @@ -0,0 +1,54 @@ +// src/hardware/SDI12TalonAdapter.h + +#ifndef SDI12_TALON_ADAPTER_H +#define SDI12_TALON_ADAPTER_H + +#include "ISDI12Talon.h" +#include "SDI12Talon.h" + +/** + * @brief Adapter implementing ISDI12Talon interface + * + * Adapts the concrete SDI12Talon class to the ISDI12Talon interface + * for dependency injection and testing purposes. + */ +class SDI12TalonAdapter : public ISDI12Talon { +public: + /** + * @brief Constructor that takes a reference to a concrete SDI12Talon + * @param talon The concrete SDI12Talon implementation to delegate to + */ + SDI12TalonAdapter(SDI12Talon& talon) : talon(talon) {} + ~SDI12TalonAdapter() override = default; + + // SDI12 communication methods + int getAddress() override { return talon.getAddress(); } + String sendCommand(String command) override { return talon.sendCommand(command); } + String command(String commandStr, int address) override { return talon.command(commandStr, address); } + int startMeasurment(int Address) override { return talon.startMeasurment(Address); } + int startMeasurmentIndex(int index, int Address) override { return talon.startMeasurmentIndex(index, Address); } + String continuousMeasurmentCRC(int Measure, int Address) override { return talon.continuousMeasurmentCRC(Measure, Address); } + bool testCRC(String message) override { return talon.testCRC(message); } + + // Port management methods + int enableData(uint8_t port, bool state) override { return talon.enableData(port, state); } + int enablePower(uint8_t port, bool state) override { return talon.enablePower(port, state); } + void disableDataAll() override { talon.disableDataAll(); } + uint8_t getNumPorts() override { return talon.getNumPorts(); } + + // Sensor interrogation + bool isPresent() override { return talon.isPresent(); } + + // Error handling and state reporting + //int throwError(uint32_t error) override { return talon.throwError(error); } + String getSensorPortString() override { return talon.getSensorPortString(); } + String getTalonPortString() override { return talon.getTalonPortString(); } + uint8_t getSensorPort() override { return talon.getSensorPort(); } + uint8_t getTalonPort() override { return talon.getTalonPort(); } + int restart() override { return talon.restart(); } + +private: + SDI12Talon& talon; // Reference to the concrete implementation +}; + +#endif // SDI12_TALON_ADAPTER_H \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index af8e3f2..22044ee 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,7 @@ # FlightControl_Demo/test/CMakeLists.txt +#allow debugging +set(CMAKE_BUILD_TYPE Debug) + # Add GoogleTest add_subdirectory(external/googletest) @@ -36,8 +39,12 @@ add_executable(unit_tests main.cpp # Kestrel tests - unit/Driver_-_Kestrel/Driver_-_KestrelSetupTests.cpp - unit/Driver_-_Kestrel/Driver_-_KestrelFunctionTests.cpp + #unit/Driver_-_Kestrel/KestrelTest.cpp + #${CMAKE_SOURCE_DIR}/lib/Driver_-_Kestrel/src/Kestrel.cpp + + # Li710 tests + unit/Driver_-_Li710/Li710Test.cpp + ${CMAKE_SOURCE_DIR}/lib/Driver_-_Li710/src/Li710.cpp ) # Link against mocks and GoogleTest diff --git a/test/mocks/MockSDI12Talon.h b/test/mocks/MockSDI12Talon.h new file mode 100644 index 0000000..e4d332a --- /dev/null +++ b/test/mocks/MockSDI12Talon.h @@ -0,0 +1,39 @@ +#ifndef MOCK_SDI12_TALON_H +#define MOCK_SDI12_TALON_H + +#include +#include "ISDI12Talon.h" + +/** + * @brief Mock implementation of the ISDI12Talon interface for testing + */ +class MockSDI12Talon : public ISDI12Talon { +public: + // SDI12 communication methods + MOCK_METHOD(int, getAddress, (), (override)); + MOCK_METHOD(String, sendCommand, (String command), (override)); + MOCK_METHOD(String, command, (String commandStr, int address), (override)); + MOCK_METHOD(int, startMeasurment, (int Address), (override)); + MOCK_METHOD(int, startMeasurmentIndex, (int index, int Address), (override)); + MOCK_METHOD(String, continuousMeasurmentCRC, (int Measure, int Address), (override)); + MOCK_METHOD(bool, testCRC, (String message), (override)); + + // Port management methods + MOCK_METHOD(int, enableData, (uint8_t port, bool state), (override)); + MOCK_METHOD(int, enablePower, (uint8_t port, bool state), (override)); + MOCK_METHOD(void, disableDataAll, (), (override)); + MOCK_METHOD(uint8_t, getNumPorts, (), (override)); + + // Sensor interrogation + MOCK_METHOD(bool, isPresent, (), (override)); + + // Error handling and state reporting + //MOCK_METHOD(int, throwError, (uint32_t error), (override)); + MOCK_METHOD(String, getSensorPortString, (), (override)); + MOCK_METHOD(String, getTalonPortString, (), (override)); + MOCK_METHOD(uint8_t, getSensorPort, (), (override)); + MOCK_METHOD(uint8_t, getTalonPort, (), (override)); + MOCK_METHOD(int, restart, (), (override)); +}; + +#endif // MOCK_SDI12_TALON_H \ No newline at end of file diff --git a/test/mocks/Particle.h b/test/mocks/Particle.h index 31ed9a3..03ef082 100644 --- a/test/mocks/Particle.h +++ b/test/mocks/Particle.h @@ -1,45 +1,389 @@ -#pragma once +#ifndef MOCK_PARTICLE_H +#define MOCK_PARTICLE_H -#include "MockParticle.h" -#include -#include +// This file provides a minimal mock implementation of Particle's String class +// for testing purposes, without the need for actual Particle.h -// Mock Particle types and functions to satisfy dependencies -typedef uint8_t system_event_t; +#include +#include +#include +#include +#include // For std::min and std::max -// System event handlers -constexpr system_event_t TIME_CHANGED = 1; -constexpr system_event_t LOW_MEMORY = 2; +// Forward declaration +class StringSumHelper; -// Mock Particle functions -inline void System_on(system_event_t event, void (*handler)(system_event_t, int)) { - // Just do nothing in mock -} +/** + * Mock implementation of Particle's String class for testing + * + * This class implements the minimum functionality needed for testing Li710 + * and can be expanded as needed for other components. + */ +class String { +public: + // Constructors + String(const char *cstr = "") { + if (cstr) { + _buffer = strdup(cstr); + if (_buffer) { + _length = strlen(cstr); + _capacity = _length; + } + } + } + + String(const String &str) : String(str._buffer) {} + + explicit String(char c) { + _buffer = (char*)malloc(2); + if (_buffer) { + _buffer[0] = c; + _buffer[1] = 0; + _length = 1; + _capacity = 1; + } + } + + explicit String(int value, unsigned char base = 10) { + char buf[33]; + snprintf(buf, sizeof(buf), base == 10 ? "%d" : "%x", value); + *this = String(buf); + } + + explicit String(float value, int decimalPlaces = 2) { + char buf[33]; + snprintf(buf, sizeof(buf), "%.*f", decimalPlaces, value); + *this = String(buf); + } + + ~String() { + if (_buffer) free(_buffer); + } + + // Operators + String& operator = (const String &rhs) { + if (this == &rhs) return *this; + if (_buffer) free(_buffer); + if (rhs._buffer) { + _buffer = strdup(rhs._buffer); + _length = rhs._length; + _capacity = rhs._capacity; + } else { + _buffer = nullptr; + _length = 0; + _capacity = 0; + } + return *this; + } + + String& operator = (const char *cstr) { + if (_buffer) free(_buffer); + if (cstr) { + _buffer = strdup(cstr); + _length = strlen(cstr); + _capacity = _length; + } else { + _buffer = nullptr; + _length = 0; + _capacity = 0; + } + return *this; + } + + // Concatenation + unsigned char concat(const String &str) { + return concat(str._buffer, str._length); + } + + unsigned char concat(const char *cstr) { + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); + } + + unsigned char concat(const char *cstr, unsigned int length) { + if (!cstr || !length) return 0; + + unsigned int newLen = _length + length; + char *newBuffer = (char*)realloc(_buffer, newLen + 1); + if (!newBuffer) return 0; + + _buffer = newBuffer; + memcpy(_buffer + _length, cstr, length); + _buffer[newLen] = 0; + _length = newLen; + _capacity = newLen; + return 1; + } + + unsigned char concat(char c) { + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); + } + + unsigned char concat(int num) { + char buf[12]; + snprintf(buf, sizeof(buf), "%d", num); + return concat(buf, strlen(buf)); + } + + unsigned char concat(float num, int decimalPlaces = 2) { + char buf[20]; + snprintf(buf, sizeof(buf), "%.*f", decimalPlaces, num); + return concat(buf, strlen(buf)); + } + + String& operator += (const String &rhs) { + concat(rhs); + return *this; + } + + String& operator += (const char *cstr) { + concat(cstr); + return *this; + } + + String& operator += (char c) { + concat(c); + return *this; + } + + String& operator += (int num) { + concat(num); + return *this; + } + + // Comparison + unsigned char equals(const String &s) const { + if (_length != s._length) return 0; + if (!_buffer || !s._buffer) return (_buffer == s._buffer); + return (strcmp(_buffer, s._buffer) == 0); + } + + unsigned char equals(const char *cstr) const { + if (!_buffer || !cstr) return (_buffer == cstr); + return (strcmp(_buffer, cstr) == 0); + } + + unsigned char operator == (const String &rhs) const { + return equals(rhs); + } + + unsigned char operator == (const char *cstr) const { + return equals(cstr); + } + + unsigned char operator != (const String &rhs) const { + return !equals(rhs); + } + + unsigned char operator != (const char *cstr) const { + return !equals(cstr); + } + + // Access + char charAt(unsigned int index) const { + if (index >= _length || !_buffer) return 0; + return _buffer[index]; + } + + void setCharAt(unsigned int index, char c) { + if (index >= _length || !_buffer) return; + _buffer[index] = c; + } + + char operator [] (unsigned int index) const { + return charAt(index); + } + + char& operator [] (unsigned int index) { + static char dummy_writable_char; + if (index >= _length || !_buffer) { + dummy_writable_char = 0; + return dummy_writable_char; + } + return _buffer[index]; + } + + const char* c_str() const { + return _buffer ? _buffer : ""; + } + + operator const char*() const { + return c_str(); + } + + unsigned int length() const { + return _length; + } + + // Search + int indexOf(char ch) const { + return indexOf(ch, 0); + } + + int indexOf(char ch, unsigned int fromIndex) const { + if (!_buffer || fromIndex >= _length) return -1; + const char* temp = strchr(_buffer + fromIndex, ch); + if (temp == nullptr) return -1; + return temp - _buffer; + } + + int indexOf(const String &str) const { + return indexOf(str, 0); + } + + int indexOf(const String &str, unsigned int fromIndex) const { + if (!_buffer || !str._buffer || fromIndex >= _length) return -1; + const char* found = strstr(_buffer + fromIndex, str._buffer); + if (found == nullptr) return -1; + return found - _buffer; + } -inline int Time_now() { - return time(NULL); -} + void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const { + if (buf == nullptr || bufsize == 0) { + return; // Nothing to do + } -inline bool Particle_connected() { - return true; -} + // Always null-terminate the start of the buffer + buf[0] = '\0'; -inline bool Particle_syncTime() { - return true; -} + // Check if the source buffer is valid and index is within bounds + if (_buffer == nullptr || index >= _length) { + return; // Nothing to copy + } + + // How many characters are available in the source string from index? + size_t source_available = _length - index; + + // How many characters can we actually copy? (Need bufsize - 1 for the null terminator) + size_t copy_len = std::min(source_available, (size_t)(bufsize - 1)); -// Define the actual Particle API namespace/functions -namespace Particle { - inline bool connected() { return Particle_connected(); } - inline bool syncTime() { return Particle_syncTime(); } + // Perform the copy from the internal buffer + if (copy_len > 0) { // Only copy if there's something to copy + memcpy(buf, _buffer + index, copy_len); + } + + // Add the null terminator at the end of the copied content + buf[copy_len] = '\0'; + } + + // Modification + String substring(unsigned int beginIndex) const { + if (!_buffer || beginIndex >= _length) return String(); + return String(_buffer + beginIndex); + } + + String substring(unsigned int beginIndex, unsigned int endIndex) const { + if (!_buffer || beginIndex >= _length || endIndex <= beginIndex) return String(); + if (endIndex > _length) endIndex = _length; + char temp[endIndex - beginIndex + 1]; + strncpy(temp, _buffer + beginIndex, endIndex - beginIndex); + temp[endIndex - beginIndex] = 0; + return String(temp); + } + + String& remove(unsigned int index) { + if (!_buffer || index >= _length) return *this; + memmove(_buffer + index, _buffer + index + 1, _length - index); + _length--; + _buffer[_length] = 0; + return *this; + } + + String& remove(unsigned int index, unsigned int count) { + if (!_buffer || index >= _length) return *this; + if (count > _length - index) count = _length - index; + memmove(_buffer + index, _buffer + index + count, _length - index - count + 1); + _length -= count; + return *this; + } + + String& replace(char find, char replace) { + if (!_buffer) return *this; + for (unsigned int i = 0; i < _length; i++) { + if (_buffer[i] == find) _buffer[i] = replace; + } + return *this; + } - namespace System { - inline void on(system_event_t event, void (*handler)(system_event_t, int)) { - System_on(event, handler); + String& trim() { + if (!_buffer || !_length) return *this; + + // Find start of non-whitespace + char *begin = _buffer; + while (isspace(*begin)) begin++; + + // Find end of non-whitespace + char *end = _buffer + _length - 1; + while (end > begin && isspace(*end)) end--; + + // Calculate new length + unsigned int newlen = end - begin + 1; + + // Move string if needed + if (begin > _buffer) { + memmove(_buffer, begin, newlen); } + + // Add null terminator + _buffer[newlen] = 0; + _length = newlen; + + return *this; } - namespace Time { - inline int now() { return Time_now(); } + // Parsing + long toInt() const { + if (!_buffer) return 0; + return atol(_buffer); } -} \ No newline at end of file + + float toFloat() const { + if (!_buffer) return 0; + return atof(_buffer); + } + +private: + char* _buffer = nullptr; + unsigned int _length = 0; + unsigned int _capacity = 0; +}; + +// String helper class for concatenation operations +class StringSumHelper : public String { +public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(float num) : String(num) {} +}; + +// Concatenation operators +inline StringSumHelper operator + (const String &lhs, const String &rhs) { + StringSumHelper result(lhs); + result += rhs; + return result; +} + +inline StringSumHelper operator + (const String &lhs, const char *cstr) { + StringSumHelper result(lhs); + result += cstr; + return result; +} + +inline StringSumHelper operator + (const String &lhs, char c) { + StringSumHelper result(lhs); + result += c; + return result; +} + +inline StringSumHelper operator + (const String &lhs, int num) { + StringSumHelper result(lhs); + result += num; + return result; +} + +#endif // MOCK_PARTICLE_H diff --git a/test/unit/Driver_-_Li710/Li710Test.cpp b/test/unit/Driver_-_Li710/Li710Test.cpp new file mode 100644 index 0000000..d6b95d7 --- /dev/null +++ b/test/unit/Driver_-_Li710/Li710Test.cpp @@ -0,0 +1,423 @@ +#include +#include + +#include "Particle.h" //this is a mock of Particle.h that only includes its string implementation + +// Include other mocks +#include "MockSDI12Talon.h" +#include "MockTimeProvider.h" + +// Include the actual implementation +#include "Li710.h" + +class Li710Test : public ::testing::Test { +protected: + // Our mock objects + MockSDI12Talon mockTalon; + MockTimeProvider mockTimeProvider; + + void SetUp() override { + // Set up common mock behavior + ON_CALL(mockTalon, getSensorPortString()) + .WillByDefault(::testing::Return("1")); + ON_CALL(mockTalon, getTalonPortString()) + .WillByDefault(::testing::Return("1")); + ON_CALL(mockTalon, getSensorPort()) + .WillByDefault(::testing::Return(1)); + ON_CALL(mockTalon, getTalonPort()) + .WillByDefault(::testing::Return(1)); + } +}; + +// verify sensor interface set to SDI12 +TEST_F(Li710Test, TestSensorInterfaceSdi12) { + // Create a Li710 instance with our mock + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + // Verify that the sensor interface is set to SDI12 + EXPECT_EQ(li710.sensorInterface, BusType::SDI12); +} + +//verify talon port set to 255 if not in range +TEST_F(Li710Test, TestTalonPortOutOfRange) { + // Create a Li710 instance with our mock + LI710 li710(mockTimeProvider, mockTalon, 0, 1); // Set an out-of-range talon port + + // Verify that getTalonPort returns 0 when the port is 255 + EXPECT_EQ(li710.getTalonPort(), 0); +} + +//verify sensor port set to 255 if not in range +TEST_F(Li710Test, TestSensorPortOutOfRange) { + // Create a Li710 instance with our mock + LI710 li710(mockTimeProvider, mockTalon, 1, 0); // Set an out-of-range sensor port + + // Verify that getTalonPort returns 0 when the port is 255 + EXPECT_EQ(li710.getSensorPort(), 0); +} + +//verify talonPort is talonPort_ - 1 +TEST_F(Li710Test, TestTalonPortSet) { + // Create a Li710 instance with our mock + LI710 li710(mockTimeProvider, mockTalon, 42, 1); // Set a valid talon port + + // Verify that the talon port is set correctly + EXPECT_EQ(li710.getTalonPort(), 42); +} + +//verify sensorPort is sensorPort_ - 1 +TEST_F(Li710Test, TestSensorPortSet) { + // Create a Li710 instance with our mock + LI710 li710(mockTimeProvider, mockTalon, 1, 42); // Set a valid talon port + + // Verify that the sensor port is set correctly + EXPECT_EQ(li710.getSensorPort(), 42); +} + +// verify begin returns empty string +TEST_F(Li710Test, TestBegin) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + bool criticalFault = false; + bool fault = false; + + String result = li710.begin(0, criticalFault, fault); + + EXPECT_EQ(result, ""); +} + +// Test isPresent method when sensor is present +TEST_F(Li710Test, TestIsPresent_SensorFound) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillOnce(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillOnce(::testing::Return("013LI-COR LI-7101.01234567")); + + bool result = li710.isPresent(); + + EXPECT_TRUE(result); +} + +// Test isPresent method when sensor is not found +TEST_F(Li710Test, TestIsPresent_SensorNotFound) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillOnce(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillOnce(::testing::Return("013UNKNOWN SENSOR1.01234567")); + + bool result = li710.isPresent(); + + EXPECT_FALSE(result); +} + +//verify isPresent is called three times when it only returns false +TEST_F(Li710Test, TestGetData_SensorNotFound) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .Times(3) + .WillRepeatedly(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .Times(3) + .WillRepeatedly(::testing::Return("013UNKNOWN SENSOR1.01234567")); + + li710.getData(0); +} + +//verify talon.getAddress is called three times when it only return -1 +TEST_F(Li710Test, TestGetData_TalonAddressFail) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .Times(3) + .WillRepeatedly(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .Times(3) + .WillRepeatedly(::testing::Return("013LI-COR LI-7101.01234567")); + + EXPECT_CALL(mockTalon, getAddress()) + .Times(3) + .WillRepeatedly(::testing::Return(-1)); + + li710.getData(0); +} + +//verify ouptut is null when sensorPort is 0 +TEST_F(Li710Test, TestGetData_SensorPortZero) { + LI710 li710(mockTimeProvider, mockTalon, 1, 0); // Set an out-of-range sensor port + + String result = li710.getData(0); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"ET\":null") > 0); + EXPECT_TRUE(result.indexOf("}") > 0); +} + +//verify output is null when retry count is reached +TEST_F(Li710Test, TestGetData_RetryCountReached) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .Times(3) + .WillRepeatedly(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .Times(3) + .WillRepeatedly(::testing::Return("013UNKNOWN SENSOR1.01234567")); + + String result = li710.getData(0); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"ET\":null") > 0); + EXPECT_TRUE(result.indexOf("}") > 0); +} + +// Test getData method with valid data +TEST_F(Li710Test, DISABLED_TestGetData_ValidData) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillOnce(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillOnce(::testing::Return("013LI-COR LI-7101.01234567")); + + EXPECT_CALL(mockTalon, getAddress()) + .WillOnce(::testing::Return(0)); + + EXPECT_CALL(mockTalon, command(String("XT"), 0)) + .WillOnce(::testing::Return("")); + + // Mock valid responses for data + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(0, 0)) + .WillOnce(::testing::Return("0+1.23+4.56+7.89+10.11+12.13+14.15+16.17+18.19+20.21")); + + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(1, 0)) + .WillOnce(::testing::Return("0+22.23+24.25+26.27+28.29+30.31+32.33+34.35+36.37+38.39")); + + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(2, 0)) + .WillOnce(::testing::Return("0+40.41+42.43+44.45+46.47+48.49+50.51+52.53+54.55")); + + EXPECT_CALL(mockTalon, testCRC(::testing::_)) + .WillRepeatedly(::testing::Return(true)); + + String result = li710.getData(0); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"ET\":1.230") > 0); + EXPECT_TRUE(result.indexOf("\"LE\":4.6") > 0); + EXPECT_TRUE(result.indexOf("\"H\":7.9") > 0); + EXPECT_TRUE(result.indexOf("\"VPD\":10.11") > 0); + EXPECT_TRUE(result.indexOf("\"PA\":12.13") > 0); + EXPECT_TRUE(result.indexOf("\"TA\":14.15") > 0); + EXPECT_TRUE(result.indexOf("\"RH\":16.17") > 0); + EXPECT_TRUE(result.indexOf("\"SAMP_CNT\":36") > 0); + EXPECT_TRUE(result.indexOf("\"AH\":40.41") > 0); + EXPECT_TRUE(result.indexOf("\"SVP\":44.45") > 0); + EXPECT_TRUE(result.indexOf("\"TD\":54.55") > 0); + EXPECT_TRUE(result.indexOf("\"Pos\":[1,1]") > 0); +} + +// Test getData method with valid data and start measurment +//after new read method +TEST_F(Li710Test, TestGetData_ValidDataStartMeasurment) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillOnce(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillOnce(::testing::Return("013LI-COR LI-7101.01234567")); + + EXPECT_CALL(mockTalon, getAddress()) + .WillOnce(::testing::Return(0)); + + EXPECT_CALL(mockTalon, command(String("XT"), 0)) + .WillOnce(::testing::Return("")); + + // Mock valid responses for data + EXPECT_CALL(mockTalon, startMeasurmentIndex(0 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(1 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(2 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(3 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, command(String("D0"), 0)) + .WillOnce(::testing::Return("0+1.23+4.56+7.89")) + .WillOnce(::testing::Return("0+22.23+24.25+26.27")) + .WillOnce(::testing::Return("0+40.41+42.43+44.45")) + .WillOnce(::testing::Return("0+40.41+42.43+44.45")); //value tbd + + EXPECT_CALL(mockTalon, command(String("D1"), 0)) + .WillOnce(::testing::Return("0+10.11+12.13+14.15")) + .WillOnce(::testing::Return("0+28.29+30.31+32.33")) + .WillOnce(::testing::Return("0+46.47+48.49+50.51")) + .WillOnce(::testing::Return("0+46.47+48.49+50.51")); //value tbd + + EXPECT_CALL(mockTalon, command(String("D2"), 0)) + .WillOnce(::testing::Return("0+16.17+18.19+20.21")) + .WillOnce(::testing::Return("0+34.35+36.37+38.39")) + .WillOnce(::testing::Return("0+52.53+54.55")) + .WillOnce(::testing::Return("0+52.53+54.55")); //value tbd + + String result = li710.getData(0); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"ET\":1.230") > 0); + EXPECT_TRUE(result.indexOf("\"LE\":4.6") > 0); + EXPECT_TRUE(result.indexOf("\"H\":7.9") > 0); + EXPECT_TRUE(result.indexOf("\"VPD\":10.11") > 0); + EXPECT_TRUE(result.indexOf("\"PA\":12.13") > 0); + EXPECT_TRUE(result.indexOf("\"TA\":14.15") > 0); + EXPECT_TRUE(result.indexOf("\"RH\":16.17") > 0); + EXPECT_TRUE(result.indexOf("\"SAMP_CNT\":36") > 0); + EXPECT_TRUE(result.indexOf("\"AH\":40.41") > 0); + EXPECT_TRUE(result.indexOf("\"SVP\":44.45") > 0); + EXPECT_TRUE(result.indexOf("\"TD\":54.55") > 0); + EXPECT_TRUE(result.indexOf("\"Pos\":[1,1]") > 0); +} + +// Test getData method with CRC failure +//disabled after new read method +TEST_F(Li710Test, DISABLED_TestGetData_CRCFailure) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .Times(3) + .WillRepeatedly(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .Times(3) + .WillRepeatedly(::testing::Return("013LI-COR LI-7101.01234567")); + + EXPECT_CALL(mockTalon, getAddress()) + .WillRepeatedly(::testing::Return(0)); + + EXPECT_CALL(mockTalon, command(String("XT"), 0)) + .WillRepeatedly(::testing::Return("")); + + // Mock valid responses for data + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(0, 0)) + .WillRepeatedly(::testing::Return("0+1.23+4.56+7.89+10.11+12.13+14.15+16.17+18.19+20.21")); + + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(1, 0)) + .WillRepeatedly(::testing::Return("0+22.23+24.25+26.27+28.29+30.31+32.33+34.35+36.37+38.39")); + + EXPECT_CALL(mockTalon, continuousMeasurmentCRC(2, 0)) + .WillRepeatedly(::testing::Return("0+40.41+42.43+44.45+46.47+48.49+50.51+52.53+54.55")); + + // Force CRC failure + EXPECT_CALL(mockTalon, testCRC(::testing::_)) + .WillRepeatedly(::testing::Return(false)); + + // Expect error to be reported + //EXPECT_CALL(mockTalon, throwError(::testing::_)) + //.Times(::testing::AtLeast(1)); + + String result = li710.getData(0); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"ET\":null") > 0); + EXPECT_TRUE(result.indexOf("\"LE\":null") > 0); + EXPECT_TRUE(result.indexOf("\"Pos\":[1,1]") > 0); +} + +// Test getMetadata method +// refactor this after refactoring Li710 +TEST_F(Li710Test, TestGetMetadata) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillOnce(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillOnce(::testing::Return("013LI-COR LI-7101.01234567")); + + String result = li710.getMetadata(); + + EXPECT_TRUE(result.indexOf("LiCor ET\":{") > 0); + EXPECT_TRUE(result.indexOf("\"Hardware\":\"1.0\"") > 0); + EXPECT_TRUE(result.indexOf("\"SDI12_Ver\":\"1.3\"") > 0); + EXPECT_TRUE(result.indexOf("\"Mfg\":\"LI-COR\"") > 0); + EXPECT_TRUE(result.indexOf("\"Model\":\"LI-710\"") > 0); + EXPECT_TRUE(result.indexOf("\"SN\":\"1234567\"") > 0); + EXPECT_TRUE(result.indexOf("\"Pos\":[1,1]") > 0); + EXPECT_TRUE(result.indexOf("}") > 0); +} + +// Test selfDiagnostic method +TEST_F(Li710Test, TestSelfDiagnostic) { + LI710 li710(mockTimeProvider, mockTalon, 1, 1); + + EXPECT_CALL(mockTalon, sendCommand(String("?!"))) + .WillRepeatedly(::testing::Return("0")); + + EXPECT_CALL(mockTalon, command(String("I"), 0)) + .WillRepeatedly(::testing::Return("013LI-COR LI-7101.01234567")); + + EXPECT_CALL(mockTalon, getAddress()) + .WillOnce(::testing::Return(0)); + + EXPECT_CALL(mockTalon, command(String("XT"), 0)) + .WillOnce(::testing::Return("")); + + // Mock valid responses for data + EXPECT_CALL(mockTalon, startMeasurmentIndex(0 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(1 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(2 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, startMeasurmentIndex(3 , 0)) + .WillOnce(::testing::Return(10)); + + EXPECT_CALL(mockTalon, command(String("D0"), 0)) + .WillOnce(::testing::Return("0+1.23+4.56+7.89")) + .WillOnce(::testing::Return("0+22.23+24.25+26.27")) + .WillOnce(::testing::Return("0+40.41+42.43+44.45")) + .WillOnce(::testing::Return("0+56.57+58.59+60.61")); //value tbd + + EXPECT_CALL(mockTalon, command(String("D1"), 0)) + .WillOnce(::testing::Return("0+10.11+12.13+14.15")) + .WillOnce(::testing::Return("0+28.29+30.31+32.33")) + .WillOnce(::testing::Return("0+46.47+48.49+50.51")) + .WillOnce(::testing::Return("0+62.63+64.65+66.67")); //value tbd + + EXPECT_CALL(mockTalon, command(String("D2"), 0)) + .WillOnce(::testing::Return("0+16.17+18.19+20.21")) + .WillOnce(::testing::Return("0+34.35+36.37+38.39")) + .WillOnce(::testing::Return("0+52.53+54.55")) + .WillOnce(::testing::Return("0+68.69+70.71")); //value tbd + + li710.getData(0); + + String result = li710.selfDiagnostic(5, 0); + + EXPECT_TRUE(result.indexOf("\"LiCor ET\":{") >= 0); + EXPECT_TRUE(result.indexOf("\"Adr\":0") > 0); + EXPECT_TRUE(result.indexOf("\"PUMP_V\":56.57") > 0); + EXPECT_TRUE(result.indexOf("\"PA_CELL\":58.59") > 0); + EXPECT_TRUE(result.indexOf("\"RH_CELL\":60.61") > 0); + EXPECT_TRUE(result.indexOf("\"TA_CELL\":62.63") > 0); + //I think this is not 70.71 because the precision value is 0 + //instead of 2. I think the fake string implementation gets rid + //of the digits before the decimal place instead of after + EXPECT_TRUE(result.indexOf("\"DATA_QC\":71") > 0); + EXPECT_TRUE(result.indexOf("\"Pos\":[1,1]") > 0); +} \ No newline at end of file From 70a93901020f2b468773917c1031ccb8fd2b74b3 Mon Sep 17 00:00:00 2001 From: Zach Radlicz Date: Thu, 17 Apr 2025 11:00:18 -0500 Subject: [PATCH 2/2] updated conflicts from cherry pick --- .github/workflows/manual-flash.yaml | 2 +- .github/workflows/manual-upload.yaml | 2 +- .github/workflows/pr-workflow.yaml | 2 +- .gitmodules | 6 + CMakeLists.txt | 2 +- lib/Driver_-_Li710 | 2 +- lib/Driver_-_Talon-SDI12 | 2 +- lib/FlightControl-hardware-dependencies | 1 + lib/FlightControl-platform-dependencies | 1 + src/FlightControl_Demo.cpp | 1 + src/platform/ParticleTimeProvider.cpp | 24 ++ src/platform/ParticleTimeProvider.h | 38 +++ test/CMakeLists.txt | 66 ++--- test/main.cpp | 3 - test/mocks/Arduino.h | 29 -- test/mocks/MockArduino.cpp | 31 --- test/mocks/MockArduino.h | 89 ------- test/mocks/MockBMA456.cpp | 11 - test/mocks/MockBMA456.h | 37 --- test/mocks/MockGNSS.cpp | 18 -- test/mocks/MockGNSS.h | 58 ---- test/mocks/MockIncludes.h | 65 ----- test/mocks/MockMCP79412.cpp | 13 - test/mocks/MockMCP79412.h | 23 -- test/mocks/MockMXC6655.cpp | 6 - test/mocks/MockMXC6655.h | 29 -- test/mocks/MockPAC1934.cpp | 17 -- test/mocks/MockPAC1934.h | 21 -- test/mocks/MockPCA9634.cpp | 9 - test/mocks/MockPCA9634.h | 23 -- test/mocks/MockPCAL9535A.cpp | 17 -- test/mocks/MockPCAL9535A.h | 23 -- test/mocks/MockParticle.h | 70 ----- test/mocks/MockSHT4x.cpp | 17 -- test/mocks/MockSHT4x.h | 29 -- test/mocks/MockSPI.cpp | 4 - test/mocks/MockSensor.h | 36 --- test/mocks/MockTimeProvider.h | 34 +++ test/mocks/MockVEML3328.cpp | 19 -- test/mocks/MockVEML3328.h | 23 -- test/mocks/MockWire.cpp | 17 -- test/mocks/MockWireDeclare.h | 41 --- test/mocks/SPI.h | 30 --- test/mocks/TestKestrel.h | 336 ------------------------ test/mocks/WProgram.h | 4 - test/mocks/Wire.h | 5 - 46 files changed, 138 insertions(+), 1198 deletions(-) create mode 160000 lib/FlightControl-hardware-dependencies create mode 160000 lib/FlightControl-platform-dependencies create mode 100644 src/platform/ParticleTimeProvider.cpp create mode 100644 src/platform/ParticleTimeProvider.h delete mode 100644 test/mocks/Arduino.h delete mode 100644 test/mocks/MockArduino.cpp delete mode 100644 test/mocks/MockArduino.h delete mode 100644 test/mocks/MockBMA456.cpp delete mode 100644 test/mocks/MockBMA456.h delete mode 100644 test/mocks/MockGNSS.cpp delete mode 100644 test/mocks/MockGNSS.h delete mode 100644 test/mocks/MockIncludes.h delete mode 100644 test/mocks/MockMCP79412.cpp delete mode 100644 test/mocks/MockMCP79412.h delete mode 100644 test/mocks/MockMXC6655.cpp delete mode 100644 test/mocks/MockMXC6655.h delete mode 100644 test/mocks/MockPAC1934.cpp delete mode 100644 test/mocks/MockPAC1934.h delete mode 100644 test/mocks/MockPCA9634.cpp delete mode 100644 test/mocks/MockPCA9634.h delete mode 100644 test/mocks/MockPCAL9535A.cpp delete mode 100644 test/mocks/MockPCAL9535A.h delete mode 100644 test/mocks/MockParticle.h delete mode 100644 test/mocks/MockSHT4x.cpp delete mode 100644 test/mocks/MockSHT4x.h delete mode 100644 test/mocks/MockSPI.cpp delete mode 100644 test/mocks/MockSensor.h create mode 100644 test/mocks/MockTimeProvider.h delete mode 100644 test/mocks/MockVEML3328.cpp delete mode 100644 test/mocks/MockVEML3328.h delete mode 100644 test/mocks/MockWire.cpp delete mode 100644 test/mocks/MockWireDeclare.h delete mode 100644 test/mocks/SPI.h delete mode 100644 test/mocks/TestKestrel.h delete mode 100644 test/mocks/WProgram.h delete mode 100644 test/mocks/Wire.h diff --git a/.github/workflows/manual-flash.yaml b/.github/workflows/manual-flash.yaml index 0bba37e..aec95ac 100644 --- a/.github/workflows/manual-flash.yaml +++ b/.github/workflows/manual-flash.yaml @@ -41,7 +41,7 @@ jobs: - name: Download latest firmware artifact if: github.event.inputs.use_latest_artifact == 'yes' - uses: dawidd6/action-download-artifact@v3 + uses: dawidd6/action-download-artifact@v6 with: workflow: manual-compile.yaml name: firmware-binary diff --git a/.github/workflows/manual-upload.yaml b/.github/workflows/manual-upload.yaml index 7b69dc6..d308cd1 100644 --- a/.github/workflows/manual-upload.yaml +++ b/.github/workflows/manual-upload.yaml @@ -45,7 +45,7 @@ jobs: - name: Download release artifacts if: github.event.inputs.use_release_artifact == 'yes' - uses: dawidd6/action-download-artifact@v3 + uses: dawidd6/action-download-artifact@v6 with: workflow: manual-release.yaml name: release-artifacts diff --git a/.github/workflows/pr-workflow.yaml b/.github/workflows/pr-workflow.yaml index eef8465..6b83b0b 100644 --- a/.github/workflows/pr-workflow.yaml +++ b/.github/workflows/pr-workflow.yaml @@ -3,7 +3,7 @@ name: Pull Request Workflow on: # Runs on PR open pull_request: - types: [opened, reopened, synchronize] + types: [opened, reopened, synchronize, edited] branches: - master # or 'main' depending on your main branch diff --git a/.gitmodules b/.gitmodules index fc0685c..9931ca3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -131,3 +131,9 @@ [submodule "test/external/fff"] path = test/external/fff url = https://github.com/meekrosoft/fff.git +[submodule "lib/FlightControl-platform-dependencies"] + path = lib/FlightControl-platform-dependencies + url = https://github.com/gemsiot/FlightControl-platform-dependencies +[submodule "lib/FlightControl-hardware-dependencies"] + path = lib/FlightControl-hardware-dependencies + url = https://github.com/gemsiot/FlightControl-hardware-dependencies diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e61118..bd21d6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) project(FlightControl_Demo_Tests) # Specify C++ standard -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Add test directory diff --git a/lib/Driver_-_Li710 b/lib/Driver_-_Li710 index c43b276..d5616c6 160000 --- a/lib/Driver_-_Li710 +++ b/lib/Driver_-_Li710 @@ -1 +1 @@ -Subproject commit c43b276337d09504a9f53c28270dee2190e31ea1 +Subproject commit d5616c60261d93517faf6d8b580ec932b9185ef2 diff --git a/lib/Driver_-_Talon-SDI12 b/lib/Driver_-_Talon-SDI12 index c97deae..6439b28 160000 --- a/lib/Driver_-_Talon-SDI12 +++ b/lib/Driver_-_Talon-SDI12 @@ -1 +1 @@ -Subproject commit c97deaeacbc7db7784d9c5dde4189687f114364a +Subproject commit 6439b287dd1513858b8f8449e5250ac166215456 diff --git a/lib/FlightControl-hardware-dependencies b/lib/FlightControl-hardware-dependencies new file mode 160000 index 0000000..1fec360 --- /dev/null +++ b/lib/FlightControl-hardware-dependencies @@ -0,0 +1 @@ +Subproject commit 1fec36002d6e53980f6091d81b1e466944b55345 diff --git a/lib/FlightControl-platform-dependencies b/lib/FlightControl-platform-dependencies new file mode 160000 index 0000000..183167f --- /dev/null +++ b/lib/FlightControl-platform-dependencies @@ -0,0 +1 @@ +Subproject commit 183167f55afbe499f67b8ad22292a9c12602bdc6 diff --git a/src/FlightControl_Demo.cpp b/src/FlightControl_Demo.cpp index dc84e28..fd9af8b 100644 --- a/src/FlightControl_Demo.cpp +++ b/src/FlightControl_Demo.cpp @@ -79,6 +79,7 @@ SDI12Talon sdi12(0, 0x14); //Instantiate SDI12 talon with alt - null port and ha PCAL9535A ioAlpha(0x20); PCAL9535A ioBeta(0x21); SDI12TalonAdapter realSdi12(sdi12); +ParticleTimeProvider realTimeProvider; String globalNodeID = ""; //Store current node ID diff --git a/src/platform/ParticleTimeProvider.cpp b/src/platform/ParticleTimeProvider.cpp new file mode 100644 index 0000000..e27a815 --- /dev/null +++ b/src/platform/ParticleTimeProvider.cpp @@ -0,0 +1,24 @@ +// src/platform/ParticleTimeProvider.cpp +#include "ParticleTimeProvider.h" + +// Use :: prefix for global scope functions like millis() and delay() +// to avoid potential name conflicts if methods had same name. + +int ParticleTimeProvider::year() { return Time.year(); } +int ParticleTimeProvider::year(time_t t) { return Time.year(t); } +int ParticleTimeProvider::month() { return Time.month(); } +int ParticleTimeProvider::month(time_t t) { return Time.month(t); } +int ParticleTimeProvider::day() { return Time.day(); } +int ParticleTimeProvider::day(time_t t) { return Time.day(t); } +int ParticleTimeProvider::hour() { return Time.hour(); } +int ParticleTimeProvider::hour(time_t t) { return Time.hour(t); } +int ParticleTimeProvider::minute() { return Time.minute(); } +int ParticleTimeProvider::minute(time_t t) { return Time.minute(t); } +int ParticleTimeProvider::second() { return Time.second(); } +int ParticleTimeProvider::second(time_t t) { return Time.second(t); } +time_t ParticleTimeProvider::now() { return Time.now(); } +void ParticleTimeProvider::setTime(time_t t) { Time.setTime(t); } +bool ParticleTimeProvider::isValid() { return Time.isValid(); } +void ParticleTimeProvider::zone(float GMT_Offset) { Time.zone(GMT_Offset); } +uint32_t ParticleTimeProvider::millis() { return ::millis(); } +void ParticleTimeProvider::delay(uint32_t ms) { ::delay(ms); } \ No newline at end of file diff --git a/src/platform/ParticleTimeProvider.h b/src/platform/ParticleTimeProvider.h new file mode 100644 index 0000000..3410802 --- /dev/null +++ b/src/platform/ParticleTimeProvider.h @@ -0,0 +1,38 @@ +// src/platform/ParticleTimeProvider.h +#ifndef PARTICLE_TIME_PROVIDER_H +#define PARTICLE_TIME_PROVIDER_H + +#include "ITimeProvider.h" // Include the interface definition +#include "Particle.h" // Include the actual Particle header HERE + +/** + * @brief Concrete implementation of ITimeProvider using Particle API. + */ +class ParticleTimeProvider : public ITimeProvider { +public: + // Constructor/Destructor (often default is fine) + ParticleTimeProvider() = default; + ~ParticleTimeProvider() override = default; + + // Implement methods from ITimeProvider + int year() override; + int year(time_t t) override; + int month() override; + int month(time_t t) override; + int day() override; + int day(time_t t) override; + int hour() override; + int hour(time_t t) override; + int minute() override; + int minute(time_t t) override; + int second() override; + int second(time_t t) override; + time_t now() override; + void setTime(time_t t) override; + bool isValid() override; + void zone(float GMT_Offset) override; + uint32_t millis() override; + void delay(uint32_t ms) override; +}; + +#endif // PARTICLE_TIME_PROVIDER_H \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 22044ee..e052d37 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,29 +8,35 @@ add_subdirectory(external/googletest) # Define the TESTING preprocessor macro for all test builds add_compile_definitions(TESTING) -# IMPORTANT: Make sure mocks are included first to override system headers -include_directories(BEFORE mocks) +# Set C++ standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) -# Include FFF headers -include_directories(external/fff) - -# Include Google Test headers +# Include Google Test and Google Mock headers include_directories(external/googletest/googletest/include) +include_directories(external/googletest/googlemock/include) + +# Find all driver directories and add them to the include path +file(GLOB DRIVER_DIRS ${CMAKE_SOURCE_DIR}/lib/*/src) -# Create a mocks library -add_library(mocks STATIC - mocks/MockWire.cpp - mocks/MockArduino.cpp - mocks/MockPCAL9535A.cpp - mocks/MockMCP79412.cpp - mocks/MockSPI.cpp - mocks/MockPCA9634.cpp - mocks/MockSHT4x.cpp - mocks/MockVEML3328.cpp - mocks/MockPAC1934.cpp - mocks/MockMXC6655.cpp - mocks/MockBMA456.cpp - mocks/MockGNSS.cpp +# Create a library for the mocks +file(GLOB MOCK_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/mocks/*.cpp +) + +# Add a library of mocks - if there are no source files yet, use an interface library +if(MOCK_SOURCES) + add_library(mocks ${MOCK_SOURCES}) +else() + add_library(mocks INTERFACE) +endif() + +# Add header include directories for mocks - mock directory MUST be first +target_include_directories(mocks BEFORE INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/mocks # Mocks FIRST + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/src + ${DRIVER_DIRS} # Add all driver directories ) # Specify test executable @@ -48,22 +54,4 @@ add_executable(unit_tests ) # Link against mocks and GoogleTest -target_link_libraries(unit_tests mocks gtest gtest_main) - -# Find all driver directories and add them to the include path -file(GLOB DRIVER_DIRS ${CMAKE_SOURCE_DIR}/lib/*/src) - -# Add header include directories - mock directory MUST be first -target_include_directories(mocks BEFORE PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/mocks # Mocks FIRST - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/src - ${DRIVER_DIRS} # Add all driver directories -) - -target_include_directories(unit_tests BEFORE PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/mocks # Mocks FIRST - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/src - ${DRIVER_DIRS} # Add all driver directories -) \ No newline at end of file +target_link_libraries(unit_tests mocks gtest gtest_main gmock) \ No newline at end of file diff --git a/test/main.cpp b/test/main.cpp index ec03b1f..879b780 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,8 +1,5 @@ // FlightControl_Demo/test/main.cpp #include "gtest/gtest.h" -#include "fff.h" - -DEFINE_FFF_GLOBALS; int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/mocks/Arduino.h b/test/mocks/Arduino.h deleted file mode 100644 index 371a6c9..0000000 --- a/test/mocks/Arduino.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -// Include our Arduino mocks -#include "MockArduino.h" - -// Arduino standard libraries -#include -#include -#include - -// Forward declarations for common Arduino types and functions -// This will silence most Arduino.h include errors -typedef uint8_t byte; - -class HardwareSerial { -public: - void begin(unsigned long baud) {} - int available() { return 0; } - int read() { return -1; } - void print(const char* str) {} - void print(int val) {} - void println(const char* str) {} - void println(int val) {} -}; - -extern HardwareSerial Serial1; -extern HardwareSerial Serial2; - -// Add more Arduino types/functions as needed \ No newline at end of file diff --git a/test/mocks/MockArduino.cpp b/test/mocks/MockArduino.cpp deleted file mode 100644 index a3ebc20..0000000 --- a/test/mocks/MockArduino.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// test/mocks/MockArduino.cpp -#include "MockArduino.h" - -// Define fake functions -DEFINE_FAKE_VOID_FUNC(pinMode, uint8_t, uint8_t); -DEFINE_FAKE_VOID_FUNC(digitalWrite, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(int, digitalRead, uint8_t); -DEFINE_FAKE_VALUE_FUNC(int, analogRead, uint8_t); -DEFINE_FAKE_VOID_FUNC(analogWrite, uint8_t, int); - -// Time functions -DEFINE_FAKE_VALUE_FUNC(unsigned long, millis); -DEFINE_FAKE_VALUE_FUNC(unsigned long, micros); -DEFINE_FAKE_VOID_FUNC(delay, unsigned long); -DEFINE_FAKE_VOID_FUNC(delayMicroseconds, unsigned int); - -// Misc -DEFINE_FAKE_VOID_FUNC(randomSeed, unsigned long); -DEFINE_FAKE_VALUE_FUNC(long, random, long, long); - -// Serial functions -DEFINE_FAKE_VOID_FUNC(Serial_begin, unsigned long); -DEFINE_FAKE_VALUE_FUNC(int, Serial_available); -DEFINE_FAKE_VALUE_FUNC(int, Serial_read); -DEFINE_FAKE_VOID_FUNC(Serial_print_s, const char*); -DEFINE_FAKE_VOID_FUNC(Serial_print_i, int); -DEFINE_FAKE_VOID_FUNC(Serial_println_s, const char*); -DEFINE_FAKE_VOID_FUNC(Serial_println_i, int); - -// Define the global Serial instance -MockSerial Serial; \ No newline at end of file diff --git a/test/mocks/MockArduino.h b/test/mocks/MockArduino.h deleted file mode 100644 index 4e36f5a..0000000 --- a/test/mocks/MockArduino.h +++ /dev/null @@ -1,89 +0,0 @@ -// test/mocks/MockArduino.h -#pragma once - -#include -#include "fff.h" - -// Define Arduino pin modes -#define INPUT 0 -#define OUTPUT 1 -#define INPUT_PULLUP 2 -#define INPUT_PULLDOWN 3 - -// Define pin values -#define HIGH 1 -#define LOW 0 - -// Define common Arduino pins -#define A0 14 -#define A1 15 -#define A2 16 -#define A3 17 -#define A4 18 -#define A5 19 -#define A6 20 -#define A7 21 -#define D0 0 -#define D1 1 -#define D2 2 -#define D3 3 -#define D4 4 -#define D5 5 -#define D6 6 -#define D7 7 -#define D8 8 -#define D9 9 -#define D10 10 -#define D11 11 -#define D12 12 -#define D13 13 -#define D14 14 -#define D15 15 -#define D16 16 -#define D17 17 -#define D18 18 -#define D19 19 -#define D20 20 -#define D21 21 -#define D22 22 -#define D23 23 - -// Digital and Analog I/O -DECLARE_FAKE_VOID_FUNC(pinMode, uint8_t, uint8_t); -DECLARE_FAKE_VOID_FUNC(digitalWrite, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(int, digitalRead, uint8_t); -DECLARE_FAKE_VALUE_FUNC(int, analogRead, uint8_t); -DECLARE_FAKE_VOID_FUNC(analogWrite, uint8_t, int); - -// Time functions -DECLARE_FAKE_VALUE_FUNC(unsigned long, millis); -DECLARE_FAKE_VALUE_FUNC(unsigned long, micros); -DECLARE_FAKE_VOID_FUNC(delay, unsigned long); -DECLARE_FAKE_VOID_FUNC(delayMicroseconds, unsigned int); - -// Misc -DECLARE_FAKE_VOID_FUNC(randomSeed, unsigned long); -DECLARE_FAKE_VALUE_FUNC(long, random, long, long); - -// Forward declarations for Serial functions -DECLARE_FAKE_VOID_FUNC(Serial_begin, unsigned long); -DECLARE_FAKE_VALUE_FUNC(int, Serial_available); -DECLARE_FAKE_VALUE_FUNC(int, Serial_read); -DECLARE_FAKE_VOID_FUNC(Serial_print_s, const char*); -DECLARE_FAKE_VOID_FUNC(Serial_print_i, int); -DECLARE_FAKE_VOID_FUNC(Serial_println_s, const char*); -DECLARE_FAKE_VOID_FUNC(Serial_println_i, int); - -// Mock class for the Serial object -class MockSerial { -public: - void begin(unsigned long baud) { Serial_begin(baud); } - int available() { return Serial_available(); } - int read() { return Serial_read(); } - void print(const char* str) { Serial_print_s(str); } - void print(int val) { Serial_print_i(val); } - void println(const char* str) { Serial_println_s(str); } - void println(int val) { Serial_println_i(val); } -}; - -extern MockSerial Serial; \ No newline at end of file diff --git a/test/mocks/MockBMA456.cpp b/test/mocks/MockBMA456.cpp deleted file mode 100644 index 66d38e2..0000000 --- a/test/mocks/MockBMA456.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "MockBMA456.h" - -// Define fake functions for BMA456 -DEFINE_FAKE_VALUE_FUNC(bool, BMA456_begin); -DEFINE_FAKE_VALUE_FUNC(bool, BMA456_readAcceleration, float*, float*, float*); -DEFINE_FAKE_VALUE_FUNC(bool, BMA456_enableStepCounter, bool); -DEFINE_FAKE_VALUE_FUNC(uint32_t, BMA456_getStepCount); -DEFINE_FAKE_VALUE_FUNC(bool, BMA456_resetStepCounter); - -// Initialize the global object -BMA456 accel_bma456; \ No newline at end of file diff --git a/test/mocks/MockBMA456.h b/test/mocks/MockBMA456.h deleted file mode 100644 index 40549fa..0000000 --- a/test/mocks/MockBMA456.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions for BMA456 accelerometer -DECLARE_FAKE_VALUE_FUNC(bool, BMA456_begin); -DECLARE_FAKE_VALUE_FUNC(bool, BMA456_readAcceleration, float*, float*, float*); -DECLARE_FAKE_VALUE_FUNC(bool, BMA456_enableStepCounter, bool); -DECLARE_FAKE_VALUE_FUNC(uint32_t, BMA456_getStepCount); -DECLARE_FAKE_VALUE_FUNC(bool, BMA456_resetStepCounter); - -// Mock class for BMA456 via arduino_bma456 -class BMA456 { -public: - // Default mock values - float x_acceleration = 0.0f; - float y_acceleration = 0.0f; - float z_acceleration = 1.0f; // Default to 1G in Z direction (earth gravity) - uint32_t step_count = 0; - - bool begin() { return BMA456_begin(); } - - bool readAcceleration(float* x, float* y, float* z) { - *x = x_acceleration; - *y = y_acceleration; - *z = z_acceleration; - return BMA456_readAcceleration(x, y, z); - } - - bool enableStepCounter(bool enable) { return BMA456_enableStepCounter(enable); } - uint32_t getStepCount() { return BMA456_getStepCount(); } - bool resetStepCounter() { return BMA456_resetStepCounter(); } -}; - -// This simulates the global object provided by the arduino_bma456 library -extern BMA456 accel_bma456; \ No newline at end of file diff --git a/test/mocks/MockGNSS.cpp b/test/mocks/MockGNSS.cpp deleted file mode 100644 index 4d88aa9..0000000 --- a/test/mocks/MockGNSS.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "MockGNSS.h" - -// Define fake functions for GNSS -DEFINE_FAKE_VALUE_FUNC(bool, GNSS_begin, int); -DEFINE_FAKE_VALUE_FUNC(bool, GNSS_isConnected); -DEFINE_FAKE_VALUE_FUNC(bool, GNSS_setI2COutput, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, GNSS_setNavigationFrequency, uint8_t); -DEFINE_FAKE_VALUE_FUNC(long, GNSS_getLatitude); -DEFINE_FAKE_VALUE_FUNC(long, GNSS_getLongitude); -DEFINE_FAKE_VALUE_FUNC(long, GNSS_getAltitude); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getSIV); -DEFINE_FAKE_VALUE_FUNC(uint32_t, GNSS_getTimeOfWeek); -DEFINE_FAKE_VALUE_FUNC(uint16_t, GNSS_getYear); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getMonth); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getDay); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getHour); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getMinute); -DEFINE_FAKE_VALUE_FUNC(uint8_t, GNSS_getSecond); \ No newline at end of file diff --git a/test/mocks/MockGNSS.h b/test/mocks/MockGNSS.h deleted file mode 100644 index 7511d12..0000000 --- a/test/mocks/MockGNSS.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "fff.h" -#include -#include - -// Declare fake functions for u-blox GNSS -DECLARE_FAKE_VALUE_FUNC(bool, GNSS_begin, int); -DECLARE_FAKE_VALUE_FUNC(bool, GNSS_isConnected); -DECLARE_FAKE_VALUE_FUNC(bool, GNSS_setI2COutput, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, GNSS_setNavigationFrequency, uint8_t); -DECLARE_FAKE_VALUE_FUNC(long, GNSS_getLatitude); -DECLARE_FAKE_VALUE_FUNC(long, GNSS_getLongitude); -DECLARE_FAKE_VALUE_FUNC(long, GNSS_getAltitude); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getSIV); -DECLARE_FAKE_VALUE_FUNC(uint32_t, GNSS_getTimeOfWeek); -DECLARE_FAKE_VALUE_FUNC(uint16_t, GNSS_getYear); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getMonth); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getDay); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getHour); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getMinute); -DECLARE_FAKE_VALUE_FUNC(uint8_t, GNSS_getSecond); - -// Mock class for SFE_UBLOX_GNSS -class SFE_UBLOX_GNSS { -public: - // Default mock values - long latitude = 449673925; // Minneapolis ~44.96°N - long longitude = -932838386; // Minneapolis ~-93.28°E - long altitude = 25000; // 250m above MSL - uint8_t satellites = 8; // 8 satellites in view - - // Time values - uint16_t year = 2023; - uint8_t month = 5; - uint8_t day = 15; - uint8_t hour = 10; - uint8_t minute = 30; - uint8_t second = 0; - - bool begin(int wirePort = 0) { return GNSS_begin(wirePort); } - bool isConnected() { return GNSS_isConnected(); } - bool setI2COutput(uint8_t comSettings) { return GNSS_setI2COutput(comSettings); } - bool setNavigationFrequency(uint8_t navFreq) { return GNSS_setNavigationFrequency(navFreq); } - - long getLatitude() { return GNSS_getLatitude(); } - long getLongitude() { return GNSS_getLongitude(); } - long getAltitude() { return GNSS_getAltitude(); } - uint8_t getSIV() { return GNSS_getSIV(); } - - uint32_t getTimeOfWeek() { return GNSS_getTimeOfWeek(); } - uint16_t getYear() { return GNSS_getYear(); } - uint8_t getMonth() { return GNSS_getMonth(); } - uint8_t getDay() { return GNSS_getDay(); } - uint8_t getHour() { return GNSS_getHour(); } - uint8_t getMinute() { return GNSS_getMinute(); } - uint8_t getSecond() { return GNSS_getSecond(); } -}; \ No newline at end of file diff --git a/test/mocks/MockIncludes.h b/test/mocks/MockIncludes.h deleted file mode 100644 index 0a677c9..0000000 --- a/test/mocks/MockIncludes.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -// This file contains includes and settings for testing the Kestrel driver with real code -// It ensures we properly redirect hardware calls to mocks while avoiding redefinition errors - -// Tell the compiler we're in testing mode - this can be used in #ifdef blocks -#define TESTING - -// First define all the hardware classes as empty forward declarations -// This prevents the real implementations from being compiled -class Sensor; -class PCAL9535A; -class PCA9634; -class MCP79412; -class SFE_UBLOX_GNSS; -class PAC1934; -class VEML3328; -class Adafruit_SHT4x; -class MXC6655; -class BMA456; - -// Now include our mock implementations -#include "MockSensor.h" -#include "MockPCAL9535A.h" -#include "MockPCA9634.h" -#include "MockMCP79412.h" -#include "MockGNSS.h" -#include "MockPAC1934.h" -#include "MockVEML3328.h" -#include "MockSHT4x.h" -#include "MockMXC6655.h" -#include "MockBMA456.h" -#include "MockArduino.h" -#include "MockWireDeclare.h" - -// Define any constants that might be needed by Kestrel.h -#define OUTPUT 1 -#define INPUT 0 -#define HIGH 1 -#define LOW 0 - -// Arduino constants -#define A0 14 -#define A1 15 -#define A2 16 -#define A3 17 -#define A4 18 -#define A5 19 -#define A6 20 -#define A7 21 -#define D0 0 -#define D1 1 -#define D2 2 -#define D3 3 -#define D4 4 -#define D5 5 -#define D6 6 -#define D7 7 -#define D8 8 -#define D22 22 -#define D23 23 - -// Define additional constants that Kestrel.h might need -// If there are specific enum values or constants that Kestrel.h expects, -// add them here \ No newline at end of file diff --git a/test/mocks/MockMCP79412.cpp b/test/mocks/MockMCP79412.cpp deleted file mode 100644 index 2641e83..0000000 --- a/test/mocks/MockMCP79412.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "MockMCP79412.h" - -// Define fake functions -DEFINE_FAKE_VALUE_FUNC(bool, MCP79412_begin); -DEFINE_FAKE_VALUE_FUNC(time_t, MCP79412_getTime); -DEFINE_FAKE_VALUE_FUNC(bool, MCP79412_setTime, time_t); - -// Set default behavior -void setup_mock_MCP79412_defaults() { - MCP79412_begin_fake.return_val = true; - MCP79412_getTime_fake.return_val = time(NULL); // Current time - MCP79412_setTime_fake.return_val = true; -} \ No newline at end of file diff --git a/test/mocks/MockMCP79412.h b/test/mocks/MockMCP79412.h deleted file mode 100644 index b2117ae..0000000 --- a/test/mocks/MockMCP79412.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "fff.h" -#include -#include - -// Declare fake functions -DECLARE_FAKE_VALUE_FUNC(bool, MCP79412_begin); -DECLARE_FAKE_VALUE_FUNC(time_t, MCP79412_getTime); -DECLARE_FAKE_VALUE_FUNC(bool, MCP79412_setTime, time_t); - -// Mock class for MCP79412 RTC -class MCP79412 { -public: - bool begin() { return MCP79412_begin(); } - time_t getTime() { return MCP79412_getTime(); } - bool setTime(time_t time) { return MCP79412_setTime(time); } - - // Additional properties to match the real implementation - uint8_t numErrors = 0; - - // Add more methods as needed for Kestrel tests -}; \ No newline at end of file diff --git a/test/mocks/MockMXC6655.cpp b/test/mocks/MockMXC6655.cpp deleted file mode 100644 index 535b0dc..0000000 --- a/test/mocks/MockMXC6655.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "MockMXC6655.h" - -// Define fake functions for MXC6655 -DEFINE_FAKE_VALUE_FUNC(bool, MXC6655_begin); -DEFINE_FAKE_VALUE_FUNC(bool, MXC6655_readAcceleration, float*, float*, float*); -DEFINE_FAKE_VALUE_FUNC(bool, MXC6655_resetOrientation); \ No newline at end of file diff --git a/test/mocks/MockMXC6655.h b/test/mocks/MockMXC6655.h deleted file mode 100644 index 40509ef..0000000 --- a/test/mocks/MockMXC6655.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions for MXC6655 accelerometer -DECLARE_FAKE_VALUE_FUNC(bool, MXC6655_begin); -DECLARE_FAKE_VALUE_FUNC(bool, MXC6655_readAcceleration, float*, float*, float*); -DECLARE_FAKE_VALUE_FUNC(bool, MXC6655_resetOrientation); - -// Mock class for MXC6655 accelerometer -class MXC6655 { -public: - // Default mock values - float x_acceleration = 0.0f; - float y_acceleration = 0.0f; - float z_acceleration = 1.0f; // Default to 1G in Z direction (earth gravity) - - bool begin() { return MXC6655_begin(); } - - bool readAcceleration(float* x, float* y, float* z) { - *x = x_acceleration; - *y = y_acceleration; - *z = z_acceleration; - return MXC6655_readAcceleration(x, y, z); - } - - bool resetOrientation() { return MXC6655_resetOrientation(); } -}; \ No newline at end of file diff --git a/test/mocks/MockPAC1934.cpp b/test/mocks/MockPAC1934.cpp deleted file mode 100644 index a1c86ff..0000000 --- a/test/mocks/MockPAC1934.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "MockPAC1934.h" - -// Define fake functions -DEFINE_FAKE_VALUE_FUNC(bool, PAC1934_begin); -DEFINE_FAKE_VALUE_FUNC(float, PAC1934_readVoltage, uint8_t); -DEFINE_FAKE_VALUE_FUNC(float, PAC1934_readCurrent, uint8_t); -DEFINE_FAKE_VALUE_FUNC(float, PAC1934_readPower, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PAC1934_enableChannel, uint8_t, bool); - -// Set default behavior -void setup_mock_PAC1934_defaults() { - PAC1934_begin_fake.return_val = true; - PAC1934_readVoltage_fake.return_val = 3.3f; - PAC1934_readCurrent_fake.return_val = 0.1f; - PAC1934_readPower_fake.return_val = 0.33f; - PAC1934_enableChannel_fake.return_val = true; -} diff --git a/test/mocks/MockPAC1934.h b/test/mocks/MockPAC1934.h deleted file mode 100644 index b39276f..0000000 --- a/test/mocks/MockPAC1934.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions for PAC1934 (power monitor) -DECLARE_FAKE_VALUE_FUNC(bool, PAC1934_begin); -DECLARE_FAKE_VALUE_FUNC(float, PAC1934_readVoltage, uint8_t); -DECLARE_FAKE_VALUE_FUNC(float, PAC1934_readCurrent, uint8_t); -DECLARE_FAKE_VALUE_FUNC(float, PAC1934_readPower, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PAC1934_enableChannel, uint8_t, bool); - -// Mock class for PAC1934 -class PAC1934 { -public: - bool begin() { return PAC1934_begin(); } - float readVoltage(uint8_t channel) { return PAC1934_readVoltage(channel); } - float readCurrent(uint8_t channel) { return PAC1934_readCurrent(channel); } - float readPower(uint8_t channel) { return PAC1934_readPower(channel); } - bool enableChannel(uint8_t channel, bool enable) { return PAC1934_enableChannel(channel, enable); } -}; diff --git a/test/mocks/MockPCA9634.cpp b/test/mocks/MockPCA9634.cpp deleted file mode 100644 index 4bfd766..0000000 --- a/test/mocks/MockPCA9634.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "MockPCA9634.h" - -// Define fake functions for PCA9634 -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_begin); -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_begin_address, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_setLEDOutputMode, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_setLEDDriverMode, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_setBrightness, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCA9634_setOutputState, uint8_t, uint8_t); \ No newline at end of file diff --git a/test/mocks/MockPCA9634.h b/test/mocks/MockPCA9634.h deleted file mode 100644 index 76f41d4..0000000 --- a/test/mocks/MockPCA9634.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions for PCA9634 LED driver -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_begin); -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_begin_address, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_setLEDOutputMode, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_setLEDDriverMode, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_setBrightness, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCA9634_setOutputState, uint8_t, uint8_t); - -// Mock class for PCA9634 LED driver -class PCA9634 { -public: - bool begin() { return PCA9634_begin(); } - bool begin(uint8_t address) { return PCA9634_begin_address(address); } - bool setLEDOutputMode(uint8_t ledNum, uint8_t mode) { return PCA9634_setLEDOutputMode(ledNum, mode); } - bool setLEDDriverMode(uint8_t ledNum, uint8_t mode) { return PCA9634_setLEDDriverMode(ledNum, mode); } - bool setBrightness(uint8_t ledNum, uint8_t brightness) { return PCA9634_setBrightness(ledNum, brightness); } - bool setOutputState(uint8_t ledNum, uint8_t state) { return PCA9634_setOutputState(ledNum, state); } -}; \ No newline at end of file diff --git a/test/mocks/MockPCAL9535A.cpp b/test/mocks/MockPCAL9535A.cpp deleted file mode 100644 index 88c502f..0000000 --- a/test/mocks/MockPCAL9535A.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "MockPCAL9535A.h" - -// Define fake functions -DEFINE_FAKE_VALUE_FUNC(bool, PCAL9535A_begin); -DEFINE_FAKE_VALUE_FUNC(bool, PCAL9535A_pinMode, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCAL9535A_digitalWrite, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(uint8_t, PCAL9535A_digitalRead, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, PCAL9535A_begin_address, uint8_t); - -// Set default behavior -void setup_mock_PCAL9535A_defaults() { - PCAL9535A_begin_fake.return_val = true; - PCAL9535A_pinMode_fake.return_val = true; - PCAL9535A_digitalWrite_fake.return_val = true; - PCAL9535A_digitalRead_fake.return_val = 0; - PCAL9535A_begin_address_fake.return_val = true; -} \ No newline at end of file diff --git a/test/mocks/MockPCAL9535A.h b/test/mocks/MockPCAL9535A.h deleted file mode 100644 index 0646586..0000000 --- a/test/mocks/MockPCAL9535A.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions -DECLARE_FAKE_VALUE_FUNC(bool, PCAL9535A_begin); -DECLARE_FAKE_VALUE_FUNC(bool, PCAL9535A_pinMode, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCAL9535A_digitalWrite, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(uint8_t, PCAL9535A_digitalRead, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, PCAL9535A_begin_address, uint8_t); - -// Mock class for PCAL9535A IO expander -class PCAL9535A { -public: - bool begin() { return PCAL9535A_begin(); } - bool pinMode(uint8_t pin, uint8_t mode) { return PCAL9535A_pinMode(pin, mode); } - bool digitalWrite(uint8_t pin, uint8_t value) { return PCAL9535A_digitalWrite(pin, value); } - uint8_t digitalRead(uint8_t pin) { return PCAL9535A_digitalRead(pin); } - bool begin(uint8_t address) { return PCAL9535A_begin_address(address); } - - // Add more methods as needed for Kestrel tests -}; \ No newline at end of file diff --git a/test/mocks/MockParticle.h b/test/mocks/MockParticle.h deleted file mode 100644 index 38ba1be..0000000 --- a/test/mocks/MockParticle.h +++ /dev/null @@ -1,70 +0,0 @@ -// test/mocks/mock_particle.h -#pragma once -#include -#include -#include - -// Basic String implementation to match Particle's String class -class String { -private: - std::string data; - -public: - String() : data("") {} - String(const char* str) : data(str ? str : "") {} - String(const std::string& str) : data(str) {} - String(int value) : data(std::to_string(value)) {} - - // Common methods used in the tests - bool equals(const String& other) const { return data == other.data; } - bool startsWith(const String& prefix) const { - return data.find(prefix.data) == 0; - } - bool endsWith(const String& suffix) const { - if (suffix.data.length() > data.length()) return false; - return data.rfind(suffix.data) == (data.length() - suffix.data.length()); - } - - // Operators - String operator+(const String& rhs) const { - return String(data + rhs.data); - } - String& operator+=(const String& rhs) { - data += rhs.data; - return *this; - } - bool operator==(const String& rhs) const { - return data == rhs.data; - } - - // Conversion operators - operator const char*() const { return data.c_str(); } - - // Common String methods - size_t length() const { return data.length(); } - const char* c_str() const { return data.c_str(); } - - // Specific methods needed for your FlightControl_Demo - bool endsWith(char c) const { - return !data.empty() && data.back() == c; - } - - int lastIndexOf(char c) const { - size_t pos = data.rfind(c); - return pos != std::string::npos ? static_cast(pos) : -1; - } - - int lastIndexOf(const String& str) const { - size_t pos = data.rfind(str.data); - return pos != std::string::npos ? static_cast(pos) : -1; - } - - // Add more methods as they're needed -}; - -// Add other Particle types and functions as needed -// For example: -typedef uint8_t byte; - -// Time functions are implemented in MockArduino.cpp -// Don't define millis() here to avoid duplicate definition \ No newline at end of file diff --git a/test/mocks/MockSHT4x.cpp b/test/mocks/MockSHT4x.cpp deleted file mode 100644 index f944eb3..0000000 --- a/test/mocks/MockSHT4x.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "MockSHT4x.h" - -// Define fake functions -DEFINE_FAKE_VALUE_FUNC(bool, SHT4x_begin); -DEFINE_FAKE_VALUE_FUNC(bool, SHT4x_setPrecision, uint8_t); -DEFINE_FAKE_VALUE_FUNC(bool, SHT4x_readTemperature); -DEFINE_FAKE_VALUE_FUNC(bool, SHT4x_readHumidity); -DEFINE_FAKE_VALUE_FUNC(bool, SHT4x_getEvent); - -// Set default behavior -void setup_mock_SHT4x_defaults() { - SHT4x_begin_fake.return_val = true; - SHT4x_setPrecision_fake.return_val = true; - SHT4x_readTemperature_fake.return_val = true; - SHT4x_readHumidity_fake.return_val = true; - SHT4x_getEvent_fake.return_val = true; -} diff --git a/test/mocks/MockSHT4x.h b/test/mocks/MockSHT4x.h deleted file mode 100644 index 22081ea..0000000 --- a/test/mocks/MockSHT4x.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Constants to match Adafruit's SHT4x -#define SHT4X_HIGH_PRECISION 0 -#define SHT4X_MED_PRECISION 1 -#define SHT4X_LOW_PRECISION 2 - -// Declare fake functions -DECLARE_FAKE_VALUE_FUNC(bool, SHT4x_begin); -DECLARE_FAKE_VALUE_FUNC(bool, SHT4x_setPrecision, uint8_t); -DECLARE_FAKE_VALUE_FUNC(bool, SHT4x_readTemperature); -DECLARE_FAKE_VALUE_FUNC(bool, SHT4x_readHumidity); -DECLARE_FAKE_VALUE_FUNC(bool, SHT4x_getEvent); - -// Mock class for Adafruit_SHT4x -class Adafruit_SHT4x { -public: - float temperature = 25.0f; // Default mock values - float humidity = 50.0f; - - bool begin() { return SHT4x_begin(); } - bool setPrecision(uint8_t precision) { return SHT4x_setPrecision(precision); } - float readTemperature() { SHT4x_readTemperature(); return temperature; } - float readHumidity() { SHT4x_readHumidity(); return humidity; } - bool getEvent() { return SHT4x_getEvent(); } -}; diff --git a/test/mocks/MockSPI.cpp b/test/mocks/MockSPI.cpp deleted file mode 100644 index 430c89b..0000000 --- a/test/mocks/MockSPI.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "SPI.h" - -// Define the extern variable -SPIClass SPI; \ No newline at end of file diff --git a/test/mocks/MockSensor.h b/test/mocks/MockSensor.h deleted file mode 100644 index 3c27298..0000000 --- a/test/mocks/MockSensor.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include "MockParticle.h" - -// This is a minimal mock of the Sensor base class that Kestrel inherits from -class Sensor { -public: - Sensor() {} - virtual ~Sensor() {} - - // Common base class properties - static constexpr int MAX_NUM_ERRORS = 10; // Maximum number of errors to log - uint32_t errors[MAX_NUM_ERRORS] = {0}; - uint8_t numErrors = 0; - bool errorOverwrite = false; - - // Common methods - virtual int throwError(uint32_t error) { - // Simple error handling implementation - if (numErrors < MAX_NUM_ERRORS) { - errors[numErrors++] = error; - } else { - errors[MAX_NUM_ERRORS - 1] = error; - errorOverwrite = true; - } - return 0; - } - - // Virtual methods that would be implemented by derived classes - virtual String begin(bool &criticalFault, bool &fault) { return ""; } - virtual String getData(void) { return ""; } - virtual String getMetadata(void) { return ""; } - virtual String getErrors(void) { return ""; } - virtual String selfDiagnostic(uint8_t diagnosticLevel) { return ""; } -}; \ No newline at end of file diff --git a/test/mocks/MockTimeProvider.h b/test/mocks/MockTimeProvider.h new file mode 100644 index 0000000..3d91242 --- /dev/null +++ b/test/mocks/MockTimeProvider.h @@ -0,0 +1,34 @@ +// tests/mocks/MockTimeProvider.h +#ifndef MOCK_TIME_PROVIDER_H +#define MOCK_TIME_PROVIDER_H + +#include "gmock/gmock.h" +#include "ITimeProvider.h" // Include the interface definition + +/** + * @brief Google Mock implementation of ITimeProvider for testing. + */ +class MockTimeProvider : public ITimeProvider { +public: + // Mock all methods defined in the interface + MOCK_METHOD(int, year, (), (override)); + MOCK_METHOD(int, year, (time_t t), (override)); + MOCK_METHOD(int, month, (), (override)); + MOCK_METHOD(int, month, (time_t t), (override)); + MOCK_METHOD(int, day, (), (override)); + MOCK_METHOD(int, day, (time_t t), (override)); + MOCK_METHOD(int, hour, (), (override)); + MOCK_METHOD(int, hour, (time_t t), (override)); + MOCK_METHOD(int, minute, (), (override)); + MOCK_METHOD(int, minute, (time_t t), (override)); + MOCK_METHOD(int, second, (), (override)); + MOCK_METHOD(int, second, (time_t t), (override)); + MOCK_METHOD(time_t, now, (), (override)); + MOCK_METHOD(void, setTime, (time_t t), (override)); + MOCK_METHOD(bool, isValid, (), (override)); + MOCK_METHOD(void, zone, (float GMT_Offset), (override)); + MOCK_METHOD(uint32_t, millis, (), (override)); + MOCK_METHOD(void, delay, (uint32_t ms), (override)); +}; + +#endif // MOCK_TIME_PROVIDER_H \ No newline at end of file diff --git a/test/mocks/MockVEML3328.cpp b/test/mocks/MockVEML3328.cpp deleted file mode 100644 index 38909fe..0000000 --- a/test/mocks/MockVEML3328.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "MockVEML3328.h" - -// Define fake functions -DEFINE_FAKE_VALUE_FUNC(bool, VEML3328_begin); -DEFINE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readRed); -DEFINE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readGreen); -DEFINE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readBlue); -DEFINE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readClear); -DEFINE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readIR); - -// Set default behavior -void setup_mock_VEML3328_defaults() { - VEML3328_begin_fake.return_val = true; - VEML3328_readRed_fake.return_val = 500; - VEML3328_readGreen_fake.return_val = 600; - VEML3328_readBlue_fake.return_val = 450; - VEML3328_readClear_fake.return_val = 800; - VEML3328_readIR_fake.return_val = 300; -} diff --git a/test/mocks/MockVEML3328.h b/test/mocks/MockVEML3328.h deleted file mode 100644 index 619355e..0000000 --- a/test/mocks/MockVEML3328.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "fff.h" -#include - -// Declare fake functions for VEML3328 (light sensor) -DECLARE_FAKE_VALUE_FUNC(bool, VEML3328_begin); -DECLARE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readRed); -DECLARE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readGreen); -DECLARE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readBlue); -DECLARE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readClear); -DECLARE_FAKE_VALUE_FUNC(uint16_t, VEML3328_readIR); - -// Mock class for VEML3328 -class VEML3328 { -public: - bool begin() { return VEML3328_begin(); } - uint16_t readRed() { return VEML3328_readRed(); } - uint16_t readGreen() { return VEML3328_readGreen(); } - uint16_t readBlue() { return VEML3328_readBlue(); } - uint16_t readClear() { return VEML3328_readClear(); } - uint16_t readIR() { return VEML3328_readIR(); } -}; diff --git a/test/mocks/MockWire.cpp b/test/mocks/MockWire.cpp deleted file mode 100644 index 2ef0b89..0000000 --- a/test/mocks/MockWire.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// test/mocks/wire_mock.cpp -#include "MockWireDeclare.h" - -// Define fake functions -DEFINE_FAKE_VOID_FUNC(Wire_begin); -DEFINE_FAKE_VOID_FUNC(Wire_setClock, unsigned long); -DEFINE_FAKE_VOID_FUNC(Wire_beginTransmission, uint8_t); -DEFINE_FAKE_VALUE_FUNC(uint8_t, Wire_endTransmission, bool); -DEFINE_FAKE_VALUE_FUNC(uint8_t, Wire_requestFrom_3args, uint8_t, uint8_t, bool); -DEFINE_FAKE_VALUE_FUNC(uint8_t, Wire_requestFrom_2args, uint8_t, uint8_t); -DEFINE_FAKE_VALUE_FUNC(int, Wire_available); -DEFINE_FAKE_VALUE_FUNC(int, Wire_read); -DEFINE_FAKE_VOID_FUNC(Wire_write_uint8, uint8_t); -DEFINE_FAKE_VOID_FUNC(Wire_write_buffer, const uint8_t*, size_t); - -// Define the global Wire instance -MockWire Wire; \ No newline at end of file diff --git a/test/mocks/MockWireDeclare.h b/test/mocks/MockWireDeclare.h deleted file mode 100644 index 334300c..0000000 --- a/test/mocks/MockWireDeclare.h +++ /dev/null @@ -1,41 +0,0 @@ -// test/mocks/mock_wire_defs.h -#ifndef WIRE_MOCK_DEFS_H -#define WIRE_MOCK_DEFS_H - -#include -#include "fff.h" - -// Declare fake functions -DECLARE_FAKE_VOID_FUNC(Wire_begin); -DECLARE_FAKE_VOID_FUNC(Wire_setClock, unsigned long); -DECLARE_FAKE_VOID_FUNC(Wire_beginTransmission, uint8_t); -DECLARE_FAKE_VALUE_FUNC(uint8_t, Wire_endTransmission, bool); -DECLARE_FAKE_VALUE_FUNC(uint8_t, Wire_requestFrom_3args, uint8_t, uint8_t, bool); -DECLARE_FAKE_VALUE_FUNC(uint8_t, Wire_requestFrom_2args, uint8_t, uint8_t); -DECLARE_FAKE_VALUE_FUNC(int, Wire_available); -DECLARE_FAKE_VALUE_FUNC(int, Wire_read); -DECLARE_FAKE_VOID_FUNC(Wire_write_uint8, uint8_t); -DECLARE_FAKE_VOID_FUNC(Wire_write_buffer, const uint8_t*, size_t); - -// Mock Wire class declaration -class MockWire { -public: - void begin() { Wire_begin(); } - void setClock(unsigned long clock) { Wire_setClock(clock); } - void beginTransmission(uint8_t address) { Wire_beginTransmission(address); } - uint8_t endTransmission(bool sendStop = true) { return Wire_endTransmission(sendStop); } - uint8_t requestFrom(uint8_t address, uint8_t quantity, bool sendStop) { - return Wire_requestFrom_3args(address, quantity, sendStop); - } - uint8_t requestFrom(uint8_t address, uint8_t quantity) { - return Wire_requestFrom_2args(address, quantity); - } - int available() { return Wire_available(); } - int read() { return Wire_read(); } - void write(uint8_t data) { Wire_write_uint8(data); } - void write(const uint8_t* data, size_t quantity) { Wire_write_buffer(data, quantity); } -}; - -extern MockWire Wire; - -#endif // WIRE_MOCK_DEFS_H \ No newline at end of file diff --git a/test/mocks/SPI.h b/test/mocks/SPI.h deleted file mode 100644 index 1f4fc88..0000000 --- a/test/mocks/SPI.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include // For size_t - -// SPI settings -#define SPI_MODE0 0x00 -#define SPI_MODE1 0x01 -#define SPI_MODE2 0x02 -#define SPI_MODE3 0x03 - -#define SPI_CLOCK_DIV2 0x00 -#define SPI_CLOCK_DIV4 0x01 -#define SPI_CLOCK_DIV8 0x02 -#define SPI_CLOCK_DIV16 0x03 -#define SPI_CLOCK_DIV32 0x04 -#define SPI_CLOCK_DIV64 0x05 -#define SPI_CLOCK_DIV128 0x06 - -// Simple mock for the SPI class -class SPIClass { -public: - void begin() {} - void beginTransaction(uint32_t settings) {} - void endTransaction() {} - uint8_t transfer(uint8_t data) { return 0; } - void transfer(void *buf, size_t count) {} -}; - -extern SPIClass SPI; \ No newline at end of file diff --git a/test/mocks/TestKestrel.h b/test/mocks/TestKestrel.h deleted file mode 100644 index 8898d5f..0000000 --- a/test/mocks/TestKestrel.h +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -// Modified Kestrel.h intended for testing only -// This provides a controlled environment without class redefinitions - -// Include all mocks we need -#include "MockArduino.h" -#include "MockSensor.h" -#include "MockPCAL9535A.h" -#include "MockPCA9634.h" -#include "MockMCP79412.h" -#include "MockGNSS.h" -#include "MockPAC1934.h" -#include "MockVEML3328.h" -#include "MockSHT4x.h" -#include "MockMXC6655.h" -#include "MockBMA456.h" -#include "MockWireDeclare.h" - -// Define constants and namespaces from Kestrel.h that we need for testing -namespace Pins { - constexpr uint16_t WD_HOLD = D2; - constexpr uint16_t SD_CS = D8; - constexpr uint16_t Clock_INT = D22; - constexpr uint16_t TALON1_GPIOA = A3; - constexpr uint16_t TALON1_GPIOB = D7; - constexpr uint16_t TALON2_GPIOA = A2; - constexpr uint16_t TALON2_GPIOB = D6; - constexpr uint16_t TALON3_GPIOA = A1; - constexpr uint16_t TALON3_GPIOB = D5; - constexpr uint16_t I2C_GLOBAL_EN = D23; - constexpr uint16_t I2C_OB_EN = A6; -} - -namespace PinsOB { - constexpr uint16_t I2C_EXT_EN = 10; - constexpr uint16_t SD_CD = 8; - constexpr uint16_t SD_EN = 12; - constexpr uint16_t AUX_EN = 15; - constexpr uint16_t CE = 11; - constexpr uint16_t LED_EN = 13; - constexpr uint16_t CSA_EN = 14; - constexpr uint16_t GPS_INT = 7; -} - -namespace PinsTalon { - constexpr uint8_t SEL[4] = {0, 4, 8, 12}; - constexpr uint8_t I2C_EN[4] = {1, 5, 9, 13}; - constexpr uint8_t EN[4] = {3, 7, 11, 15}; - constexpr uint8_t FAULT[4] = {2, 6, 10, 14}; -} - -namespace TimeSource { - constexpr uint8_t INCREMENT = 4; - constexpr uint8_t RTC = 3; - constexpr uint8_t GPS_RTC = 2; - constexpr uint8_t CELLULAR = 1; - constexpr uint8_t GPS = 0; - constexpr uint8_t NONE = 5; -} - -namespace IndicatorLight { - constexpr uint8_t SENSORS = 1; - constexpr uint8_t GPS = 2; - constexpr uint8_t CELL = 3; - constexpr uint8_t STAT = 4; - constexpr uint8_t ALL = 5; -} - -namespace IndicatorMode { - constexpr uint8_t NONE = 0; - constexpr uint8_t PASS = 1; - constexpr uint8_t WAITING = 2; - constexpr uint8_t ERROR = 3; - constexpr uint8_t ERROR_CRITICAL = 4; - constexpr uint8_t PREPASS = 5; - constexpr uint8_t INIT = 6; - constexpr uint8_t IDLE = 7; - constexpr uint8_t COMMAND = 8; -} - -namespace AccelType { - constexpr uint8_t MXC6655 = 0; - constexpr uint8_t BMA456 = 1; -} - -namespace HardwareVersion { - constexpr uint8_t PRE_1v9 = 0; - constexpr uint8_t MODEL_1v9 = 1; -} - -struct dateTimeStruct { - int year; - int month; - int day; - int hour; - int minute; - int second; - uint8_t source = TimeSource::NONE; -}; - -// Simplified version of Kestrel for testing -// We'll manually implement the methods we want to test -class Kestrel : public Sensor { -public: - constexpr static int MAX_NUM_ERRORS = 10; - const std::string FIRMWARE_VERSION = "1.7.5"; - static constexpr uint8_t numTalonPorts = 5; - static constexpr int MAX_MESSAGE_LENGTH = 1024; - - dateTimeStruct currentDateTime = {2049, 6, 16, 3, 27, 31, TimeSource::NONE}; - uint8_t timeFix = 0; - SFE_UBLOX_GNSS gps; - - // Constructor - Kestrel(bool useSensors = false) : reportSensors(useSensors) { - // Initialize member objects - } - - // Public methods we want to test - std::string begin(time_t time, bool &criticalFault, bool &fault) { - // Call internal device initializations - ioOB.begin(); - ioTalon.begin(); - rtc.begin(); - led.begin(); - - if (reportSensors) { - als.begin(); - csaAlpha.begin(); - csaBeta.begin(); - atmos.begin(); - accel.begin(); - gps.begin(); - } - - // Return success message - return "Kestrel " + FIRMWARE_VERSION + " initialized successfully"; - } - - bool enablePower(uint8_t port, bool state = true) { - if (port >= numTalonPorts) return false; - - // Call IO expander to enable/disable power - return ioTalon.digitalWrite(PinsTalon::EN[port], state); - } - - bool enableData(uint8_t port, bool state = true) { - if (port >= numTalonPorts) return false; - - // Call IO expander to enable/disable data - return ioTalon.digitalWrite(PinsTalon::I2C_EN[port], state); - } - - time_t getTime() { - return rtc.getTime(); - } - - bool enableI2C_OB(bool state = true) { - return ioOB.digitalWrite(PinsOB::I2C_EXT_EN, state); - } - - bool enableI2C_Global(bool state = true) { - // In our mock environment, digitalWrite returns void - // But in the real implementation it would return a status - digitalWrite(Pins::I2C_GLOBAL_EN, state); - return true; // Assume success - } - - bool enableI2C_External(bool state = true) { - return ioOB.digitalWrite(PinsOB::I2C_EXT_EN, state); - } - - bool setIndicatorState(uint8_t ledBank, uint8_t mode) { - int brightness = 0; - - // Convert mode to brightness - switch (mode) { - case IndicatorMode::PASS: - brightness = 75; - break; - case IndicatorMode::ERROR: - brightness = 100; - break; - default: - brightness = 0; - break; - } - - return led.setBrightness(ledBank, brightness); - } - - // Other methods as needed for testing... - -private: - PCAL9535A ioOB; - PCAL9535A ioTalon; - MCP79412 rtc; - PAC1934 csaAlpha; - PAC1934 csaBeta; - VEML3328 als; - Adafruit_SHT4x atmos; - MXC6655 accel; - PCA9634 led; - bool reportSensors = false; -}; - -// Helper functions for testing Kestrel -namespace KestrelTest { - // Setup a Kestrel instance with all mock dependencies properly configured - inline Kestrel* createKestrel() { - // Configure all mock return values for a successful initialization - PCAL9535A_begin_fake.return_val = true; - MCP79412_begin_fake.return_val = true; - MCP79412_getTime_fake.return_val = 1616161616; - PCA9634_begin_fake.return_val = true; - VEML3328_begin_fake.return_val = true; - PAC1934_begin_fake.return_val = true; - SHT4x_begin_fake.return_val = true; - MXC6655_begin_fake.return_val = true; - BMA456_begin_fake.return_val = true; - GNSS_begin_fake.return_val = true; - - // Create a Kestrel instance - return new Kestrel(true); // true = use sensors - } - - // Reset all mocks for a clean slate - inline void resetAllMocks() { - // Wire mocks - RESET_FAKE(Wire_begin); - RESET_FAKE(Wire_setClock); - RESET_FAKE(Wire_beginTransmission); - RESET_FAKE(Wire_endTransmission); - RESET_FAKE(Wire_requestFrom_3args); - RESET_FAKE(Wire_requestFrom_2args); - RESET_FAKE(Wire_available); - RESET_FAKE(Wire_read); - RESET_FAKE(Wire_write_uint8); - RESET_FAKE(Wire_write_buffer); - - // Arduino mocks - RESET_FAKE(pinMode); - RESET_FAKE(digitalWrite); - RESET_FAKE(digitalRead); - RESET_FAKE(millis); - RESET_FAKE(delay); - - // Hardware component mocks - RESET_FAKE(PCAL9535A_begin); - RESET_FAKE(PCAL9535A_pinMode); - RESET_FAKE(PCAL9535A_digitalWrite); - RESET_FAKE(PCAL9535A_digitalRead); - - RESET_FAKE(MCP79412_begin); - RESET_FAKE(MCP79412_getTime); - RESET_FAKE(MCP79412_setTime); - - RESET_FAKE(PCA9634_begin); - RESET_FAKE(PCA9634_setBrightness); - RESET_FAKE(PCA9634_setLEDOutputMode); - - RESET_FAKE(VEML3328_begin); - RESET_FAKE(VEML3328_readRed); - RESET_FAKE(VEML3328_readGreen); - RESET_FAKE(VEML3328_readBlue); - - RESET_FAKE(PAC1934_begin); - RESET_FAKE(PAC1934_readVoltage); - RESET_FAKE(PAC1934_readCurrent); - - RESET_FAKE(SHT4x_begin); - RESET_FAKE(SHT4x_readTemperature); - RESET_FAKE(SHT4x_readHumidity); - - RESET_FAKE(MXC6655_begin); - RESET_FAKE(MXC6655_readAcceleration); - - RESET_FAKE(BMA456_begin); - RESET_FAKE(BMA456_readAcceleration); - RESET_FAKE(BMA456_getStepCount); - - RESET_FAKE(GNSS_begin); - RESET_FAKE(GNSS_getLatitude); - RESET_FAKE(GNSS_getLongitude); - RESET_FAKE(GNSS_getAltitude); - } - - // Set default successful return values for hardware operations - inline void setDefaultMockBehavior() { - // Configure default successful behaviors - Wire_endTransmission_fake.return_val = 0; // Success - Wire_available_fake.return_val = 1; // Data available - - PCAL9535A_begin_fake.return_val = true; - PCAL9535A_digitalWrite_fake.return_val = true; - PCAL9535A_digitalRead_fake.return_val = 0; // Default to LOW - - MCP79412_begin_fake.return_val = true; - MCP79412_getTime_fake.return_val = 1616161616; - MCP79412_setTime_fake.return_val = true; - - PCA9634_begin_fake.return_val = true; - PCA9634_setBrightness_fake.return_val = true; - PCA9634_setLEDOutputMode_fake.return_val = true; - - VEML3328_begin_fake.return_val = true; - VEML3328_readRed_fake.return_val = 500; - VEML3328_readGreen_fake.return_val = 600; - VEML3328_readBlue_fake.return_val = 400; - - PAC1934_begin_fake.return_val = true; - PAC1934_readVoltage_fake.return_val = 3.3f; - PAC1934_readCurrent_fake.return_val = 0.1f; - - SHT4x_begin_fake.return_val = true; - - MXC6655_begin_fake.return_val = true; - BMA456_begin_fake.return_val = true; - - GNSS_begin_fake.return_val = true; - GNSS_isConnected_fake.return_val = true; - GNSS_getLatitude_fake.return_val = 449673925; - GNSS_getLongitude_fake.return_val = -932838386; - GNSS_getAltitude_fake.return_val = 25000; - GNSS_getSIV_fake.return_val = 8; - GNSS_getYear_fake.return_val = 2023; - GNSS_getMonth_fake.return_val = 5; - GNSS_getDay_fake.return_val = 15; - GNSS_getHour_fake.return_val = 10; - GNSS_getMinute_fake.return_val = 30; - GNSS_getSecond_fake.return_val = 0; - - millis_fake.return_val = 1000; // Start at 1 second - } -} \ No newline at end of file diff --git a/test/mocks/WProgram.h b/test/mocks/WProgram.h deleted file mode 100644 index f638a01..0000000 --- a/test/mocks/WProgram.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -// This is for older Arduino code that used WProgram.h instead of Arduino.h -#include "Arduino.h" \ No newline at end of file diff --git a/test/mocks/Wire.h b/test/mocks/Wire.h deleted file mode 100644 index 993e1f4..0000000 --- a/test/mocks/Wire.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "MockWireDeclare.h" - -// This is just a header to include our Wire mock \ No newline at end of file