compile with esp mqtt lib

This commit is contained in:
technyon
2023-01-27 19:29:13 +01:00
parent 10650c1132
commit c9dbbb5dc1
113 changed files with 9740 additions and 2997 deletions

View File

@@ -0,0 +1,313 @@
#include <unity.h>
#include <thread>
#include <iostream>
#include <espMqttClient.h> // espMqttClient for Linux also defines millis()
void setUp() {}
void tearDown() {}
espMqttClient mqttClient;
std::atomic_bool exitProgram(false);
std::thread t;
const IPAddress broker(127,0,0,1);
//const char* broker = "localhost";
const uint16_t broker_port = 1883;
/*
- setup the client with basic settings
- connect to the broker
- successfully connect
*/
void test_connect() {
std::atomic<bool> onConnectCalledTest(false);
bool sessionPresentTest = true;
mqttClient.setServer(broker, broker_port)
.setCleanSession(true)
.setKeepAlive(5)
.onConnect([&](bool sessionPresent) mutable {
sessionPresentTest = sessionPresent;
onConnectCalledTest = true;
});
mqttClient.connect();
uint32_t start = millis();
while (millis() - start < 2000) {
if (onConnectCalledTest) {
break;
}
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_TRUE(onConnectCalledTest);
TEST_ASSERT_FALSE(sessionPresentTest);
}
/*
- keepalive is set at 5 seconds in previous test
- client should stay connected during 2x keepalive period
*/
void test_ping() {
bool pingTest = true;
uint32_t start = millis();
while (millis() - start < 11000) {
if (mqttClient.disconnected()) {
pingTest = false;
break;
}
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_TRUE(pingTest);
}
/*
- client subscribes to topic
- ack is received from broker
*/
void test_subscribe() {
std::atomic<bool> subscribeTest(false);
mqttClient.onSubscribe([&](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) mutable {
(void) packetId;
if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS0) {
subscribeTest = true;
}
});
mqttClient.subscribe("test/test", 0);
uint32_t start = millis();
while (millis() - start < 2000) {
if (subscribeTest) {
break;
}
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_TRUE(subscribeTest);
}
/*
- client publishes using all three qos levels
- all publish get packetID returned > 0 (equal to 1 for qos 0)
- 2 pubacks are received
*/
void test_publish() {
std::atomic<int> publishSendTest(0);
mqttClient.onPublish([&](uint16_t packetId) mutable {
(void) packetId;
publishSendTest++;
});
std::atomic<int> publishReceiveTest(0);
mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable {
(void) properties;
(void) topic;
(void) payload;
(void) len;
(void) index;
(void) total;
publishReceiveTest++;
});
uint16_t sendQos0Test = mqttClient.publish("test/test", 0, false, "test0");
uint16_t sendQos1Test = mqttClient.publish("test/test", 1, false, "test1");
uint16_t sendQos2Test = mqttClient.publish("test/test", 2, false, "test2");
uint32_t start = millis();
while (millis() - start < 6000) {
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_EQUAL_UINT16(1, sendQos0Test);
TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos1Test);
TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test);
TEST_ASSERT_EQUAL_INT(2, publishSendTest);
TEST_ASSERT_EQUAL_INT(3, publishReceiveTest);
}
void test_publish_empty() {
std::atomic<int> publishSendEmptyTest(0);
mqttClient.onPublish([&](uint16_t packetId) mutable {
(void) packetId;
publishSendEmptyTest++;
});
std::atomic<int> publishReceiveEmptyTest(0);
mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable {
(void) properties;
(void) topic;
(void) payload;
(void) len;
(void) index;
(void) total;
publishReceiveEmptyTest++;
});
uint16_t sendQos0Test = mqttClient.publish("test/test", 0, false, nullptr, 0);
uint16_t sendQos1Test = mqttClient.publish("test/test", 1, false, nullptr, 0);
uint16_t sendQos2Test = mqttClient.publish("test/test", 2, false, nullptr, 0);
uint32_t start = millis();
while (millis() - start < 6000) {
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_EQUAL_UINT16(1, sendQos0Test);
TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos1Test);
TEST_ASSERT_GREATER_THAN_UINT16(0, sendQos2Test);
TEST_ASSERT_EQUAL_INT(2, publishSendEmptyTest);
TEST_ASSERT_EQUAL_INT(3, publishReceiveEmptyTest);
}
/*
- subscribe to test/test, qos 1
- send to test/test, qos 1
- check if message is received at least once.
*/
void test_receive1() {
std::atomic<int> publishReceive1Test(0);
mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable {
(void) properties;
(void) topic;
(void) payload;
(void) len;
(void) index;
(void) total;
publishReceive1Test++;
});
mqttClient.onSubscribe([&](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) mutable {
(void) packetId;
if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS1) {
mqttClient.publish("test/test", 1, false, "");
}
});
mqttClient.subscribe("test/test", 1);
uint32_t start = millis();
while (millis() - start < 6000) {
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_GREATER_THAN_INT(0, publishReceive1Test);
}
/*
- subscribe to test/test, qos 2
- send to test/test, qos 2
- check if message is received exactly once.
*/
void test_receive2() {
std::atomic<int> publishReceive2Test(0);
mqttClient.onMessage([&](const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) mutable {
(void) properties;
(void) topic;
(void) payload;
(void) len;
(void) index;
(void) total;
publishReceive2Test++;
});
mqttClient.onSubscribe([&](uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* returncodes, size_t len) mutable {
(void) packetId;
if (len == 1 && returncodes[0] == espMqttClientTypes::SubscribeReturncode::QOS2) {
mqttClient.publish("test/test", 2, false, "");
}
});
mqttClient.subscribe("test/test", 2);
uint32_t start = millis();
while (millis() - start < 6000) {
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_EQUAL_INT(1, publishReceive2Test);
}
/*
- client unsibscribes from topic
*/
void test_unsubscribe() {
std::atomic<bool> unsubscribeTest(false);
mqttClient.onUnsubscribe([&](uint16_t packetId) mutable {
(void) packetId;
unsubscribeTest = true;
});
mqttClient.unsubscribe("test/test");
uint32_t start = millis();
while (millis() - start < 2000) {
if (unsubscribeTest) {
break;
}
std::this_thread::yield();
}
TEST_ASSERT_TRUE(mqttClient.connected());
TEST_ASSERT_TRUE(unsubscribeTest);
}
/*
- client disconnects cleanly
*/
void test_disconnect() {
std::atomic<bool> onDisconnectCalled(false);
espMqttClientTypes::DisconnectReason reasonTest = espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED;
mqttClient.onDisconnect([&](espMqttClientTypes::DisconnectReason reason) mutable {
reasonTest = reason;
onDisconnectCalled = true;
});
mqttClient.disconnect();
uint32_t start = millis();
while (millis() - start < 2000) {
if (onDisconnectCalled) {
break;
}
std::this_thread::yield();
}
TEST_ASSERT_TRUE(onDisconnectCalled);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::DisconnectReason::USER_OK, reasonTest);
TEST_ASSERT_TRUE(mqttClient.disconnected());
}
int main() {
UNITY_BEGIN();
t = std::thread([] {
while (1) {
mqttClient.loop();
if (exitProgram) break;
}
});
RUN_TEST(test_connect);
RUN_TEST(test_ping);
RUN_TEST(test_subscribe);
RUN_TEST(test_publish);
RUN_TEST(test_publish_empty);
RUN_TEST(test_receive1);
RUN_TEST(test_receive2);
RUN_TEST(test_unsubscribe);
RUN_TEST(test_disconnect);
exitProgram = true;
t.join();
return UNITY_END();
}

View File

@@ -0,0 +1,171 @@
#include <unity.h>
#include <Outbox.h>
using espMqttClientInternals::Outbox;
void setUp() {}
void tearDown() {}
void test_outbox_create() {
Outbox<uint32_t> outbox;
Outbox<uint32_t>::Iterator it = outbox.front();
TEST_ASSERT_NULL(outbox.getCurrent());
TEST_ASSERT_NULL(it.get());
TEST_ASSERT_TRUE(outbox.empty());
}
void test_outbox_emplace() {
Outbox<uint32_t> outbox;
outbox.emplace(1);
// 1, current points to 1
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(1, *(outbox.getCurrent()));
TEST_ASSERT_FALSE(outbox.empty());
outbox.next();
// 1, current points to nullptr
TEST_ASSERT_NULL(outbox.getCurrent());
outbox.emplace(2);
// 1 2, current points to 2
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(2, *(outbox.getCurrent()));
outbox.emplace(3);
// 1 2 3, current points to 2
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(2, *(outbox.getCurrent()));
}
void test_outbox_emplaceFront() {
Outbox<uint32_t> outbox;
outbox.emplaceFront(1);
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(1, *(outbox.getCurrent()));
outbox.emplaceFront(2);
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(2, *(outbox.getCurrent()));
}
void test_outbox_remove1() {
Outbox<uint32_t> outbox;
Outbox<uint32_t>::Iterator it;
outbox.emplace(1);
outbox.emplace(2);
outbox.emplace(3);
outbox.emplace(4);
outbox.next();
outbox.next();
it = outbox.front();
++it;
++it;
++it;
++it;
outbox.remove(it);
// 1 2 3 4, it points to nullptr, current points to 3
TEST_ASSERT_NULL(it.get());
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(3, *(outbox.getCurrent()));
it = outbox.front();
++it;
++it;
++it;
outbox.remove(it);
// 1 2 3, it points to nullptr, current points to 3
TEST_ASSERT_NULL(it.get());
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(3, *(outbox.getCurrent()));
it = outbox.front();
outbox.remove(it);
// 2 3, it points to 2, current points to 3
TEST_ASSERT_NOT_NULL(it.get());
TEST_ASSERT_EQUAL_UINT32(2, *(it.get()));
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(3, *(outbox.getCurrent()));
it = outbox.front();
outbox.remove(it);
// 3, it points to 3, current points to 3
TEST_ASSERT_NOT_NULL(it.get());
TEST_ASSERT_EQUAL_UINT32(3, *(it.get()));
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(3, *(outbox.getCurrent()));
it = outbox.front();
outbox.remove(it);
TEST_ASSERT_NULL(it.get());
TEST_ASSERT_NULL(outbox.getCurrent());
}
void test_outbox_remove2() {
Outbox<uint32_t> outbox;
Outbox<uint32_t>::Iterator it;
outbox.emplace(1);
outbox.emplace(2);
outbox.next();
outbox.next();
it = outbox.front();
// 1 2, current points to nullptr
TEST_ASSERT_NULL(outbox.getCurrent());
TEST_ASSERT_NOT_NULL(it.get());
TEST_ASSERT_EQUAL_UINT32(1, *(it.get()));
++it;
// 1 2, current points to nullptr
TEST_ASSERT_NOT_NULL(it.get());
TEST_ASSERT_EQUAL_UINT32(2, *(it.get()));
outbox.remove(it);
// 1, current points to nullptr
TEST_ASSERT_NULL(outbox.getCurrent());
TEST_ASSERT_NULL(it.get());
it = outbox.front();
TEST_ASSERT_NOT_NULL(it.get());
TEST_ASSERT_EQUAL_UINT32(1, *(it.get()));
outbox.remove(it);
TEST_ASSERT_NULL(it.get());
TEST_ASSERT_TRUE(outbox.empty());
}
void test_outbox_removeCurrent() {
Outbox<uint32_t> outbox;
outbox.emplace(1);
outbox.emplace(2);
outbox.emplace(3);
outbox.emplace(4);
outbox.removeCurrent();
// 2 3 4, current points to 2
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(2, *(outbox.getCurrent()));
outbox.next();
outbox.removeCurrent();
// 2 4, current points to 4
TEST_ASSERT_NOT_NULL(outbox.getCurrent());
TEST_ASSERT_EQUAL_UINT32(4, *(outbox.getCurrent()));
outbox.removeCurrent();
// 4, current points to nullptr
TEST_ASSERT_NULL(outbox.getCurrent());
// outbox will go out of scope and destructor will be called
// Valgrind should not detect a leak here
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_outbox_create);
RUN_TEST(test_outbox_emplace);
RUN_TEST(test_outbox_emplaceFront);
RUN_TEST(test_outbox_remove1);
RUN_TEST(test_outbox_remove2);
RUN_TEST(test_outbox_removeCurrent);
return UNITY_END();
}

View File

@@ -0,0 +1,714 @@
#include <unity.h>
#include <Packets/Packet.h>
using espMqttClientInternals::Packet;
using espMqttClientInternals::PacketType;
void setUp() {}
void tearDown() {}
void test_encodeConnect0() {
const uint8_t check[] = {
0b00010000, // header
0x0F, // remaining length
0x00,0x04,'M','Q','T','T', // protocol
0b00000100, // protocol level
0b00000010, // connect flags
0x00,0x10, // keepalive (16)
0x00,0x03,'c','l','i' // client id
};
const uint32_t length = 17;
bool cleanSession = true;
const char* username = nullptr;
const char* password = nullptr;
const char* willTopic = nullptr;
bool willRemain = false;
uint8_t willQoS = 0;
const uint8_t* willPayload = nullptr;
uint16_t willPayloadLength = 0;
uint16_t keepalive = 16;
const char* clientId = "cli";
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
cleanSession,
username,
password,
willTopic,
willRemain,
willQoS,
willPayload,
willPayloadLength,
keepalive,
clientId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.CONNECT, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
}
void test_encodeConnect1() {
const uint8_t check[] = {
0b00010000, // header
0x20, // remaining length
0x00,0x04,'M','Q','T','T', // protocol
0b00000100, // protocol level
0b11101110, // connect flags
0x00,0x10, // keepalive (16)
0x00,0x03,'c','l','i', // client id
0x00,0x03,'t','o','p', // will topic
0x00,0x02,'p','l', // will payload
0x00,0x02,'u','n', // username
0x00,0x02,'p','a' // password
};
const uint32_t length = 34;
bool cleanSession = true;
const char* username = "un";
const char* password = "pa";
const char* willTopic = "top";
bool willRemain = true;
uint8_t willQoS = 1;
const uint8_t willPayload[] = {'p', 'l'};
uint16_t willPayloadLength = 2;
uint16_t keepalive = 16;
const char* clientId = "cli";
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
cleanSession,
username,
password,
willTopic,
willRemain,
willQoS,
willPayload,
willPayloadLength,
keepalive,
clientId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.CONNECT, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
}
void test_encodeConnect2() {
const uint8_t check[] = {
0b00010000, // header
0x20, // remaining length
0x00,0x04,'M','Q','T','T', // protocol
0b00000100, // protocol level
0b11110110, // connect flags
0x00,0x10, // keepalive (16)
0x00,0x03,'c','l','i', // client id
0x00,0x03,'t','o','p', // will topic
0x00,0x02,'p','l', // will payload
0x00,0x02,'u','n', // username
0x00,0x02,'p','a' // password
};
const uint32_t length = 34;
bool cleanSession = true;
const char* username = "un";
const char* password = "pa";
const char* willTopic = "top";
bool willRemain = true;
uint8_t willQoS = 2;
const uint8_t willPayload[] = {'p', 'l', '\0'};
uint16_t willPayloadLength = 0;
uint16_t keepalive = 16;
const char* clientId = "cli";
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
cleanSession,
username,
password,
willTopic,
willRemain,
willQoS,
willPayload,
willPayloadLength,
keepalive,
clientId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.CONNECT, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
}
void test_encodeConnectFail0() {
bool cleanSession = true;
const char* username = nullptr;
const char* password = nullptr;
const char* willTopic = nullptr;
bool willRemain = false;
uint8_t willQoS = 0;
const uint8_t* willPayload = nullptr;
uint16_t willPayloadLength = 0;
uint16_t keepalive = 16;
const char* clientId = "";
espMqttClientTypes::Error error = espMqttClientTypes::Error::SUCCESS;
Packet packet(error,
cleanSession,
username,
password,
willTopic,
willRemain,
willQoS,
willPayload,
willPayloadLength,
keepalive,
clientId);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::MALFORMED_PARAMETER, error);
}
void test_encodePublish0() {
const uint8_t check[] = {
0b00110000, // header, dup, qos, retain
0x09,
0x00,0x03,'t','o','p', // topic
0x01,0x02,0x03,0x04 // payload
};
const uint32_t length = 11;
const char* topic = "top";
uint8_t qos = 0;
bool retain = false;
const uint8_t payload[] = {0x01, 0x02, 0x03, 0x04};
uint16_t payloadLength = 4;
uint16_t packetId = 22; // any value except 0 for testing
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
packetId,
topic,
payload,
payloadLength,
qos,
retain);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBLISH, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
packet.setDup();
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
}
void test_encodePublish1() {
const uint8_t check[] = {
0b00110011, // header, dup, qos, retain
0x0B,
0x00,0x03,'t','o','p', // topic
0x00,0x16, // packet Id
0x01,0x02,0x03,0x04 // payload
};
const uint32_t length = 13;
const char* topic = "top";
uint8_t qos = 1;
bool retain = true;
const uint8_t payload[] = {0x01, 0x02, 0x03, 0x04};
uint16_t payloadLength = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
packetId,
topic,
payload,
payloadLength,
qos,
retain);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBLISH, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
const uint8_t checkDup[] = {
0b00111011, // header, dup, qos, retain
0x0B,
0x00,0x03,'t','o','p', // topic
0x00,0x16, // packet Id
0x01,0x02,0x03,0x04 // payload
};
packet.setDup();
TEST_ASSERT_EQUAL_UINT8_ARRAY(checkDup, packet.data(0), length);
}
void test_encodePublish2() {
const uint8_t check[] = {
0b00110101, // header, dup, qos, retain
0x0B,
0x00,0x03,'t','o','p', // topic
0x00,0x16, // packet Id
0x01,0x02,0x03,0x04 // payload
};
const uint32_t length = 13;
const char* topic = "top";
uint8_t qos = 2;
bool retain = true;
const uint8_t payload[] = {0x01, 0x02, 0x03, 0x04};
uint16_t payloadLength = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
packetId,
topic,
payload,
payloadLength,
qos,
retain);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBLISH, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
const uint8_t checkDup[] = {
0b00111101, // header, dup, qos, retain
0x0B,
0x00,0x03,'t','o','p', // topic
0x00,0x16, // packet Id
0x01,0x02,0x03,0x04 // payload
};
packet.setDup();
TEST_ASSERT_EQUAL_UINT8_ARRAY(checkDup, packet.data(0), length);
}
void test_encodePubAck() {
const uint8_t check[] = {
0b01000000, // header
0x02,
0x00,0x16, // packet Id
};
const uint32_t length = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.PUBACK, packetId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBACK, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodePubRec() {
const uint8_t check[] = {
0b01010000, // header
0x02,
0x00,0x16, // packet Id
};
const uint32_t length = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.PUBREC, packetId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBREC, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodePubRel() {
const uint8_t check[] = {
0b01100010, // header
0x02,
0x00,0x16, // packet Id
};
const uint32_t length = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.PUBREL, packetId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBREL, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodePubComp() {
const uint8_t check[] = {
0b01110000, // header
0x02, // remaining length
0x00,0x16, // packet Id
};
const uint32_t length = 4;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.PUBCOMP, packetId);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PUBCOMP, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeSubscribe() {
const uint8_t check[] = {
0b10000010, // header
0x08, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic
0x02 // qos
};
const uint32_t length = 10;
const char* topic = "a/b";
uint8_t qos = 2;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic, qos);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.SUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeMultiSubscribe2() {
const uint8_t check[] = {
0b10000010, // header
0x0E, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic1
0x01, // qos1
0x00, 0x03, 'c', '/', 'd', // topic2
0x02 // qos2
};
const uint32_t length = 16;
const char* topic1 = "a/b";
const char* topic2 = "c/d";
uint8_t qos1 = 1;
uint8_t qos2 = 2;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic1, qos1, topic2, qos2);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.SUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeMultiSubscribe3() {
const uint8_t check[] = {
0b10000010, // header
0x14, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic1
0x01, // qos1
0x00, 0x03, 'c', '/', 'd', // topic2
0x02, // qos2
0x00, 0x03, 'e', '/', 'f', // topic3
0x00 // qos3
};
const uint32_t length = 22;
const char* topic1 = "a/b";
const char* topic2 = "c/d";
const char* topic3 = "e/f";
uint8_t qos1 = 1;
uint8_t qos2 = 2;
uint8_t qos3 = 0;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic1, qos1, topic2, qos2, topic3, qos3);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.SUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeUnsubscribe() {
const uint8_t check[] = {
0b10100010, // header
0x07, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic
};
const uint32_t length = 9;
const char* topic = "a/b";
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.UNSUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeMultiUnsubscribe2() {
const uint8_t check[] = {
0b10100010, // header
0x0C, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic1
0x00, 0x03, 'c', '/', 'd' // topic2
};
const uint32_t length = 14;
const char* topic1 = "a/b";
const char* topic2 = "c/d";
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic1, topic2);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.UNSUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodeMultiUnsubscribe3() {
const uint8_t check[] = {
0b10100010, // header
0x11, // remaining length
0x00,0x16, // packet Id
0x00, 0x03, 'a', '/', 'b', // topic1
0x00, 0x03, 'c', '/', 'd', // topic2
0x00, 0x03, 'e', '/', 'f', // topic3
};
const uint32_t length = 19;
const char* topic1 = "a/b";
const char* topic2 = "c/d";
const char* topic3 = "e/f";
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, packetId, topic1, topic2, topic3);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.UNSUBSCRIBE, packet.packetType());
TEST_ASSERT_FALSE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
}
void test_encodePingReq() {
const uint8_t check[] = {
0b11000000, // header
0x00
};
const uint32_t length = 2;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.PINGREQ);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.PINGREQ, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
}
void test_encodeDisconnect() {
const uint8_t check[] = {
0b11100000, // header
0x00
};
const uint32_t length = 2;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error, PacketType.DISCONNECT);
packet.setDup(); // no effect
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(length, packet.size());
TEST_ASSERT_EQUAL_UINT8(PacketType.DISCONNECT, packet.packetType());
TEST_ASSERT_TRUE(packet.removable());
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(0), length);
TEST_ASSERT_EQUAL_UINT16(0, packet.packetId());
}
size_t getData(uint8_t* dest, size_t len, size_t index) {
(void) index;
static uint8_t i = 1;
memset(dest, i, len);
++i;
return len;
}
void test_encodeChunkedPublish() {
const uint8_t check[] = {
0b00110011, // header, dup, qos, retain
0xCF, 0x01, // 7 + 200 = (0x4F * 1) & 0x40 + (0x01 * 128)
0x00,0x03,'t','o','p', // topic
0x00,0x16 // packet Id
};
uint8_t payloadChunk[EMC_TX_BUFFER_SIZE] = {};
memset(payloadChunk, 0x01, EMC_TX_BUFFER_SIZE);
const char* topic = "top";
uint8_t qos = 1;
bool retain = true;
size_t headerLength = 10;
size_t payloadLength = 200;
size_t size = headerLength + payloadLength;
uint16_t packetId = 22;
espMqttClientTypes::Error error = espMqttClientTypes::Error::MISC_ERROR;
Packet packet(error,
packetId,
topic,
getData,
payloadLength,
qos,
retain);
TEST_ASSERT_EQUAL_UINT8(espMqttClientTypes::Error::SUCCESS, error);
TEST_ASSERT_EQUAL_UINT32(size, packet.size());
TEST_ASSERT_EQUAL_UINT16(packetId, packet.packetId());
size_t available = 0;
size_t index = 0;
// call 'available' before 'data'
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(headerLength + EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, packet.data(index), headerLength);
// index == first payload byte
index = headerLength;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(payloadChunk, packet.data(index), available);
// index == first payload byte
index = headerLength + 4;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(EMC_TX_BUFFER_SIZE - 4, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(payloadChunk, packet.data(index), available);
// index == last payload byte in first chunk
index = headerLength + EMC_TX_BUFFER_SIZE - 1;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(1, available);
// index == first payloadbyte in second chunk
memset(payloadChunk, 0x02, EMC_TX_BUFFER_SIZE);
index = headerLength + EMC_TX_BUFFER_SIZE;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(payloadChunk, packet.data(index), available);
memset(payloadChunk, 0x03, EMC_TX_BUFFER_SIZE);
index = headerLength + EMC_TX_BUFFER_SIZE + EMC_TX_BUFFER_SIZE + 10;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(payloadChunk, packet.data(index), available);
const uint8_t checkDup[] = {
0b00111011, // header, dup, qos, retain
0xCF, 0x01, // 7 + 200 = (0x4F * 0) + (0x01 * 128)
0x00,0x03,'t','o','p', // topic
0x00,0x16, // packet Id
};
index = 0;
packet.setDup();
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(headerLength + EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(checkDup, packet.data(index), headerLength);
memset(payloadChunk, 0x04, EMC_TX_BUFFER_SIZE);
index = headerLength;
available = packet.available(index);
TEST_ASSERT_EQUAL_UINT32(EMC_TX_BUFFER_SIZE, available);
TEST_ASSERT_EQUAL_UINT8_ARRAY(payloadChunk, packet.data(index), available);
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_encodeConnect0);
RUN_TEST(test_encodeConnect1);
RUN_TEST(test_encodeConnect2);
RUN_TEST(test_encodeConnectFail0);
RUN_TEST(test_encodePublish0);
RUN_TEST(test_encodePublish1);
RUN_TEST(test_encodePublish2);
RUN_TEST(test_encodePubAck);
RUN_TEST(test_encodePubRec);
RUN_TEST(test_encodePubRel);
RUN_TEST(test_encodePubComp);
RUN_TEST(test_encodeSubscribe);
RUN_TEST(test_encodeMultiSubscribe2);
RUN_TEST(test_encodeMultiSubscribe3);
RUN_TEST(test_encodeUnsubscribe);
RUN_TEST(test_encodeMultiUnsubscribe2);
RUN_TEST(test_encodeMultiUnsubscribe3);
RUN_TEST(test_encodePingReq);
RUN_TEST(test_encodeDisconnect);
RUN_TEST(test_encodeChunkedPublish);
return UNITY_END();
}

View File

@@ -0,0 +1,355 @@
#include <unity.h>
#include <Packets/Parser.h>
using espMqttClientInternals::Parser;
using espMqttClientInternals::ParserResult;
using espMqttClientInternals::IncomingPacket;
void setUp() {}
void tearDown() {}
Parser parser;
void test_Connack() {
const uint8_t stream[] = {
0b00100000, // header
0b00000010, // flags
0b00000001, // session present
0b00000000 // reserved
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(4, bytesRead);
TEST_ASSERT_EQUAL_UINT8(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT8(1, parser.getPacket().variableHeader.fixed.connackVarHeader.sessionPresent);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().variableHeader.fixed.connackVarHeader.returnCode);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_Empty() {
const uint8_t stream[] = {
0x00
};
const size_t length = 0;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_UINT8(ParserResult::awaitData, result);
TEST_ASSERT_EQUAL_INT32(0, bytesRead);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_Header() {
const uint8_t stream[] = {
0x12,
0x13,
0x14
};
const size_t length = 3;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::protocolError, result);
TEST_ASSERT_EQUAL_UINT32(1, bytesRead);
}
void test_Publish() {
uint8_t stream[] = {
0b00110010, // header
0x0B, // remaining length
0x00, 0x03, 'a', '/', 'b', // topic
0x00, 0x0A, // packet id
0x01, 0x02 // payload
};
size_t length = 11;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBLISH, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_STRING("a/b", parser.getPacket().variableHeader.topic);
TEST_ASSERT_EQUAL_UINT16(10, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.index);
TEST_ASSERT_EQUAL_UINT32(2, parser.getPacket().payload.length);
TEST_ASSERT_EQUAL_UINT32(4, parser.getPacket().payload.total);
TEST_ASSERT_EQUAL_UINT8(1, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
stream[0] = 0x03;
stream[1] = 0x04;
length = 2;
bytesRead = 0;
result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_STRING("a/b", parser.getPacket().variableHeader.topic);
TEST_ASSERT_EQUAL_UINT16(10, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT32(2, parser.getPacket().payload.index);
TEST_ASSERT_EQUAL_UINT32(2, parser.getPacket().payload.length);
TEST_ASSERT_EQUAL_UINT32(4, parser.getPacket().payload.total);
TEST_ASSERT_EQUAL_UINT8(1, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_Publish_empty() {
uint8_t stream0[] = {
0b00110000, // header
0x05, // remaining length
0x00, 0x03, 'a', '/', 'b', // topic
};
size_t length0 = 7;
size_t bytesRead0 = 0;
ParserResult result0 = parser.parse(stream0, length0, &bytesRead0);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result0);
TEST_ASSERT_EQUAL_UINT32(length0, bytesRead0);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBLISH, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_STRING("a/b", parser.getPacket().variableHeader.topic);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.index);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.length);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.total);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
uint8_t stream1[] = {
0b00110000, // header
0x05, // remaining length
0x00, 0x03, 'a', '/', 'b', // topic
};
size_t length1 = 7;
size_t bytesRead1 = 0;
ParserResult result1 = parser.parse(stream1, length1, &bytesRead1);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result1);
TEST_ASSERT_EQUAL_UINT32(length1, bytesRead1);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBLISH, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_STRING("a/b", parser.getPacket().variableHeader.topic);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.index);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.length);
TEST_ASSERT_EQUAL_UINT32(0, parser.getPacket().payload.total);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_PubAck() {
const uint8_t stream[] = {
0b01000000,
0b00000010,
0x12,
0x34
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBACK, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT16(4660, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_PubRec() {
const uint8_t stream[] = {
0b01010000,
0b00000010,
0x56,
0x78
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_BITS(0xF0, espMqttClientInternals::PacketType.PUBREC, parser.getPacket().fixedHeader.packetType);
TEST_ASSERT_EQUAL_UINT16(22136, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_PubRel() {
const uint8_t stream[] = {
0b01100010,
0b00000010,
0x9A,
0xBC
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBREL, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT16(0x9ABC, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_PubComp() {
const uint8_t stream[] = {
0b01110000,
0b00000010,
0xDE,
0xF0
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBCOMP, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT16(0xDEF0, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_SubAck() {
const uint8_t stream[] = {
0b10010000,
0b00000100,
0x00,
0x0A,
0x02,
0x01
};
const size_t length = 6;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.SUBACK, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT16(10, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8_ARRAY(&stream[4], parser.getPacket().payload.data,2);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_UnsubAck() {
const uint8_t stream[] = {
0b10110000,
0b00000010,
0x00,
0x0A
};
const size_t length = 4;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.UNSUBACK, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT16(10, parser.getPacket().variableHeader.fixed.packetId);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_PingResp() {
const uint8_t stream[] = {
0b11010000,
0x00
};
const size_t length = 2;
size_t bytesRead = 0;
ParserResult result = parser.parse(stream, length, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT32(length, bytesRead);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PINGRESP, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
void test_longStream() {
const uint8_t stream[] = {
0x90, 0x03, 0x00, 0x01, 0x00, 0x31, 0x0F, 0x00, 0x09, 0x66, 0x6F, 0x6F, 0x2F, 0x62, 0x61, 0x72,
0x2F, 0x30, 0x74, 0x65, 0x73, 0x74, 0x90, 0x03, 0x00, 0x02, 0x01, 0x33, 0x11, 0x00, 0x09, 0x66,
0x6F, 0x6F, 0x2F, 0x62, 0x61, 0x72, 0x2F, 0x31, 0x00, 0x01, 0x74, 0x65, 0x73, 0x74, 0x90, 0x03,
0x00, 0x03, 0x02, 0x30, 0x0F, 0x00, 0x09, 0x66, 0x6F, 0x6F, 0x2F, 0x62, 0x61, 0x72, 0x2F, 0x30,
0x74, 0x65, 0x73, 0x74, 0x32, 0x11, 0x00, 0x09, 0x66, 0x6F, 0x6F, 0x2F, 0x62, 0x61, 0x72, 0x2F,
0x31, 0x00, 0x02, 0x74, 0x65, 0x73, 0x74, 0x40, 0x02, 0x00, 0x04, 0x50, 0x02, 0x00, 0x05
};
const size_t length = 94;
size_t bytesRead = 0;
ParserResult result = parser.parse(&stream[bytesRead], length - bytesRead, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.SUBACK, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT32(5, bytesRead);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
result = parser.parse(&stream[bytesRead], length - bytesRead, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.PUBLISH, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT32(5 + 17, bytesRead);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_TRUE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
result = parser.parse(&stream[bytesRead], length - bytesRead, &bytesRead);
TEST_ASSERT_EQUAL_INT32(ParserResult::packet, result);
TEST_ASSERT_EQUAL_UINT8(espMqttClientInternals::PacketType.SUBACK, parser.getPacket().fixedHeader.packetType & 0xF0);
TEST_ASSERT_EQUAL_UINT32(5 + 17 + 5, bytesRead);
TEST_ASSERT_EQUAL_UINT8(0, parser.getPacket().qos());
TEST_ASSERT_FALSE(parser.getPacket().retain());
TEST_ASSERT_FALSE(parser.getPacket().dup());
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_Connack);
RUN_TEST(test_Empty);
RUN_TEST(test_Header);
RUN_TEST(test_Publish);
RUN_TEST(test_Publish_empty);
RUN_TEST(test_PubAck);
RUN_TEST(test_PubRec);
RUN_TEST(test_PubRel);
RUN_TEST(test_PubComp);
RUN_TEST(test_SubAck);
RUN_TEST(test_UnsubAck);
RUN_TEST(test_PingResp);
RUN_TEST(test_longStream);
return UNITY_END();
}

View File

@@ -0,0 +1,63 @@
#include <iostream>
#include <unity.h>
#include <Packets/RemainingLength.h>
void setUp() {}
void tearDown() {}
// Examples takes from MQTT specification
uint8_t bytes1[] = {0x40};
uint8_t size1 = 1;
uint32_t length1 = 64;
uint8_t bytes2[] = {193, 2};
uint8_t size2 = 2;
uint32_t length2 = 321;
uint8_t bytes3[] = {0xff, 0xff, 0xff, 0x7f};
uint8_t size3 = 4;
uint32_t length3 = 268435455;
void test_remainingLengthDecode() {
TEST_ASSERT_EQUAL_INT32(length1, espMqttClientInternals::decodeRemainingLength(bytes1));
TEST_ASSERT_EQUAL_INT32(length2, espMqttClientInternals::decodeRemainingLength(bytes2));
uint8_t stream[] = {0x80, 0x80, 0x80, 0x01};
TEST_ASSERT_EQUAL_INT32(2097152 , espMqttClientInternals::decodeRemainingLength(stream));
TEST_ASSERT_EQUAL_INT32(length3, espMqttClientInternals::decodeRemainingLength(bytes3));
}
void test_remainingLengthEncode() {
uint8_t bytes[4];
TEST_ASSERT_EQUAL_UINT8(1, espMqttClientInternals::remainingLengthLength(0));
TEST_ASSERT_EQUAL_UINT8(size1, espMqttClientInternals::remainingLengthLength(length1));
TEST_ASSERT_EQUAL_UINT8(size1, espMqttClientInternals::encodeRemainingLength(length1, bytes));
TEST_ASSERT_EQUAL_UINT8_ARRAY(bytes1, bytes, size1);
TEST_ASSERT_EQUAL_UINT8(size2, espMqttClientInternals::remainingLengthLength(length2));
TEST_ASSERT_EQUAL_UINT8(size2, espMqttClientInternals::encodeRemainingLength(length2, bytes));
TEST_ASSERT_EQUAL_UINT8_ARRAY(bytes2, bytes, size2);
TEST_ASSERT_EQUAL_UINT8(size3, espMqttClientInternals::remainingLengthLength(length3));
TEST_ASSERT_EQUAL_UINT8(size3, espMqttClientInternals::encodeRemainingLength(length3, bytes));
TEST_ASSERT_EQUAL_UINT8_ARRAY(bytes3, bytes, size3);
}
void test_remainingLengthError() {
uint8_t bytes[] = {0xff, 0xff, 0xff, 0x80}; // high bit of last byte is 1
// this indicates a next byte is coming
// which is a violation of the spec
TEST_ASSERT_EQUAL_UINT8(0, espMqttClientInternals::remainingLengthLength(268435456));
TEST_ASSERT_EQUAL_INT32(-1, espMqttClientInternals::decodeRemainingLength(bytes));
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_remainingLengthDecode);
RUN_TEST(test_remainingLengthEncode);
RUN_TEST(test_remainingLengthError);
return UNITY_END();
}

View File

@@ -0,0 +1,64 @@
#include <iostream>
#include <unity.h>
#include <Packets/String.h>
void setUp() {}
void tearDown() {}
void test_encodeString() {
const char test[] = "abcd";
uint8_t buffer[6];
const uint8_t check[] = {0x00, 0x04, 'a', 'b', 'c', 'd'};
const uint32_t length = 6;
TEST_ASSERT_EQUAL_UINT32(length, espMqttClientInternals::encodeString(test, buffer));
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, buffer, length);
}
void test_emtpyString() {
const char test[] = "";
uint8_t buffer[2];
const uint8_t check[] = {0x00, 0x00};
const uint32_t length = 2;
TEST_ASSERT_EQUAL_UINT32(length, espMqttClientInternals::encodeString(test, buffer));
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, buffer, length);
}
void test_longString() {
const size_t maxSize = 65535;
char test[maxSize + 1];
test[maxSize] = '\0';
memset(test, 'a', maxSize);
uint8_t buffer[maxSize + 3];
uint8_t check[maxSize + 2];
check[0] = 0xFF;
check[1] = 0xFF;
memset(&check[2], 'a', maxSize);
const uint32_t length = 2 + maxSize;
TEST_ASSERT_EQUAL_UINT32(length, espMqttClientInternals::encodeString(test, buffer));
TEST_ASSERT_EQUAL_UINT8_ARRAY(check, buffer, length);
}
void test_tooLongString() {
const size_t maxSize = 65535;
char test[maxSize + 2];
test[maxSize + 1] = '\0';
memset(test, 'a', maxSize + 1);
uint8_t buffer[maxSize + 4]; // extra 4 bytes for headroom: test progam, don't test test
const uint32_t length = 0;
TEST_ASSERT_EQUAL_UINT32(length, espMqttClientInternals::encodeString(test, buffer));
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_encodeString);
RUN_TEST(test_emtpyString);
RUN_TEST(test_longString);
RUN_TEST(test_tooLongString);
return UNITY_END();
}