mirror of
https://github.com/alexhopeoconnor/arduino-home-assistant.git
synced 2026-10-04 02:48:13 +10:00
Per-entity availability, deferred discovery publish, suggested precision
- Add HAAvailabilityConfig for per-entity availability_topic and payloads - Defer discovery until MQTT connected; publish availability after discovery - HASensor/HANumber: optional suggested_display_precision in discovery - HASerializer/HADictionary: extend for new keys; update device types and mocks - Docs and examples reflect availability and precision usage - Tests updated for discovery and availability behavior - Ignore .cursor/ in repo root
This commit is contained in:
@@ -19,6 +19,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_BinarySensorTest_publish_initial_state),
|
||||
TEST_ENTRY(test_BinarySensorTest_publish_state_debounce),
|
||||
TEST_ENTRY(test_BinarySensorTest_publish_state_debounce_skip),
|
||||
TEST_ENTRY(test_BinarySensorTest_disconnected_state_updates_local_shadow),
|
||||
TEST_ENTRY(test_BinarySensorTest_publish_state_off),
|
||||
TEST_ENTRY(test_BinarySensorTest_publish_state_on),
|
||||
TEST_ENTRY(test_ButtonTest_availability),
|
||||
@@ -57,6 +58,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_p3_zero_signed),
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_p3_zero_unsigned),
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_precision_mismatch),
|
||||
TEST_ENTRY(test_SensorNumberTest_disconnected_value_updates_local_shadow),
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_uint16),
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_uint32),
|
||||
TEST_ENTRY(test_SensorNumberTest_publish_uint8),
|
||||
@@ -85,7 +87,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_SwitchTest_command_off),
|
||||
TEST_ENTRY(test_SwitchTest_command_on),
|
||||
TEST_ENTRY(test_SwitchTest_command_subscription),
|
||||
TEST_ENTRY(test_SwitchTest_callback_publish_attempt_is_rejected),
|
||||
TEST_ENTRY(test_SwitchTest_callback_publish_is_deferred_until_after_dispatch),
|
||||
TEST_ENTRY(test_SwitchTest_current_state_setter),
|
||||
TEST_ENTRY(test_SwitchTest_default_entity_id_setter),
|
||||
TEST_ENTRY(test_SwitchTest_default_params),
|
||||
@@ -121,7 +123,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_TextTest_publish_nothing_if_retained),
|
||||
TEST_ENTRY(test_TextTest_publish_state),
|
||||
TEST_ENTRY(test_TextTest_publish_state_debounce),
|
||||
TEST_ENTRY(test_TextTest_callback_publish_attempt_is_rejected),
|
||||
TEST_ENTRY(test_TextTest_callback_publish_is_deferred_until_after_dispatch),
|
||||
TEST_ENTRY(test_TextTest_retain_setter),
|
||||
};
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ extern void test_BinarySensorTest_object_id_setter(void);
|
||||
extern void test_BinarySensorTest_publish_initial_state(void);
|
||||
extern void test_BinarySensorTest_publish_state_debounce(void);
|
||||
extern void test_BinarySensorTest_publish_state_debounce_skip(void);
|
||||
extern void test_BinarySensorTest_disconnected_state_updates_local_shadow(void);
|
||||
extern void test_BinarySensorTest_publish_state_off(void);
|
||||
extern void test_BinarySensorTest_publish_state_on(void);
|
||||
extern void test_ButtonTest_availability(void);
|
||||
@@ -67,6 +68,7 @@ extern void test_SensorNumberTest_publish_p3_smaller(void);
|
||||
extern void test_SensorNumberTest_publish_p3_zero_signed(void);
|
||||
extern void test_SensorNumberTest_publish_p3_zero_unsigned(void);
|
||||
extern void test_SensorNumberTest_publish_precision_mismatch(void);
|
||||
extern void test_SensorNumberTest_disconnected_value_updates_local_shadow(void);
|
||||
extern void test_SensorNumberTest_publish_uint16(void);
|
||||
extern void test_SensorNumberTest_publish_uint32(void);
|
||||
extern void test_SensorNumberTest_publish_uint8(void);
|
||||
@@ -113,7 +115,7 @@ extern void test_SwitchTest_publish_nothing_if_retained(void);
|
||||
extern void test_SwitchTest_publish_state_off(void);
|
||||
extern void test_SwitchTest_publish_state_on(void);
|
||||
extern void test_SwitchTest_retain_setter(void);
|
||||
extern void test_SwitchTest_callback_publish_attempt_is_rejected(void);
|
||||
extern void test_SwitchTest_callback_publish_is_deferred_until_after_dispatch(void);
|
||||
extern void test_TextTest_availability(void);
|
||||
extern void test_TextTest_command_callback(void);
|
||||
extern void test_TextTest_command_subscription(void);
|
||||
@@ -132,6 +134,6 @@ extern void test_TextTest_publish_nothing_if_retained(void);
|
||||
extern void test_TextTest_publish_state(void);
|
||||
extern void test_TextTest_publish_state_debounce(void);
|
||||
extern void test_TextTest_retain_setter(void);
|
||||
extern void test_TextTest_callback_publish_attempt_is_rejected(void);
|
||||
extern void test_TextTest_callback_publish_is_deferred_until_after_dispatch(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -281,3 +281,13 @@ void test_BinarySensorTest_publish_state_debounce_skip(void) {
|
||||
TEST_ASSERT_TRUE(result);
|
||||
}
|
||||
|
||||
void test_BinarySensorTest_disconnected_state_updates_local_shadow(void) {
|
||||
initMqttTest(testDeviceId)
|
||||
|
||||
HABinarySensor sensor(testUniqueId);
|
||||
|
||||
TEST_ASSERT_FALSE(sensor.setState(true));
|
||||
TEST_ASSERT_TRUE(sensor.getCurrentState());
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
}
|
||||
|
||||
|
||||
@@ -676,3 +676,14 @@ void test_SensorNumberTest_publish_precision_mismatch(void) {
|
||||
TEST_ASSERT_EQUAL(mock->getFlushedMessagesNb(), 0);
|
||||
}
|
||||
|
||||
void test_SensorNumberTest_disconnected_value_updates_local_shadow(void) {
|
||||
initMqttTest(testDeviceId)
|
||||
|
||||
HASensorNumber sensor(testUniqueId, HASensorNumber::PrecisionP1);
|
||||
|
||||
TEST_ASSERT_FALSE(sensor.setValue(27.5f));
|
||||
TEST_ASSERT_TRUE(sensor.getCurrentValue().isSet());
|
||||
AHA_ASSERT_NEAR_FLOAT(27.5f, sensor.getCurrentValue().toFloat(), 0.1f);
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ void onCommandReceived(bool state, HASwitch* caller)
|
||||
lastCommandCallbackCall.caller = caller;
|
||||
}
|
||||
|
||||
void onCommandPublishAttempt(bool state, HASwitch* caller)
|
||||
void onCommandDeferredPublish(bool state, HASwitch* caller)
|
||||
{
|
||||
TEST_ASSERT_FALSE(caller->setState(state));
|
||||
TEST_ASSERT_TRUE(caller->setState(state));
|
||||
}
|
||||
|
||||
void test_SwitchTest_invalid_unique_id(void) {
|
||||
@@ -393,17 +393,19 @@ void test_SwitchTest_command_off(void) {
|
||||
assertCommandCallbackCalled(false, &testSwitch)
|
||||
}
|
||||
|
||||
void test_SwitchTest_callback_publish_attempt_is_rejected(void) {
|
||||
void test_SwitchTest_callback_publish_is_deferred_until_after_dispatch(void) {
|
||||
prepareTest
|
||||
|
||||
mock->connectDummy();
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
HASwitch testSwitch(testUniqueId);
|
||||
testSwitch.onCommand(onCommandPublishAttempt);
|
||||
testSwitch.onCommand(onCommandDeferredPublish);
|
||||
|
||||
mock->fakeMessage(AHATOFSTR(CommandTopic), F("ON"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, mock->getPublishCallsFromCallbackNb());
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
AHA_ASSERT_MQTT_MESSAGE(mock, 0, AHATOFSTR(StateTopic), "ON", true);
|
||||
}
|
||||
|
||||
void test_SwitchTest_different_switch_command(void) {
|
||||
|
||||
@@ -46,9 +46,9 @@ void onCommandReceived(const char* value, HAText* caller)
|
||||
lastCommandCallbackCall.caller = caller;
|
||||
}
|
||||
|
||||
void onCommandPublishAttempt(const char* value, HAText* caller)
|
||||
void onCommandDeferredPublish(const char* value, HAText* caller)
|
||||
{
|
||||
TEST_ASSERT_FALSE(caller->setState(value));
|
||||
TEST_ASSERT_TRUE(caller->setState(value));
|
||||
}
|
||||
|
||||
void test_TextTest_invalid_unique_id(void) {
|
||||
@@ -328,17 +328,19 @@ void test_TextTest_command_callback(void) {
|
||||
assertCommandCallbackCalled("hello", &text)
|
||||
}
|
||||
|
||||
void test_TextTest_callback_publish_attempt_is_rejected(void) {
|
||||
void test_TextTest_callback_publish_is_deferred_until_after_dispatch(void) {
|
||||
prepareTest
|
||||
|
||||
mock->connectDummy();
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
HAText text(testUniqueId);
|
||||
text.onCommand(onCommandPublishAttempt);
|
||||
text.onCommand(onCommandDeferredPublish);
|
||||
|
||||
mock->fakeMessage(AHATOFSTR(CommandTopic), F("hello"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, mock->getPublishCallsFromCallbackNb());
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
AHA_ASSERT_MQTT_MESSAGE(mock, 0, AHATOFSTR(StateTopic), "hello", true);
|
||||
}
|
||||
|
||||
void test_TextTest_different_text_command(void) {
|
||||
|
||||
@@ -13,7 +13,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_NumberTest_command_number_unsigned),
|
||||
TEST_ENTRY(test_NumberTest_command_number_zero),
|
||||
TEST_ENTRY(test_NumberTest_command_subscription),
|
||||
TEST_ENTRY(test_NumberTest_callback_publish_attempt_is_rejected),
|
||||
TEST_ENTRY(test_NumberTest_callback_publish_is_deferred_until_after_dispatch),
|
||||
TEST_ENTRY(test_NumberTest_current_state_setter_getter_float),
|
||||
TEST_ENTRY(test_NumberTest_current_state_setter_getter_int16),
|
||||
TEST_ENTRY(test_NumberTest_current_state_setter_getter_int32),
|
||||
@@ -227,7 +227,7 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_SelectTest_publish_state_only),
|
||||
TEST_ENTRY(test_SelectTest_retain_setter),
|
||||
TEST_ENTRY(test_SelectTest_single_option),
|
||||
TEST_ENTRY(test_SelectTest_callback_publish_attempt_is_rejected),
|
||||
TEST_ENTRY(test_SelectTest_callback_publish_is_deferred_until_after_dispatch),
|
||||
};
|
||||
|
||||
static const size_t TEST_COUNT = sizeof(tests) / sizeof(tests[0]);
|
||||
|
||||
@@ -23,7 +23,7 @@ extern void test_NumberTest_command_number_signed(void);
|
||||
extern void test_NumberTest_command_number_unsigned(void);
|
||||
extern void test_NumberTest_command_number_zero(void);
|
||||
extern void test_NumberTest_command_subscription(void);
|
||||
extern void test_NumberTest_callback_publish_attempt_is_rejected(void);
|
||||
extern void test_NumberTest_callback_publish_is_deferred_until_after_dispatch(void);
|
||||
extern void test_NumberTest_current_state_setter_getter_float(void);
|
||||
extern void test_NumberTest_current_state_setter_getter_int16(void);
|
||||
extern void test_NumberTest_current_state_setter_getter_int32(void);
|
||||
@@ -237,6 +237,6 @@ extern void test_SelectTest_publish_state_none(void);
|
||||
extern void test_SelectTest_publish_state_only(void);
|
||||
extern void test_SelectTest_retain_setter(void);
|
||||
extern void test_SelectTest_single_option(void);
|
||||
extern void test_SelectTest_callback_publish_attempt_is_rejected(void);
|
||||
extern void test_SelectTest_callback_publish_is_deferred_until_after_dispatch(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,9 +42,9 @@ void onCommandReceived(HANumeric number, HANumber* caller)
|
||||
lastCommandCallbackCall.caller = caller;
|
||||
}
|
||||
|
||||
void onCommandPublishAttempt(HANumeric value, HANumber* caller)
|
||||
void onCommandDeferredPublish(HANumeric value, HANumber* caller)
|
||||
{
|
||||
TEST_ASSERT_FALSE(caller->setState(value));
|
||||
TEST_ASSERT_TRUE(caller->setState(value));
|
||||
}
|
||||
|
||||
void test_NumberTest_invalid_unique_id(void) {
|
||||
@@ -1015,17 +1015,19 @@ void test_NumberTest_command_number_float_p3(void) {
|
||||
assertCommandCallbackCalled(HANumeric(-1.234f, 3), &number)
|
||||
}
|
||||
|
||||
void test_NumberTest_callback_publish_attempt_is_rejected(void) {
|
||||
void test_NumberTest_callback_publish_is_deferred_until_after_dispatch(void) {
|
||||
prepareTest
|
||||
|
||||
mock->connectDummy();
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
HANumber number(testUniqueId);
|
||||
number.onCommand(onCommandPublishAttempt);
|
||||
number.onCommand(onCommandDeferredPublish);
|
||||
|
||||
mock->fakeMessage(AHATOFSTR(CommandTopic), F("1234"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, mock->getPublishCallsFromCallbackNb());
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
AHA_ASSERT_MQTT_MESSAGE(mock, 0, AHATOFSTR(StateTopic), "1234", true);
|
||||
}
|
||||
|
||||
void test_NumberTest_command_number_invalid(void) {
|
||||
|
||||
@@ -41,9 +41,9 @@ void onCommandReceived(int8_t index, HASelect* caller)
|
||||
lastCommandCallbackCall.caller = caller;
|
||||
}
|
||||
|
||||
void onCommandPublishAttempt(int8_t index, HASelect* caller)
|
||||
void onCommandDeferredPublish(int8_t index, HASelect* caller)
|
||||
{
|
||||
TEST_ASSERT_FALSE(caller->setState(index));
|
||||
TEST_ASSERT_TRUE(caller->setState(index));
|
||||
}
|
||||
|
||||
void test_SelectTest_invalid_unique_id(void) {
|
||||
@@ -482,18 +482,20 @@ void test_SelectTest_command_option_non_existing(void) {
|
||||
assertCommandCallbackNotCalled()
|
||||
}
|
||||
|
||||
void test_SelectTest_callback_publish_attempt_is_rejected(void) {
|
||||
void test_SelectTest_callback_publish_is_deferred_until_after_dispatch(void) {
|
||||
prepareTest
|
||||
|
||||
mock->connectDummy();
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
HASelect select(testUniqueId);
|
||||
select.setOptions("Option A;B;C");
|
||||
select.onCommand(onCommandPublishAttempt);
|
||||
select.onCommand(onCommandDeferredPublish);
|
||||
|
||||
mock->fakeMessage(AHATOFSTR(CommandTopic), F("B"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, mock->getPublishCallsFromCallbackNb());
|
||||
TEST_ASSERT_EQUAL(0, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
AHA_ASSERT_MQTT_MESSAGE(mock, 0, AHATOFSTR(StateTopic), "B", true);
|
||||
}
|
||||
|
||||
void test_SelectTest_different_select_command(void) {
|
||||
|
||||
@@ -7,7 +7,13 @@ static TestCase tests[] = {
|
||||
TEST_ENTRY(test_MqttTest_reconnect_interval_default_value),
|
||||
TEST_ENTRY(test_MqttTest_reconnect_interval_setter),
|
||||
TEST_ENTRY(test_MqttTest_reconnect_interval_throttles_attempts),
|
||||
TEST_ENTRY(test_MqttTest_publish_attempt_from_message_callback_is_rejected),
|
||||
TEST_ENTRY(test_MqttTest_publish_from_message_callback_is_deferred_and_flushed),
|
||||
TEST_ENTRY(test_MqttTest_deferred_publish_order_is_preserved),
|
||||
TEST_ENTRY(test_MqttTest_processing_message_flag_only_wraps_inbound_dispatch),
|
||||
TEST_ENTRY(test_MqttTest_streaming_publish_from_message_callback_is_deferred_and_flushed),
|
||||
TEST_ENTRY(test_MqttTest_deferred_publish_is_kept_across_disconnect_and_retried_from_loop),
|
||||
TEST_ENTRY(test_MqttTest_failed_deferred_flush_keeps_queue_and_retries_in_order),
|
||||
TEST_ENTRY(test_MqttTest_mixed_deferred_publish_order_is_preserved),
|
||||
|
||||
TEST_ENTRY(test_DeviceTest_default_unique_id),
|
||||
TEST_ENTRY(test_DeviceTest_unique_id_constructor_char),
|
||||
|
||||
@@ -17,7 +17,13 @@ extern void test_MqttTest_maximum_number_of_device_types(void);
|
||||
extern void test_MqttTest_reconnect_interval_default_value(void);
|
||||
extern void test_MqttTest_reconnect_interval_setter(void);
|
||||
extern void test_MqttTest_reconnect_interval_throttles_attempts(void);
|
||||
extern void test_MqttTest_publish_attempt_from_message_callback_is_rejected(void);
|
||||
extern void test_MqttTest_publish_from_message_callback_is_deferred_and_flushed(void);
|
||||
extern void test_MqttTest_deferred_publish_order_is_preserved(void);
|
||||
extern void test_MqttTest_processing_message_flag_only_wraps_inbound_dispatch(void);
|
||||
extern void test_MqttTest_streaming_publish_from_message_callback_is_deferred_and_flushed(void);
|
||||
extern void test_MqttTest_deferred_publish_is_kept_across_disconnect_and_retried_from_loop(void);
|
||||
extern void test_MqttTest_failed_deferred_flush_keeps_queue_and_retries_in_order(void);
|
||||
extern void test_MqttTest_mixed_deferred_publish_order_is_preserved(void);
|
||||
|
||||
extern void test_DeviceTest_default_unique_id(void);
|
||||
extern void test_DeviceTest_unique_id_constructor_char(void);
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
static const char* testDeviceId = "testDevice";
|
||||
static const char* testUniqueId = "uniqueId";
|
||||
static HAMqtt* activeMqtt = nullptr;
|
||||
static PubSubClientMock* activeMock = nullptr;
|
||||
static bool messageCallbackCalled = false;
|
||||
static bool processingFlagSeenDuringCallback = false;
|
||||
|
||||
const char ComponentNameStr[] PROGMEM = {"componentName"};
|
||||
|
||||
@@ -22,7 +24,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
void onMessagePublishAttempt(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
void onMessageDeferredPublish(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
@@ -30,7 +32,78 @@ void onMessagePublishAttempt(const char* topic, const uint8_t* payload, uint16_t
|
||||
|
||||
messageCallbackCalled = true;
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_FALSE(activeMqtt->publish("testData/testDevice/echo", "1", false));
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/echo", "1", false));
|
||||
}
|
||||
|
||||
void onMessageQueueOrderedPublishes(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/a", "1", false));
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/b", "2", false));
|
||||
}
|
||||
|
||||
void onMessageInspectProcessingState(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
processingFlagSeenDuringCallback = activeMqtt->isProcessingMessage();
|
||||
}
|
||||
|
||||
void onMessageDeferredStreamingPublish(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_TRUE(activeMqtt->beginPublish("testData/testDevice/stream", 2, false));
|
||||
activeMqtt->writePayload("O", 1);
|
||||
activeMqtt->writePayload("K", 1);
|
||||
TEST_ASSERT_TRUE(activeMqtt->endPublish());
|
||||
}
|
||||
|
||||
void onMessageDeferredPublishThenDisconnect(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_NOT_NULL(activeMock);
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/retry", "1", false));
|
||||
activeMock->disconnect();
|
||||
}
|
||||
|
||||
void onMessageDeferredPublishesForFailedFlush(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/a", "1", false));
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/b", "2", false));
|
||||
}
|
||||
|
||||
void onMessageMixedDeferredPublishesPreserveOrder(const char* topic, const uint8_t* payload, uint16_t length)
|
||||
{
|
||||
(void)topic;
|
||||
(void)payload;
|
||||
(void)length;
|
||||
|
||||
TEST_ASSERT_NOT_NULL(activeMqtt);
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/a", "1", false));
|
||||
TEST_ASSERT_TRUE(activeMqtt->beginPublish("testData/testDevice/b", 1, false));
|
||||
activeMqtt->writePayload("2", 1);
|
||||
TEST_ASSERT_TRUE(activeMqtt->endPublish());
|
||||
TEST_ASSERT_TRUE(activeMqtt->publish("testData/testDevice/c", "3", false));
|
||||
}
|
||||
|
||||
void test_MqttTest_maximum_number_of_device_types(void)
|
||||
@@ -84,7 +157,7 @@ void test_MqttTest_reconnect_interval_throttles_attempts(void)
|
||||
TEST_ASSERT_EQUAL_UINT16(2, mock->getConnectCallsNb());
|
||||
}
|
||||
|
||||
void test_MqttTest_publish_attempt_from_message_callback_is_rejected(void)
|
||||
void test_MqttTest_publish_from_message_callback_is_deferred_and_flushed(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
@@ -95,14 +168,186 @@ void test_MqttTest_publish_attempt_from_message_callback_is_rejected(void)
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
messageCallbackCalled = false;
|
||||
mock->resetPublishCallsFromCallbackNb();
|
||||
mqtt.onMessage(onMessagePublishAttempt);
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageDeferredPublish);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_TRUE(messageCallbackCalled);
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mock->getPublishCallsFromCallbackNb());
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/echo", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("1", mock->getFlushedMessages()[0]->buffer);
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_deferred_publish_order_is_preserved(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageQueueOrderedPublishes);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "x");
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT16(2, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(2, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/a", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("1", mock->getFlushedMessages()[0]->buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/b", mock->getFlushedMessages()[1]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("2", mock->getFlushedMessages()[1]->buffer);
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_processing_message_flag_only_wraps_inbound_dispatch(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
processingFlagSeenDuringCallback = false;
|
||||
TEST_ASSERT_FALSE(mqtt.isProcessingMessage());
|
||||
mqtt.onMessage(onMessageInspectProcessingState);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_TRUE(processingFlagSeenDuringCallback);
|
||||
TEST_ASSERT_FALSE(mqtt.isProcessingMessage());
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_streaming_publish_from_message_callback_is_deferred_and_flushed(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageDeferredStreamingPublish);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_FALSE(mqtt.hasDeferredFlushFailureForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/stream", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("OK", mock->getFlushedMessages()[0]->buffer);
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_deferred_publish_is_kept_across_disconnect_and_retried_from_loop(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
activeMock = mock;
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageDeferredPublishThenDisconnect);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT16(1, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_TRUE(mqtt.hasDeferredFlushFailureForTest());
|
||||
TEST_ASSERT_TRUE(mqtt.didDeferredFlushFailDueToDisconnectForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mock->getFlushedMessagesNb());
|
||||
|
||||
mock->connectDummy();
|
||||
mqtt.loop();
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_FALSE(mqtt.hasDeferredFlushFailureForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(1, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/retry", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("1", mock->getFlushedMessages()[0]->buffer);
|
||||
|
||||
activeMock = nullptr;
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_failed_deferred_flush_keeps_queue_and_retries_in_order(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageDeferredPublishesForFailedFlush);
|
||||
mock->failNextEndPublish();
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT16(2, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(2, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_TRUE(mqtt.hasDeferredFlushFailureForTest());
|
||||
TEST_ASSERT_TRUE(mqtt.didDeferredFlushFailAtEndPublishForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mock->getFlushedMessagesNb());
|
||||
|
||||
mqtt.loop();
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_FALSE(mqtt.hasDeferredFlushFailureForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(2, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/a", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("1", mock->getFlushedMessages()[0]->buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/b", mock->getFlushedMessages()[1]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("2", mock->getFlushedMessages()[1]->buffer);
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
void test_MqttTest_mixed_deferred_publish_order_is_preserved(void)
|
||||
{
|
||||
PubSubClientMock* mock = new PubSubClientMock();
|
||||
HADevice device(testDeviceId);
|
||||
HAMqtt mqtt(mock, device);
|
||||
mqtt.setDataPrefix("testData");
|
||||
mqtt.begin("testHost", "testUser", "testPass");
|
||||
mock->connectDummy();
|
||||
|
||||
activeMqtt = &mqtt;
|
||||
mqtt.resetDeferredPublishTestCounters();
|
||||
mqtt.onMessage(onMessageMixedDeferredPublishesPreserveOrder);
|
||||
|
||||
mock->fakeMessage("testData/testDevice/input", "1");
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT16(3, mqtt.getDeferredPublishEnqueueCountForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(0, mqtt.getPendingDeferredPublishesForTest());
|
||||
TEST_ASSERT_EQUAL_UINT8(3, mock->getFlushedMessagesNb());
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/a", mock->getFlushedMessages()[0]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("1", mock->getFlushedMessages()[0]->buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/b", mock->getFlushedMessages()[1]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("2", mock->getFlushedMessages()[1]->buffer);
|
||||
TEST_ASSERT_EQUAL_STRING("testData/testDevice/c", mock->getFlushedMessages()[2]->topic);
|
||||
TEST_ASSERT_EQUAL_STRING("3", mock->getFlushedMessages()[2]->buffer);
|
||||
|
||||
activeMqtt = nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user