release
This commit is contained in:
102
lib/home-assistant-integration/src/mocks/AUnitHelpers.h
Normal file
102
lib/home-assistant-integration/src/mocks/AUnitHelpers.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef AHA_AUNITHELPERS_H
|
||||
#define AHA_AUNITHELPERS_H
|
||||
|
||||
#ifdef ARDUINOHA_TEST
|
||||
|
||||
#ifdef AUNITER
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include <MemoryUsage.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define initMqttTest(testDeviceId) \
|
||||
PubSubClientMock* mock = new PubSubClientMock(); \
|
||||
HADevice device(testDeviceId); \
|
||||
HAMqtt mqtt(mock, device); \
|
||||
mqtt.setDataPrefix("testData"); \
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
|
||||
#define assertNoMqttMessage() \
|
||||
assertTrue(mock->getFlushedMessagesNb() == 0);
|
||||
|
||||
#define assertMqttMessage(index, eTopic, eMessage, eRetained) { \
|
||||
const __FlashStringHelper* messageP = F(eMessage); \
|
||||
size_t messageLen = strlen_P(reinterpret_cast<const char *>(messageP)); \
|
||||
assertTrue(mock->getFlushedMessagesNb() > 0); \
|
||||
assertTrue(mock->getFlushedMessagesNb() > index); \
|
||||
MqttMessage* publishedMessage = mock->getFlushedMessages()[index]; \
|
||||
assertEqual(eTopic, publishedMessage->topic); \
|
||||
assertEqual(messageP, publishedMessage->buffer); \
|
||||
assertEqual(messageLen, publishedMessage->bufferSize - 1); \
|
||||
assertEqual(eRetained, publishedMessage->retained); \
|
||||
}
|
||||
|
||||
#define assertSingleMqttMessage(eTopic, eMessage, eRetained) { \
|
||||
assertEqual(1, mock->getFlushedMessagesNb()); \
|
||||
assertMqttMessage(0, eTopic, eMessage, eRetained) \
|
||||
}
|
||||
|
||||
#define assertEntityConfig(mock, entity, expectedJson) \
|
||||
{ \
|
||||
mqtt.loop(); \
|
||||
assertMqttMessage(0, AHATOFSTR(ConfigTopic), expectedJson, true) \
|
||||
assertTrue(entity.getSerializer() == nullptr); \
|
||||
}
|
||||
|
||||
#define assertEntityConfigOnTopic(mock, entity, topic, expectedJson) \
|
||||
{ \
|
||||
mqtt.loop(); \
|
||||
assertMqttMessage(0, topic, expectedJson, true) \
|
||||
assertTrue(entity.getSerializer() == nullptr); \
|
||||
}
|
||||
|
||||
#ifdef AUNITER
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define AHA_FREERAM mu_freeRam()
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#define AHA_FREERAM ESP.getFreeHeap()
|
||||
#else
|
||||
#define AHA_FREERAM 0
|
||||
#endif
|
||||
|
||||
#define AHA_LEAKTRACKSTART \
|
||||
int freeRam = AHA_FREERAM;
|
||||
|
||||
#define AHA_LEAKTRACKEND \
|
||||
int diff = freeRam - AHA_FREERAM; \
|
||||
if (diff < 0) { diff *= -1; } \
|
||||
if (diff != 0) { \
|
||||
Serial.print(Test::getName().getFString()); \
|
||||
Serial.print(F(" memory leak: ")); \
|
||||
Serial.print(diff); \
|
||||
Serial.println(F("b")); \
|
||||
Test::fail(); \
|
||||
}
|
||||
#else
|
||||
// EpoxyDuino doesn't support memory tracking
|
||||
#define AHA_LEAKTRACKSTART
|
||||
#define AHA_LEAKTRACKEND
|
||||
#endif
|
||||
|
||||
#define AHA_TEST(suiteName, name) \
|
||||
class suiteName##_##name : public aunit::TestOnce { \
|
||||
public: \
|
||||
suiteName##_##name(); \
|
||||
void once() override; \
|
||||
void loop() override { \
|
||||
AHA_LEAKTRACKSTART \
|
||||
once(); \
|
||||
if (isNotDone()) { pass(); } \
|
||||
AHA_LEAKTRACKEND \
|
||||
} \
|
||||
} suiteName##_##name##_instance; \
|
||||
suiteName##_##name :: suiteName##_##name() { \
|
||||
init(AUNIT_F(#suiteName "_" #name)); \
|
||||
} \
|
||||
void suiteName##_##name :: once()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
268
lib/home-assistant-integration/src/mocks/PubSubClientMock.cpp
Normal file
268
lib/home-assistant-integration/src/mocks/PubSubClientMock.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "PubSubClientMock.h"
|
||||
#ifdef ARDUINOHA_TEST
|
||||
|
||||
#include "../ArduinoHADefines.h"
|
||||
|
||||
PubSubClientMock::PubSubClientMock() :
|
||||
_pendingMessage(nullptr),
|
||||
_flushedMessages(nullptr),
|
||||
_flushedMessagesNb(0),
|
||||
_subscriptions(nullptr),
|
||||
_subscriptionsNb(0),
|
||||
callback(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PubSubClientMock::~PubSubClientMock()
|
||||
{
|
||||
if (_pendingMessage) {
|
||||
delete _pendingMessage;
|
||||
}
|
||||
|
||||
clearFlushedMessages();
|
||||
clearSubscriptions();
|
||||
}
|
||||
|
||||
bool PubSubClientMock::loop()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
|
||||
void PubSubClientMock::disconnect()
|
||||
{
|
||||
_connection.connected = false;
|
||||
}
|
||||
|
||||
bool PubSubClientMock::connected()
|
||||
{
|
||||
return _connection.connected;
|
||||
}
|
||||
|
||||
bool PubSubClientMock::connect(
|
||||
const char *id,
|
||||
const char *user,
|
||||
const char *pass,
|
||||
const char* willTopic,
|
||||
uint8_t willQos,
|
||||
bool willRetain,
|
||||
const char* willMessage,
|
||||
bool cleanSession
|
||||
)
|
||||
{
|
||||
(void)willQos;
|
||||
(void)cleanSession;
|
||||
|
||||
_connection.connected = true;
|
||||
_connection.id = id;
|
||||
_connection.user = user;
|
||||
_connection.pass = pass;
|
||||
|
||||
_lastWill.topic = willTopic;
|
||||
_lastWill.message = willMessage;
|
||||
_lastWill.retain = willRetain;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PubSubClientMock::connectDummy()
|
||||
{
|
||||
_connection.connected = true;
|
||||
_connection.id = "dummyId";
|
||||
_connection.user = nullptr;
|
||||
_connection.pass = nullptr;
|
||||
|
||||
_lastWill.topic = nullptr;
|
||||
_lastWill.message = nullptr;
|
||||
_lastWill.retain = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PubSubClientMock& PubSubClientMock::setServer(IPAddress ip, uint16_t port)
|
||||
{
|
||||
_connection.ip = ip;
|
||||
_connection.port = port;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClientMock& PubSubClientMock::setServer(
|
||||
const char * domain,
|
||||
uint16_t port
|
||||
)
|
||||
{
|
||||
_connection.domain = domain;
|
||||
_connection.port = port;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClientMock& PubSubClientMock::setCallback(MQTT_CALLBACK_SIGNATURE)
|
||||
{
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool PubSubClientMock::beginPublish(
|
||||
const char* topic,
|
||||
unsigned int plength,
|
||||
bool retained
|
||||
)
|
||||
{
|
||||
if (!connected()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_pendingMessage) {
|
||||
delete _pendingMessage;
|
||||
}
|
||||
|
||||
_pendingMessage = new MqttMessage();
|
||||
_pendingMessage->retained = retained;
|
||||
|
||||
{
|
||||
size_t size = strlen(topic) + 1;
|
||||
_pendingMessage->topic = new char[size];
|
||||
_pendingMessage->topicSize = size;
|
||||
|
||||
memset(_pendingMessage->topic, 0, size);
|
||||
memcpy(_pendingMessage->topic, topic, size);
|
||||
}
|
||||
|
||||
{
|
||||
size_t size = plength + 1;
|
||||
_pendingMessage->buffer = new char[size];
|
||||
_pendingMessage->bufferSize = size;
|
||||
|
||||
memset(_pendingMessage->buffer, 0, size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t PubSubClientMock::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
if (!_pendingMessage || !_pendingMessage->buffer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncat(_pendingMessage->buffer, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t PubSubClientMock::print(const __FlashStringHelper* buffer)
|
||||
{
|
||||
const size_t len = strlen_P(reinterpret_cast<const char*>(buffer));
|
||||
char data[len + 1]; // including null terminator
|
||||
strcpy_P(data, reinterpret_cast<const char*>(buffer));
|
||||
|
||||
return write((const uint8_t*)(data), len);
|
||||
}
|
||||
|
||||
int PubSubClientMock::endPublish()
|
||||
{
|
||||
if (!_pendingMessage) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t messageSize = _pendingMessage->bufferSize;
|
||||
uint8_t index = _flushedMessagesNb;
|
||||
|
||||
_flushedMessagesNb++;
|
||||
_flushedMessages = static_cast<MqttMessage**>(
|
||||
realloc(_flushedMessages, _flushedMessagesNb * sizeof(MqttMessage*))
|
||||
);
|
||||
|
||||
_flushedMessages[index] = _pendingMessage; // handover memory responsibility
|
||||
_pendingMessage = nullptr; // do not call destructor
|
||||
|
||||
return messageSize;
|
||||
}
|
||||
|
||||
bool PubSubClientMock::subscribe(const char* topic)
|
||||
{
|
||||
uint8_t index = _subscriptionsNb;
|
||||
|
||||
_subscriptionsNb++;
|
||||
_subscriptions = static_cast<MqttSubscription**>(
|
||||
realloc(_subscriptions, _subscriptionsNb * sizeof(MqttSubscription*))
|
||||
);
|
||||
|
||||
size_t topicSize = strlen(topic) + 1;
|
||||
MqttSubscription* subscription = new MqttSubscription();
|
||||
subscription->topic = new char[topicSize];
|
||||
memcpy(subscription->topic, topic, topicSize);
|
||||
|
||||
_subscriptions[index] = subscription;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PubSubClientMock::clearFlushedMessages()
|
||||
{
|
||||
if (_flushedMessages) {
|
||||
for (uint8_t i = 0; i < _flushedMessagesNb; i++) {
|
||||
delete _flushedMessages[i];
|
||||
}
|
||||
|
||||
delete _flushedMessages;
|
||||
}
|
||||
|
||||
_flushedMessagesNb = 0;
|
||||
}
|
||||
|
||||
void PubSubClientMock::clearSubscriptions()
|
||||
{
|
||||
if (_subscriptions) {
|
||||
for (uint8_t i = 0; i < _subscriptionsNb; i++) {
|
||||
delete _subscriptions[i];
|
||||
}
|
||||
|
||||
delete _subscriptions;
|
||||
}
|
||||
|
||||
_subscriptionsNb = 0;
|
||||
}
|
||||
|
||||
void PubSubClientMock::fakeMessage(const char* topic, const char* message)
|
||||
{
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t len = strlen(message);
|
||||
uint8_t data[len];
|
||||
memcpy(data, message, len);
|
||||
|
||||
callback(const_cast<char*>(topic), data, len);
|
||||
}
|
||||
|
||||
void PubSubClientMock::fakeMessage(
|
||||
const __FlashStringHelper* topic,
|
||||
const char* message
|
||||
)
|
||||
{
|
||||
char topicStr[strlen_P(AHAFROMFSTR(topic)) + 1];
|
||||
topicStr[0] = 0;
|
||||
strcpy_P(topicStr, AHAFROMFSTR(topic));
|
||||
|
||||
fakeMessage(topicStr, message);
|
||||
}
|
||||
|
||||
void PubSubClientMock::fakeMessage(
|
||||
const __FlashStringHelper* topic,
|
||||
const __FlashStringHelper* message
|
||||
)
|
||||
{
|
||||
char topicStr[strlen_P(AHAFROMFSTR(topic)) + 1];
|
||||
topicStr[0] = 0;
|
||||
strcpy_P(topicStr, AHAFROMFSTR(topic));
|
||||
|
||||
char messageStr[strlen_P(AHAFROMFSTR(message)) + 1];
|
||||
messageStr[0] = 0;
|
||||
strcpy_P(messageStr, AHAFROMFSTR(message));
|
||||
|
||||
fakeMessage(topicStr, messageStr);
|
||||
}
|
||||
|
||||
#endif
|
||||
166
lib/home-assistant-integration/src/mocks/PubSubClientMock.h
Normal file
166
lib/home-assistant-integration/src/mocks/PubSubClientMock.h
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef AHA_PUBSUBCLIENTMOCK_H
|
||||
#define AHA_PUBSUBCLIENTMOCK_H
|
||||
|
||||
#ifdef ARDUINOHA_TEST
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#include <functional>
|
||||
#define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
|
||||
#else
|
||||
#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
|
||||
#endif
|
||||
|
||||
struct MqttMessage
|
||||
{
|
||||
char* topic;
|
||||
size_t topicSize;
|
||||
char* buffer;
|
||||
size_t bufferSize;
|
||||
bool retained;
|
||||
|
||||
MqttMessage() :
|
||||
topic(nullptr),
|
||||
topicSize(0),
|
||||
buffer(nullptr),
|
||||
bufferSize(0),
|
||||
retained(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~MqttMessage()
|
||||
{
|
||||
if (topic) {
|
||||
delete topic;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MqttSubscription {
|
||||
char* topic;
|
||||
|
||||
MqttSubscription() :
|
||||
topic(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~MqttSubscription()
|
||||
{
|
||||
if (topic) {
|
||||
delete topic;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MqttConnection
|
||||
{
|
||||
bool connected;
|
||||
const char* domain;
|
||||
IPAddress ip;
|
||||
uint16_t port;
|
||||
const char* id;
|
||||
const char* user;
|
||||
const char* pass;
|
||||
|
||||
MqttConnection() :
|
||||
connected(false),
|
||||
domain(nullptr),
|
||||
port(0),
|
||||
id(nullptr),
|
||||
user(nullptr),
|
||||
pass(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct MqttWill
|
||||
{
|
||||
const char* topic;
|
||||
const char* message;
|
||||
bool retain;
|
||||
|
||||
MqttWill() :
|
||||
topic(nullptr),
|
||||
message(nullptr),
|
||||
retain(false)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class PubSubClientMock
|
||||
{
|
||||
public:
|
||||
PubSubClientMock();
|
||||
~PubSubClientMock();
|
||||
|
||||
bool loop();
|
||||
void disconnect();
|
||||
bool connected();
|
||||
bool connect(
|
||||
const char *id,
|
||||
const char *user,
|
||||
const char *pass,
|
||||
const char* willTopic,
|
||||
uint8_t willQos,
|
||||
bool willRetain,
|
||||
const char* willMessage,
|
||||
bool cleanSession
|
||||
);
|
||||
bool connectDummy();
|
||||
PubSubClientMock& setServer(IPAddress ip, uint16_t port);
|
||||
PubSubClientMock& setServer(const char* domain, uint16_t port);
|
||||
PubSubClientMock& setCallback(MQTT_CALLBACK_SIGNATURE);
|
||||
|
||||
bool beginPublish(const char* topic, unsigned int plength, bool retained);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t print(const __FlashStringHelper* buffer);
|
||||
int endPublish();
|
||||
bool subscribe(const char* topic);
|
||||
|
||||
inline uint8_t getFlushedMessagesNb() const
|
||||
{ return _flushedMessagesNb; }
|
||||
|
||||
inline MqttMessage** getFlushedMessages() const
|
||||
{ return _flushedMessages; }
|
||||
|
||||
inline uint8_t getSubscriptionsNb() const
|
||||
{ return _subscriptionsNb; }
|
||||
|
||||
inline MqttSubscription** getSubscriptions() const
|
||||
{ return _subscriptions; }
|
||||
|
||||
inline const MqttConnection& getConnection() const
|
||||
{ return _connection; }
|
||||
|
||||
inline const MqttWill& getLastWill() const
|
||||
{ return _lastWill; }
|
||||
|
||||
void clearFlushedMessages();
|
||||
void clearSubscriptions();
|
||||
void fakeMessage(const char* topic, const char* message);
|
||||
void fakeMessage(const __FlashStringHelper* topic, const char* message);
|
||||
void fakeMessage(const __FlashStringHelper* topic, const __FlashStringHelper* message);
|
||||
|
||||
private:
|
||||
MqttMessage* _pendingMessage;
|
||||
MqttMessage** _flushedMessages;
|
||||
uint8_t _flushedMessagesNb;
|
||||
MqttSubscription** _subscriptions;
|
||||
uint8_t _subscriptionsNb;
|
||||
MqttConnection _connection;
|
||||
MqttWill _lastWill;
|
||||
MQTT_CALLBACK_SIGNATURE;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user