mirror of
https://github.com/alexandrebobkov/ESP-Nodes.git
synced 2025-10-27 18:41:52 +00:00
mqtt
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
|
||||
idf_component_register(SRCS test_mqtt_connection.c
|
||||
INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/include
|
||||
PRIV_REQUIRES unity esp_event esp_netif esp_eth)
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
/**
|
||||
* Connection test fixture setup, so we expect the broker is available
|
||||
* on network
|
||||
*/
|
||||
void connect_test_fixture_setup(void);
|
||||
|
||||
/**
|
||||
* Cleans up the connection
|
||||
*/
|
||||
void connect_test_fixture_teardown(void);
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "unity.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_eth.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
#if SOC_EMAC_SUPPORTED
|
||||
#define ETH_START_BIT BIT(0)
|
||||
#define ETH_STOP_BIT BIT(1)
|
||||
#define ETH_CONNECT_BIT BIT(2)
|
||||
#define ETH_GOT_IP_BIT BIT(3)
|
||||
#define ETH_STOP_TIMEOUT_MS (10000)
|
||||
#define ETH_GET_IP_TIMEOUT_MS (60000)
|
||||
|
||||
|
||||
static const char *TAG = "esp32_eth_test_fixture";
|
||||
static EventGroupHandle_t s_eth_event_group = NULL;
|
||||
static esp_netif_t *s_eth_netif = NULL;
|
||||
static esp_eth_mac_t *s_mac = NULL;
|
||||
static esp_eth_phy_t *s_phy = NULL;
|
||||
static esp_eth_handle_t s_eth_handle = NULL;
|
||||
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
||||
|
||||
|
||||
/** Event handler for Ethernet events */
|
||||
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg;
|
||||
switch (event_id) {
|
||||
case ETHERNET_EVENT_CONNECTED:
|
||||
xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT);
|
||||
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||
break;
|
||||
case ETHERNET_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||
break;
|
||||
case ETHERNET_EVENT_START:
|
||||
xEventGroupSetBits(eth_event_group, ETH_START_BIT);
|
||||
ESP_LOGI(TAG, "Ethernet Started");
|
||||
break;
|
||||
case ETHERNET_EVENT_STOP:
|
||||
xEventGroupSetBits(eth_event_group, ETH_STOP_BIT);
|
||||
ESP_LOGI(TAG, "Ethernet Stopped");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Event handler for IP_EVENT_ETH_GOT_IP */
|
||||
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg;
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
const esp_netif_ip_info_t *ip_info = &event->ip_info;
|
||||
ESP_LOGI(TAG, "Ethernet Got IP Address");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
|
||||
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
|
||||
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT);
|
||||
}
|
||||
|
||||
static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait)
|
||||
{
|
||||
int i = 0;
|
||||
ms_to_wait += 100;
|
||||
for (i = 0; i < ms_to_wait / 100; i++) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (esp_eth_driver_uninstall(eth_hdl) == ESP_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < ms_to_wait / 10) {
|
||||
return ESP_OK;
|
||||
} else {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void connect_test_fixture_setup(void)
|
||||
{
|
||||
EventBits_t bits;
|
||||
s_eth_event_group = xEventGroupCreate();
|
||||
TEST_ASSERT(s_eth_event_group != NULL);
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
// create TCP/IP netif
|
||||
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
|
||||
s_eth_netif = esp_netif_new(&netif_cfg);
|
||||
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
||||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||
|
||||
// install Ethernet driver
|
||||
TEST_ESP_OK(esp_eth_driver_install(ð_config, &s_eth_handle));
|
||||
// combine driver with netif
|
||||
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
||||
TEST_ESP_OK(esp_netif_attach(s_eth_netif, s_eth_glue));
|
||||
// register user defined event handlers
|
||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, s_eth_event_group));
|
||||
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, s_eth_event_group));
|
||||
// start Ethernet driver
|
||||
TEST_ESP_OK(esp_eth_start(s_eth_handle));
|
||||
/* wait for IP lease */
|
||||
bits = xEventGroupWaitBits(s_eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS));
|
||||
TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT);
|
||||
}
|
||||
|
||||
void connect_test_fixture_teardown(void)
|
||||
{
|
||||
EventBits_t bits;
|
||||
// stop Ethernet driver
|
||||
TEST_ESP_OK(esp_eth_stop(s_eth_handle));
|
||||
/* wait for connection stop */
|
||||
bits = xEventGroupWaitBits(s_eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS));
|
||||
TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT);
|
||||
TEST_ESP_OK(esp_eth_del_netif_glue(s_eth_glue));
|
||||
/* driver should be uninstalled within 2 seconds */
|
||||
TEST_ESP_OK(test_uninstall_driver(s_eth_handle, 2000));
|
||||
TEST_ESP_OK(s_phy->del(s_phy));
|
||||
TEST_ESP_OK(s_mac->del(s_mac));
|
||||
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
|
||||
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
|
||||
esp_netif_destroy(s_eth_netif);
|
||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||
vEventGroupDelete(s_eth_event_group);
|
||||
}
|
||||
#endif // SOC_EMAC_SUPPORTED
|
||||
@@ -1,16 +0,0 @@
|
||||
#This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../common")
|
||||
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "5.5")
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components")
|
||||
else()
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
|
||||
endif()
|
||||
|
||||
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(esp_mqtt_client_test)
|
||||
@@ -1,2 +0,0 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 |
|
||||
| ----------------- | ----- | -------- |
|
||||
@@ -1,8 +0,0 @@
|
||||
set(srcs test_mqtt_client_broker.c test_mqtt.c)
|
||||
|
||||
if(CONFIG_MQTT_PROTOCOL_5)
|
||||
list(APPEND srcs test_mqtt5_client_broker.c test_mqtt5.c)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
PRIV_REQUIRES cmock test_utils mqtt nvs_flash app_update spi_flash common)
|
||||
@@ -1,14 +0,0 @@
|
||||
menu "ESP-MQTT Unit Test Config"
|
||||
|
||||
config MQTT_TEST_BROKER_URI
|
||||
string "URI of the test broker"
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL of an mqtt broker which this test connects to.
|
||||
|
||||
config MQTT5_TEST_BROKER_URI
|
||||
string "URI of the test broker"
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL of an mqtt broker which this test connects to.
|
||||
endmenu
|
||||
@@ -1,5 +0,0 @@
|
||||
dependencies:
|
||||
espressif/mqtt:
|
||||
version: "*"
|
||||
override_path: "../../../.."
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*
|
||||
* This test code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, this
|
||||
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "unity_fixture.h"
|
||||
#include "unity_fixture_extras.h"
|
||||
#include "test_utils.h"
|
||||
#include "memory_checks.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "test_mqtt_client_broker.h"
|
||||
#include "test_mqtt_connection.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
TEST_GROUP(mqtt);
|
||||
|
||||
TEST_SETUP(mqtt){
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(mqtt){
|
||||
test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
|
||||
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
|
||||
}
|
||||
|
||||
TEST(mqtt, init_with_invalid_url)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = "INVALID",
|
||||
};
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_EQUAL(NULL, client );
|
||||
}
|
||||
|
||||
TEST(mqtt, init_and_deinit)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
// no connection takes place, but the uri has to be valid for init() to succeed
|
||||
.broker.address.uri = "mqtts://localhost:8883",
|
||||
};
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, client );
|
||||
esp_mqtt_client_destroy(client);
|
||||
}
|
||||
|
||||
static const char* this_bin_addr(void)
|
||||
{
|
||||
esp_partition_mmap_handle_t out_handle;
|
||||
const void *binary_address;
|
||||
const esp_partition_t* partition = esp_ota_get_running_partition();
|
||||
esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle);
|
||||
return binary_address;
|
||||
}
|
||||
|
||||
TEST(mqtt, enqueue_and_destroy_outbox)
|
||||
{
|
||||
const char * bin_addr = this_bin_addr();
|
||||
|
||||
// Reseting leak detection since this_bin_addr adds to allocated memory.
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
const int messages = 20;
|
||||
const int size = 2000;
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
// no connection takes place, but the uri has to be valid for init() to succeed
|
||||
.broker.address.uri = "mqtts://localhost:8883",
|
||||
};
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, client );
|
||||
int bytes_before = esp_get_free_heap_size();
|
||||
for (int i=0; i<messages; ++i) {
|
||||
esp_mqtt_client_publish(client, "test", bin_addr, size, 1, 0);
|
||||
}
|
||||
int bytes_after = esp_get_free_heap_size();
|
||||
// check that outbox allocated all messages on heap
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(messages*size, bytes_before - bytes_after);
|
||||
|
||||
esp_mqtt_client_destroy(client);
|
||||
}
|
||||
|
||||
#if SOC_EMAC_SUPPORTED
|
||||
/**
|
||||
* This test cases uses ethernet kit, so build and use it only if EMAC supported
|
||||
*/
|
||||
TEST(mqtt, broker_tests)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
connect_test_fixture_setup();
|
||||
|
||||
RUN_MQTT_BROKER_TEST(mqtt_connect_disconnect);
|
||||
RUN_MQTT_BROKER_TEST(mqtt_subscribe_publish);
|
||||
RUN_MQTT_BROKER_TEST(mqtt_lwt_clean_disconnect);
|
||||
RUN_MQTT_BROKER_TEST(mqtt_subscribe_payload);
|
||||
|
||||
connect_test_fixture_teardown();
|
||||
}
|
||||
#endif // SOC_EMAC_SUPPORTED
|
||||
|
||||
|
||||
TEST_GROUP_RUNNER(mqtt) {
|
||||
RUN_TEST_CASE(mqtt, init_with_invalid_url);
|
||||
RUN_TEST_CASE(mqtt, init_and_deinit);
|
||||
RUN_TEST_CASE(mqtt, enqueue_and_destroy_outbox);
|
||||
|
||||
#if SOC_EMAC_SUPPORTED
|
||||
RUN_TEST_CASE(mqtt, broker_tests);
|
||||
#endif // SOC_EMAC_SUPPORTED
|
||||
}
|
||||
|
||||
void app_main(void){
|
||||
UNITY_MAIN(mqtt);
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
|
||||
#define WAIT_FOR_EVENT(event) \
|
||||
TEST_ASSERT_TRUE(xEventGroupWaitBits(s_event_group, event, pdTRUE, pdTRUE, pdMS_TO_TICKS(COMMON_OPERATION_TIMEOUT)) & event);
|
||||
|
||||
#define TEST_ASSERT_TRUE(condition) TEST_ASSERT_TRUE_LINE(condition, __LINE__)
|
||||
#define TEST_ASSERT_TRUE_LINE(condition, line) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
ESP_LOGE("test_mqtt_client_broker.c", \
|
||||
"Assertion failed in line %d", line); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
static const int COMMON_OPERATION_TIMEOUT = 10000;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int DISCONNECT_BIT = BIT1;
|
||||
static const int DATA_BIT = BIT2;
|
||||
|
||||
static EventGroupHandle_t s_event_group;
|
||||
|
||||
static char* append_mac(const char* string)
|
||||
{
|
||||
uint8_t mac[6];
|
||||
char *id_string = NULL;
|
||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
asprintf(&id_string, "%s_%02x%02X%02X", string, mac[3], mac[4], mac[5]);
|
||||
return id_string;
|
||||
}
|
||||
|
||||
static void mqtt_data_handler_qos(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_DATA) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
int * qos = handler_args;
|
||||
*qos = event->qos;
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_data_handler_lwt(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_DATA) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA");
|
||||
ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic);
|
||||
ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data);
|
||||
if (strncmp(event->data, "no-lwt", event->data_len) == 0) {
|
||||
// no lwt, just to indicate the test has finished
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
} else {
|
||||
// count up any potential lwt message
|
||||
int * count = handler_args;
|
||||
*count = *count + 1;
|
||||
ESP_LOGE("mqtt-lwt", "count=%d", *count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_data_handler_subscribe(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_SUBSCRIBED) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
ESP_LOGI("mqtt-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len);
|
||||
int * sub_payload = handler_args;
|
||||
if (event->data_len == 1) {
|
||||
ESP_LOGI("mqtt-subscribe", "DATA=%d", *(uint8_t*)event->data);
|
||||
*sub_payload = *(uint8_t*)event->data;
|
||||
}
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
switch ((esp_mqtt_event_id_t)event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
xEventGroupSetBits(s_event_group, CONNECT_BIT);
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool mqtt_connect_disconnect(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
|
||||
.network.disable_auto_reconnect = true,
|
||||
};
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
esp_mqtt_client_disconnect(client);
|
||||
WAIT_FOR_EVENT(DISCONNECT_BIT);
|
||||
esp_mqtt_client_reconnect(client);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt_subscribe_publish(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
|
||||
};
|
||||
char* topic = append_mac("topic");
|
||||
TEST_ASSERT_TRUE(NULL != topic);
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int qos = -1;
|
||||
esp_mqtt_client_register_event(client, MQTT_EVENT_DATA, mqtt_data_handler_qos, &qos);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 2, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos == 2);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 1, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos == 1);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(topic);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt_lwt_clean_disconnect(void)
|
||||
{
|
||||
char* lwt = append_mac("lwt");
|
||||
TEST_ASSERT_TRUE(lwt);
|
||||
const esp_mqtt_client_config_t mqtt_cfg1 = {
|
||||
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
|
||||
.credentials.set_null_client_id = true,
|
||||
.session.last_will.topic = lwt,
|
||||
.session.last_will.msg = "lwt_msg"
|
||||
};
|
||||
const esp_mqtt_client_config_t mqtt_cfg2 = {
|
||||
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
|
||||
.credentials.set_null_client_id = true,
|
||||
.session.last_will.topic = lwt,
|
||||
.session.last_will.msg = "lwt_msg"
|
||||
};
|
||||
s_event_group = xEventGroupCreate();
|
||||
|
||||
esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt_cfg1);
|
||||
esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt_cfg2);
|
||||
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 );
|
||||
esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_start(client1) == ESP_OK);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_start(client2) == ESP_OK);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int counter = 0;
|
||||
esp_mqtt_client_register_event(client1, MQTT_EVENT_DATA, mqtt_data_handler_lwt, &counter);
|
||||
esp_mqtt_client_register_event(client2, MQTT_EVENT_DATA, mqtt_data_handler_lwt, &counter);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1);
|
||||
esp_mqtt_client_disconnect(client1);
|
||||
WAIT_FOR_EVENT(DISCONNECT_BIT);
|
||||
esp_mqtt_client_reconnect(client1);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1);
|
||||
esp_mqtt_client_stop(client2);
|
||||
esp_mqtt_client_start(client2);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client1, lwt, "no-lwt", 0, 0, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(counter == 0);
|
||||
esp_mqtt_client_destroy(client1);
|
||||
esp_mqtt_client_destroy(client2);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(lwt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt_subscribe_payload(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT_TEST_BROKER_URI,
|
||||
.network.disable_auto_reconnect = true,
|
||||
};
|
||||
char* topic = append_mac("topic");
|
||||
TEST_ASSERT_TRUE(NULL != topic);
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int qos_payload = -1;
|
||||
esp_mqtt_client_register_event(client, MQTT_EVENT_SUBSCRIBED, mqtt_data_handler_subscribe, &qos_payload);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos_payload == 2);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos_payload == 0);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(topic);
|
||||
return true;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
#include "esp_log.h"
|
||||
|
||||
/**
|
||||
* @brief MQTT client-broker tests are not implemented as separate test cases
|
||||
* due to time consuming connection setup/teardown.
|
||||
* This utility macro is used to run functional cases as MQTT tests
|
||||
* and evaluate as separate assertions in one "mqtt broker tests" test case.
|
||||
*/
|
||||
#define RUN_MQTT_BROKER_TEST(test_name) \
|
||||
do { \
|
||||
ESP_LOGI("mqtt_test", "Running test:" #test_name "()"); \
|
||||
TEST_ASSERT_TRUE_MESSAGE(test_name(), "Mqtt test failed: " #test_name "() "); \
|
||||
ESP_LOGI("mqtt_test", "Test:" #test_name "() passed "); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief This module contains mqtt test cases interacting the client with a (real) broker
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The client subscribes and publishes on the same topic
|
||||
* and verifies the received published qos in the event
|
||||
*/
|
||||
bool mqtt_subscribe_publish(void);
|
||||
|
||||
/**
|
||||
* @brief The client connects, disconnects and reconnects.
|
||||
* Tests basic client state transitions
|
||||
*/
|
||||
bool mqtt_connect_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief Two clients with defined lwt connect and subscribe to lwt topic.
|
||||
* This test verifies that no lwt is send when each of the client disconnects.
|
||||
* (we expect a clean disconnection, so no last-will being sent)
|
||||
*/
|
||||
bool mqtt_lwt_clean_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief The client subscribes to a topic with certain qos
|
||||
* and verifies the qos in SUBACK message from the broker.
|
||||
*/
|
||||
bool mqtt_subscribe_payload(void);
|
||||
@@ -1,11 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.ethernet
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_mqtt_client(dut: Dut) -> None:
|
||||
dut.expect_unity_test_output()
|
||||
@@ -1,4 +0,0 @@
|
||||
CONFIG_MQTT_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTT_BROKER_TCP}"
|
||||
CONFIG_MQTT5_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTT_BROKER_TCP}"
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
@@ -1,3 +0,0 @@
|
||||
# General options for additional checks
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
@@ -1,16 +0,0 @@
|
||||
#This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS "../common")
|
||||
|
||||
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "5.5")
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components")
|
||||
else()
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
|
||||
endif()
|
||||
|
||||
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(esp_mqtt5_client_test)
|
||||
@@ -1,2 +0,0 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 |
|
||||
| ----------------- | ----- | -------- |
|
||||
@@ -1,4 +0,0 @@
|
||||
set(srcs test_mqtt5_client_broker.c test_mqtt5.c)
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
PRIV_REQUIRES cmock test_utils mqtt nvs_flash app_update spi_flash common)
|
||||
@@ -1,14 +0,0 @@
|
||||
menu "ESP-MQTT Unit Test Config"
|
||||
|
||||
config MQTT_TEST_BROKER_URI
|
||||
string "URI of the test broker"
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL of an mqtt broker which this test connects to.
|
||||
|
||||
config MQTT5_TEST_BROKER_URI
|
||||
string "URI of the test broker"
|
||||
default "mqtt://mqtt.eclipseprojects.io"
|
||||
help
|
||||
URL of an mqtt broker which this test connects to.
|
||||
endmenu
|
||||
@@ -1,4 +0,0 @@
|
||||
dependencies:
|
||||
espressif/mqtt:
|
||||
version: "*"
|
||||
override_path: "../../../.."
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "unity_fixture.h"
|
||||
#include "unity_fixture_extras.h"
|
||||
#include "test_utils.h"
|
||||
#include "memory_checks.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "test_mqtt5_client_broker.h"
|
||||
#include "test_mqtt_connection.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
|
||||
TEST_GROUP(mqtt5);
|
||||
|
||||
TEST_SETUP(mqtt5)
|
||||
{
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
}
|
||||
|
||||
TEST_TEAR_DOWN(mqtt5)
|
||||
{
|
||||
test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
|
||||
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
|
||||
}
|
||||
|
||||
static esp_mqtt5_user_property_item_t user_property_arr[3] = {
|
||||
{"board", "esp32"},
|
||||
{"u", "user"},
|
||||
{"p", "password"}
|
||||
};
|
||||
|
||||
TEST(mqtt5, init_with_invalid_url)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
.broker.address.uri = "INVALID",
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
TEST_ASSERT_EQUAL(NULL, client );
|
||||
}
|
||||
|
||||
TEST(mqtt5, init_and_deinit)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
// no connection takes place, but the uri has to be valid for init() to succeed
|
||||
.broker.address.uri = "mqtts://localhost:8883",
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
.credentials.username = "123",
|
||||
.credentials.authentication.password = "456",
|
||||
.session.last_will.topic = "/topic/will",
|
||||
.session.last_will.msg = "i will leave",
|
||||
.session.last_will.msg_len = 12,
|
||||
.session.last_will.qos = 1,
|
||||
.session.last_will.retain = true,
|
||||
};
|
||||
esp_mqtt5_connection_property_config_t connect_property = {
|
||||
.session_expiry_interval = 10,
|
||||
.maximum_packet_size = 1024,
|
||||
.receive_maximum = 65535,
|
||||
.topic_alias_maximum = 2,
|
||||
.request_resp_info = true,
|
||||
.request_problem_info = true,
|
||||
.will_delay_interval = 10,
|
||||
.payload_format_indicator = true,
|
||||
.message_expiry_interval = 10,
|
||||
.content_type = "json",
|
||||
.response_topic = "/test/response",
|
||||
.correlation_data = "123456",
|
||||
.correlation_data_len = 6,
|
||||
};
|
||||
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3);
|
||||
esp_mqtt5_client_set_user_property(&connect_property.will_user_property, user_property_arr, 3);
|
||||
esp_mqtt5_client_set_connect_property(client, &connect_property);
|
||||
esp_mqtt5_client_delete_user_property(connect_property.user_property);
|
||||
esp_mqtt5_client_delete_user_property(connect_property.will_user_property);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, client );
|
||||
esp_mqtt_client_destroy(client);
|
||||
}
|
||||
|
||||
static const char *this_bin_addr(void)
|
||||
{
|
||||
esp_partition_mmap_handle_t out_handle;
|
||||
const void *binary_address;
|
||||
const esp_partition_t *partition = esp_ota_get_running_partition();
|
||||
esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &binary_address, &out_handle);
|
||||
return binary_address;
|
||||
}
|
||||
|
||||
TEST(mqtt5, enqueue_and_destroy_outbox)
|
||||
{
|
||||
const char *bin_addr = this_bin_addr();
|
||||
// Reseting leak detection since this_bin_addr adds to allocated memory.
|
||||
test_utils_record_free_mem();
|
||||
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||
const int messages = 20;
|
||||
const int size = 2000;
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
// no connection takes place, but the uri has to be valid for init() to succeed
|
||||
.broker.address.uri = "mqtts://localhost:8883",
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
esp_mqtt5_publish_property_config_t publish_property = {
|
||||
.payload_format_indicator = 1,
|
||||
.message_expiry_interval = 1000,
|
||||
.topic_alias = 0,
|
||||
.response_topic = "/topic/test/response",
|
||||
.correlation_data = "123456",
|
||||
.correlation_data_len = 6,
|
||||
.content_type = "json",
|
||||
};
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, client );
|
||||
int bytes_before = esp_get_free_heap_size();
|
||||
for (int i = 0; i < messages; i ++) {
|
||||
esp_mqtt5_client_set_user_property(&publish_property.user_property, user_property_arr, 3);
|
||||
esp_mqtt5_client_set_publish_property(client, &publish_property);
|
||||
esp_mqtt_client_publish(client, "test", bin_addr, size, 1, 0);
|
||||
esp_mqtt5_client_delete_user_property(publish_property.user_property);
|
||||
publish_property.user_property = NULL;
|
||||
}
|
||||
int bytes_after = esp_get_free_heap_size();
|
||||
// check that outbox allocated all messages on heap
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(messages * size, bytes_before - bytes_after);
|
||||
|
||||
esp_mqtt_client_destroy(client);
|
||||
}
|
||||
|
||||
#if SOC_EMAC_SUPPORTED
|
||||
/**
|
||||
* This test cases uses ethernet kit, so build and use it only if EMAC supported
|
||||
*/
|
||||
TEST(mqtt5, broker_tests)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
connect_test_fixture_setup();
|
||||
|
||||
RUN_MQTT5_BROKER_TEST(mqtt5_connect_disconnect);
|
||||
RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_publish);
|
||||
RUN_MQTT5_BROKER_TEST(mqtt5_lwt_clean_disconnect);
|
||||
RUN_MQTT5_BROKER_TEST(mqtt5_subscribe_payload);
|
||||
|
||||
connect_test_fixture_teardown();
|
||||
}
|
||||
#endif // SOC_EMAC_SUPPORTED
|
||||
|
||||
TEST_GROUP_RUNNER(mqtt5)
|
||||
{
|
||||
#if !DISABLED_FOR_TARGETS(ESP32H2)
|
||||
RUN_TEST_CASE(mqtt5, init_with_invalid_url);
|
||||
RUN_TEST_CASE(mqtt5, init_and_deinit);
|
||||
RUN_TEST_CASE(mqtt5, enqueue_and_destroy_outbox);
|
||||
|
||||
#if SOC_EMAC_SUPPORTED
|
||||
RUN_TEST_CASE(mqtt5, broker_tests);
|
||||
#endif // SOC_EMAC_SUPPORTED
|
||||
#endif //!DISABLED_FOR_TARGETS(ESP32H2)
|
||||
}
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UNITY_MAIN(mqtt5);
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
|
||||
#define WAIT_FOR_EVENT(event) \
|
||||
TEST_ASSERT_TRUE(xEventGroupWaitBits(s_event_group, event, pdTRUE, pdTRUE, pdMS_TO_TICKS(COMMON_OPERATION_TIMEOUT)) & event);
|
||||
|
||||
#define TEST_ASSERT_TRUE(condition) TEST_ASSERT_TRUE_LINE(condition, __LINE__)
|
||||
#define TEST_ASSERT_TRUE_LINE(condition, line) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
ESP_LOGE("test_mqtt5_client_broker.c", \
|
||||
"Assertion failed in line %d", line); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
static const int COMMON_OPERATION_TIMEOUT = 10000;
|
||||
static const int CONNECT_BIT = BIT0;
|
||||
static const int DISCONNECT_BIT = BIT1;
|
||||
static const int DATA_BIT = BIT2;
|
||||
|
||||
static EventGroupHandle_t s_event_group;
|
||||
|
||||
static esp_mqtt5_user_property_item_t user_property_arr[3] = {
|
||||
{"board", "esp32"},
|
||||
{"u", "user"},
|
||||
{"p", "password"}
|
||||
};
|
||||
|
||||
static char* append_mac(const char* string)
|
||||
{
|
||||
uint8_t mac[6];
|
||||
char *id_string = NULL;
|
||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
asprintf(&id_string, "%s_%02x%02X%02X", string, mac[3], mac[4], mac[5]);
|
||||
return id_string;
|
||||
}
|
||||
|
||||
static void mqtt5_data_handler_qos(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_DATA) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
int * qos = handler_args;
|
||||
*qos = event->qos;
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt5_data_handler_lwt(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_DATA) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
ESP_LOGI("mqtt-lwt", "MQTT_EVENT_DATA");
|
||||
ESP_LOGI("mqtt-lwt", "TOPIC=%.*s", event->topic_len, event->topic);
|
||||
ESP_LOGI("mqtt-lwt", "DATA=%.*s", event->data_len, event->data);
|
||||
if (strncmp(event->data, "no-lwt", event->data_len) == 0) {
|
||||
// no lwt, just to indicate the test has finished
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
} else {
|
||||
// count up any potential lwt message
|
||||
int * count = handler_args;
|
||||
*count = *count + 1;
|
||||
ESP_LOGE("mqtt5-lwt", "count=%d", *count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt5_data_handler_subscribe(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_id == MQTT_EVENT_SUBSCRIBED) {
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
ESP_LOGI("mqtt5-subscribe", "MQTT_EVENT_SUBSCRIBED, data size=%d", event->data_len);
|
||||
int * sub_payload = handler_args;
|
||||
if (event->data_len == 1) {
|
||||
ESP_LOGI("mqtt5-subscribe", "DATA=%d", *(uint8_t*)event->data);
|
||||
*sub_payload = *(uint8_t*)event->data;
|
||||
}
|
||||
xEventGroupSetBits(s_event_group, DATA_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mqtt5_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
switch ((esp_mqtt_event_id_t)event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
xEventGroupSetBits(s_event_group, CONNECT_BIT);
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
xEventGroupSetBits(s_event_group, DISCONNECT_BIT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool mqtt5_connect_disconnect(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
|
||||
.network.disable_auto_reconnect = true,
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
esp_mqtt5_connection_property_config_t connect_property = {
|
||||
.session_expiry_interval = 10,
|
||||
.maximum_packet_size = 1024,
|
||||
.receive_maximum = 65535,
|
||||
.topic_alias_maximum = 2,
|
||||
.request_resp_info = true,
|
||||
.request_problem_info = true,
|
||||
};
|
||||
esp_mqtt5_disconnect_property_config_t disconnect_property = {
|
||||
.session_expiry_interval = 10,
|
||||
.disconnect_reason = 0,
|
||||
};
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, 3));
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client, &connect_property));
|
||||
esp_mqtt5_client_delete_user_property(connect_property.user_property);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_user_property(&disconnect_property.user_property, user_property_arr, 3));
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_disconnect_property(client, &disconnect_property));
|
||||
esp_mqtt5_client_delete_user_property(disconnect_property.user_property);
|
||||
esp_mqtt_client_disconnect(client);
|
||||
WAIT_FOR_EVENT(DISCONNECT_BIT);
|
||||
esp_mqtt_client_reconnect(client);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt5_subscribe_publish(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
esp_mqtt5_publish_property_config_t publish_property = {
|
||||
.payload_format_indicator = 1,
|
||||
.message_expiry_interval = 1000,
|
||||
.topic_alias = 1,
|
||||
.response_topic = "/topic/test/response",
|
||||
.correlation_data = "123456",
|
||||
.correlation_data_len = 6,
|
||||
.content_type = "json",
|
||||
};
|
||||
esp_mqtt5_subscribe_property_config_t subscribe_property = {
|
||||
.subscribe_id = 25555,
|
||||
.no_local_flag = false,
|
||||
.retain_as_published_flag = true,
|
||||
.retain_handle = 0,
|
||||
};
|
||||
char* topic = append_mac("topic");
|
||||
TEST_ASSERT_TRUE(NULL != topic);
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int qos = -1;
|
||||
esp_mqtt_client_register_event(client, MQTT_EVENT_DATA, mqtt5_data_handler_qos, &qos);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_subscribe_property(client, &subscribe_property));
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_publish_property(client, &publish_property));
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 2, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos == 2);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client, topic, "message", 0, 1, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos == 1);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(topic);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt5_lwt_clean_disconnect(void)
|
||||
{
|
||||
char* lwt = append_mac("lwt");
|
||||
TEST_ASSERT_TRUE(lwt);
|
||||
const esp_mqtt_client_config_t mqtt5_cfg1 = {
|
||||
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
|
||||
.credentials.set_null_client_id = true,
|
||||
.session.last_will.topic = lwt,
|
||||
.session.last_will.msg = "lwt_msg",
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
const esp_mqtt_client_config_t mqtt5_cfg2 = {
|
||||
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
|
||||
.credentials.set_null_client_id = true,
|
||||
.session.last_will.topic = lwt,
|
||||
.session.last_will.msg = "lwt_msg",
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
esp_mqtt5_connection_property_config_t connect_property = {
|
||||
.will_delay_interval = 10,
|
||||
.payload_format_indicator = true,
|
||||
.message_expiry_interval = 10,
|
||||
.content_type = "json",
|
||||
.response_topic = "/test/response",
|
||||
.correlation_data = "123456",
|
||||
.correlation_data_len = 6,
|
||||
};
|
||||
s_event_group = xEventGroupCreate();
|
||||
|
||||
esp_mqtt_client_handle_t client1 = esp_mqtt_client_init(&mqtt5_cfg1);
|
||||
esp_mqtt_client_handle_t client2 = esp_mqtt_client_init(&mqtt5_cfg2);
|
||||
TEST_ASSERT_TRUE(NULL != client1 && NULL != client2 );
|
||||
esp_mqtt_client_register_event(client1, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
|
||||
esp_mqtt_client_register_event(client2, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client1, &connect_property));
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt5_client_set_connect_property(client2, &connect_property));
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_start(client1) == ESP_OK);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_start(client2) == ESP_OK);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int counter = 0;
|
||||
esp_mqtt_client_register_event(client1, MQTT_EVENT_DATA, mqtt5_data_handler_lwt, &counter);
|
||||
esp_mqtt_client_register_event(client2, MQTT_EVENT_DATA, mqtt5_data_handler_lwt, &counter);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1);
|
||||
esp_mqtt_client_disconnect(client1);
|
||||
WAIT_FOR_EVENT(DISCONNECT_BIT);
|
||||
esp_mqtt_client_reconnect(client1);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client1, lwt, 0) != -1);
|
||||
esp_mqtt_client_stop(client2);
|
||||
esp_mqtt_client_start(client2);
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client2, lwt, 0) != -1);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_publish(client1, lwt, "no-lwt", 0, 0, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(counter == 0);
|
||||
esp_mqtt_client_destroy(client1);
|
||||
esp_mqtt_client_destroy(client2);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(lwt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mqtt5_subscribe_payload(void)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt5_cfg = {
|
||||
.broker.address.uri = CONFIG_MQTT5_TEST_BROKER_URI,
|
||||
.network.disable_auto_reconnect = true,
|
||||
.session.protocol_ver = MQTT_PROTOCOL_V_5,
|
||||
};
|
||||
char* topic = append_mac("topic");
|
||||
TEST_ASSERT_TRUE(NULL != topic);
|
||||
s_event_group = xEventGroupCreate();
|
||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt5_cfg);
|
||||
TEST_ASSERT_TRUE(NULL != client );
|
||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt5_event_handler, NULL);
|
||||
TEST_ASSERT_TRUE(ESP_OK == esp_mqtt_client_start(client));
|
||||
WAIT_FOR_EVENT(CONNECT_BIT);
|
||||
int qos_payload = -1;
|
||||
esp_mqtt_client_register_event(client, MQTT_EVENT_SUBSCRIBED, mqtt5_data_handler_subscribe, &qos_payload);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 2) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos_payload == 2);
|
||||
TEST_ASSERT_TRUE(esp_mqtt_client_subscribe(client, topic, 0) != -1);
|
||||
WAIT_FOR_EVENT(DATA_BIT);
|
||||
TEST_ASSERT_TRUE(qos_payload == 0);
|
||||
esp_mqtt_client_destroy(client);
|
||||
vEventGroupDelete(s_event_group);
|
||||
free(topic);
|
||||
return true;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "esp_log.h"
|
||||
|
||||
/**
|
||||
* @brief MQTT5 client-broker tests are not implemented as separate test cases
|
||||
* due to time consuming connection setup/teardown.
|
||||
* This utility macro is used to run functional cases as MQTT tests
|
||||
* and evaluate as separate assertions in one "mqtt5 broker tests" test case.
|
||||
*/
|
||||
#define RUN_MQTT5_BROKER_TEST(test_name) \
|
||||
do { \
|
||||
ESP_LOGI("mqtt5_test", "Running test:" #test_name "()"); \
|
||||
TEST_ASSERT_TRUE_MESSAGE(test_name(), "Mqtt5 test failed: " #test_name "() "); \
|
||||
ESP_LOGI("mqtt5_test", "Test:" #test_name "() passed "); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief This module contains mqtt5 test cases interacting the client with a (real) broker
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief The client subscribes and publishes on the same topic
|
||||
* and verifies the received published qos in the event
|
||||
*/
|
||||
bool mqtt5_subscribe_publish(void);
|
||||
|
||||
/**
|
||||
* @brief The client connects, disconnects and reconnects.
|
||||
* Tests basic client state transitions
|
||||
*/
|
||||
bool mqtt5_connect_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief Two clients with defined lwt connect and subscribe to lwt topic.
|
||||
* This test verifies that no lwt is send when each of the client disconnects.
|
||||
* (we expect a clean disconnection, so no last-will being sent)
|
||||
*/
|
||||
bool mqtt5_lwt_clean_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief The client subscribes to a topic with certain qos
|
||||
* and verifies the qos in SUBACK message from the broker.
|
||||
*/
|
||||
bool mqtt5_subscribe_payload(void);
|
||||
@@ -1,11 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.ethernet
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_mqtt5_client(dut: Dut) -> None:
|
||||
dut.expect_unity_test_output()
|
||||
@@ -1,4 +0,0 @@
|
||||
CONFIG_MQTT_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTT_BROKER_TCP}"
|
||||
CONFIG_MQTT5_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTT_BROKER_TCP}"
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
@@ -1,4 +0,0 @@
|
||||
# General options for additional checks
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_MQTT_PROTOCOL_5=y
|
||||
CONFIG_UNITY_ENABLE_FIXTURE=y
|
||||
@@ -1,16 +0,0 @@
|
||||
# The following four lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
|
||||
project(mqtt_publish_connect_test)
|
||||
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "main/mqtt_eclipseprojects_io.pem" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "ca.crt" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "ca.der" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.key" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.crt" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "client_no_pwd.key" TEXT)
|
||||
target_add_binary_data(mqtt_publish_connect_test.elf "client_inv.crt" TEXT)
|
||||
@@ -1,25 +0,0 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 |
|
||||
| ----------------- | ----- | -------- | -------- |
|
||||
|
||||
# ESP-MQTT advanced publish and connect test project
|
||||
|
||||
Main purpose of this application is to test the MQTT library to correctly publish and receive messages (of different size and sequences) over different transports.
|
||||
It is possible to run this example manually without any test to exercise how the MQTT library deals with
|
||||
|
||||
- reception of fragmented messages
|
||||
- runtime updates of URI
|
||||
|
||||
## Runtime settings
|
||||
|
||||
This app waits for user input to provide these parameters:
|
||||
- test-type: "conn" if connection test (host, port, test-case number)
|
||||
- publish test:
|
||||
* transport: string parameter, one of: tcp, ssl, ws, wss
|
||||
* pattern: sample string to be transmitted as message
|
||||
* pattern repeats: number of repeats of pattern in one MQTT message
|
||||
* repeated: number of repeats ESP32 publishes the message, also ESP32 expects to receive the same message the same number of repeats
|
||||
* qos: number specifying qos, one of: 0, 1, 2
|
||||
|
||||
## Hardware Required
|
||||
|
||||
This test-app can be executed on any ESP32 board, the only required interface is WiFi and connection to a local network, then depending on the test either a mqtt test broker or a tls server.
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGTCCAgGgAwIBAgIUY6kAA+U+ZPIJYIff8dlbi6NCzKswDQYJKoZIhvcNAQEL
|
||||
BQAwFDESMBAGA1UEAwwJRXNwcmVzc2lmMB4XDTI1MDQwMjA1MjcwMloXDTM1MDMz
|
||||
MTA1MjcwMlowFDESMBAGA1UEAwwJRXNwcmVzc2lmMIIBIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAQ8AMIIBCgKCAQEAwSY/p8zDP8W3f37xfL1jy/WcWVOOS2msWRyxjpXQM2e+
|
||||
66McSkn8mVKTW5/aZ96sFQbmBBuhp3ypopH+kBQHxK4kla6roEcN/Nx9wpC8X64l
|
||||
U9EqPmOvcIG8HElEY05LzZ9Rzc4LIBREq/sM8FE5+YHO2za8rN2XIaMii0mm2alf
|
||||
o1MFEq1nkHBeJKlXkk6eZDwcQ9kqLWBz9YQWygE2pmDCjdCoY97/dZpgAjvkrAGN
|
||||
9UYno9ZmNOYefL1P1ZmVtdBRW/xDGTDSZCJGYHOrtvfD8VS6cguOOl+rsy3obFdh
|
||||
A4AgGFEFtfdY/+2fJHFkn6Pep6j+7h8f9n89qpSwswIDAQABo2MwYTAdBgNVHQ4E
|
||||
FgQUJ+QsjjuS10OtEEcU0Wh2XhXTa1YwHwYDVR0jBBgwFoAUJ+QsjjuS10OtEEcU
|
||||
0Wh2XhXTa1YwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZI
|
||||
hvcNAQELBQADggEBABKWpI+QdMYoDwyssIbfwpbqJxb5M1w3PLnMsPzg1d5aEqLh
|
||||
zwN9EnEQ5TxfeC7Lxdv3hKEGtif/aVxBhs48wPSxD7Fuw17kX6P4l9Cu9Ro2+1Oy
|
||||
0lUxHi61xXxf7zVkdPQ0JLXdSMUvSUuKfvBtHCwEfdC+lsamxIDmCJys69kDhsCM
|
||||
VJzY8Yz4MA9WOY3Z2YYMRp6ryFBZ9UgSUEnFxSOpggymkcM5mNxod1jshvSJ3FDG
|
||||
dmvfbmK0+dN3rCiooORsIYVbopAYxralavA9IY24oiULE+GyVt5pNSONmJ96Y7GK
|
||||
dL72B8RxX+jUSzgu/N3D1DwbPHP/xRiI7EqaYvg=
|
||||
-----END CERTIFICATE-----
|
||||
Binary file not shown.
@@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDBJj+nzMM/xbd/
|
||||
fvF8vWPL9ZxZU45LaaxZHLGOldAzZ77roxxKSfyZUpNbn9pn3qwVBuYEG6GnfKmi
|
||||
kf6QFAfEriSVrqugRw383H3CkLxfriVT0So+Y69wgbwcSURjTkvNn1HNzgsgFESr
|
||||
+wzwUTn5gc7bNrys3ZchoyKLSabZqV+jUwUSrWeQcF4kqVeSTp5kPBxD2SotYHP1
|
||||
hBbKATamYMKN0Khj3v91mmACO+SsAY31Riej1mY05h58vU/VmZW10FFb/EMZMNJk
|
||||
IkZgc6u298PxVLpyC446X6uzLehsV2EDgCAYUQW191j/7Z8kcWSfo96nqP7uHx/2
|
||||
fz2qlLCzAgMBAAECggEAA5+hkxbS1OfzLNenVSVCcYmekMhyA3UskBFrPVcPLF+2
|
||||
Y7pQJg6kSAYWEKJ7mPZC+TQDbbFNA5Tho9SkV3Sgvq5brlk0DBI5L3S9gUBw4ESm
|
||||
m59xcPEy0eQFMOyo9Un7PxTNlpRWfhgTP7y6femwMj+er1skCAQyOSXT2JQdpriv
|
||||
5BnQquVSeoPbFuuObxerG878BDvMEIFzkZGmjWHhWD9P3+2sHcU6R6aZexRnkMrw
|
||||
A8gagVzIi35QPDtWYLWcybdghJW7BdW8Lsx7HvMzRvNlBxMFnqtzNspuXEyZVlXF
|
||||
J7cMpktiMQ+dNk18Utq9n19Y5ZWWi5g+XY3V0dHs3QKBgQDgrmdRWD3lLwY0equ6
|
||||
/kk6Pf+GwgRLTVQy4DfUHPFCUY3+fZgYTL7InLjgcLynSdcHZ6hXjdIsAxwgeD6U
|
||||
eBjjAhIyRNDTrSD91NQb99kmjSB9PRnPsERFiol5mR/JGUIs67y1a9oGPvhXW/9f
|
||||
nu5jIacqF5sGZhmVmssYc/yXbQKBgQDcEqcKF+0WxHSNPMBtSFBOf/Uz6cT79lLS
|
||||
1EoMiIjhQM1TrnRPqOicRegHmW7dWvtnsReprW6/mjz7t8C2kQm0Mf2UAtEm2Hzu
|
||||
XxHM1Jmj1/oNc5Gzv5PhDMY8XEafzogj2uwL9++On74XNTkt20hl7qM4lcibu86U
|
||||
f67cuOK0nwKBgQC3e7XEKFvjndNjaAp2WtNSTO8wDaGUHUJ1icYN4tTjY9ahzc83
|
||||
iPUEv3f7UhW+R/7ifTRsy9SnPKLroUb52Fn6iOZzRt+C/g/DOts9O9qKMRYnMI6z
|
||||
nS8j208JjpL2lzoDlUA2qC0UjLgiH28dl5z2N7VcGorvXtHl6tOQ1KeiwQKBgQCI
|
||||
kq7FDcodyfdGuz/z0d+8h55FBDsx3lDR89qsYoMHvy5tUyNtWDZa3Os85BQwHMlO
|
||||
NVGpBC9piq9zyzo2UlYCVM+4bfMcN1d4mtkyE3HxgxP0CxeNxENic4oGZYGSpRpJ
|
||||
ng/E8a3iBfJy9p2wfpg0Yd87O4EOXIO8Fm0PH1HZowKBgQCBmYxw+gv7zbY6ejg1
|
||||
prJsVvaVp5D8jhZ8agqRseWpeUEIrTzACNZ8L+loFMwsAIm5piLMziso1b6ktDmk
|
||||
A9c7eOOh/kec8T4LXhIglLL49kmb0ZOCMotG1n9+1n/ZuMV8bMNTGWof5QjOMMKE
|
||||
tC0yOkTvoIqHMbwnLrLLMOxh1w==
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC/zCCAeegAwIBAgIUCpDNnOm701EkM8UghGHxDAXcVWEwDQYJKoZIhvcNAQEL
|
||||
BQAwDjEMMAoGA1UEAwwDZXNwMCAXDTI1MDEyODEzMjkxMloYDzIyOTgxMTEyMTMy
|
||||
OTEyWjAOMQwwCgYDVQQDDANlc3AwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDVLhyorBPIbIS5hi7BCyv+UsrEAr17zfMu31zrj65wrRI2NPjeT/4UXTHB
|
||||
WLXevsBmxngqa1HfBeJiwbjr0HNt7OAAIePnW0v0qfED6S6SG3ySbL7wOTQiUeZE
|
||||
JiDmcjBiu3ttBimOeRAYl2RAHVrVzV01ByQ8QZZ5FFynBl6mOnu0lGSwImDCNoVk
|
||||
g+zDNf9vbZWGUwvjxBoFmjvEdIEVh58c2Bu3Vzlblb/XR4XnQb0hR18VzHTibHdz
|
||||
UKRDDzgoz1CSThmsNSJxOesS8e2wufHyqBQ1uXW2kJDIHwq+Ew7RkyhPLx6hXhN6
|
||||
QS99SN5Sbgpucqc8pjJYFv3oHevXAgMBAAGjUzBRMB0GA1UdDgQWBBT5Ja5qUdUf
|
||||
QRdQBur2UvcJmBmFVzAfBgNVHSMEGDAWgBT5Ja5qUdUfQRdQBur2UvcJmBmFVzAP
|
||||
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBrVzCP7OoyVZyZ80+c
|
||||
+B7Cz1vWmNsyCLHVSuUqr3DuvJa0V71VdMGvr+zfR2/jLW7nGy2I+5d3Yaxs/AIZ
|
||||
GF4XuDfuiJXjRDgFY8Xh+PgM7L4AxVvml8ZWaj9kurbIWKcsizCygoL4ckIA10QO
|
||||
wAg7Au1RZT6iDeGW47inz/bP8V/sQnFmupTPN4VipMCUo61c+L0tnKPGbMySnmGq
|
||||
mf9f/luAh/pgiW/HRjA4bppE5hCxUB8F5wyzAzFMnRVSYptpZdj/AYyAooV7Iit0
|
||||
Ewjtrnxlr7zhmw4p32FuRDNU5AzbQMxDS4delGHMrNtehmSLNeZ3V7tAyG7EmJZd
|
||||
y4YP
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,28 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCQ8NP82CE2OJaZ
|
||||
A07nbHyfhOdv/dnZXcemxFtoiEw1v29t5pldxBPUwy9/eg85+z1H1CTuFfHj2pzK
|
||||
yyB1eJojTtQlJRZn1cZJ/0/LZu7naNACsndXmQcc0b6Cvn/jOuiqvAqFgLknLdEl
|
||||
Iun2NSgeot3lafXy/yuLbKWHRDzsZIEpu/1iUlGx6UAQTBL+HVj2VM3hejdt33gn
|
||||
PwdS+otmv+2A4ZBhbrL7EmtDJLM1wISo5PRp3YSknLJc8PdH5DQE5kaxh8RN/MDe
|
||||
cm7kTeNeL2eN+nj9HvDUJ2yVF2P3ZaW6RtCwFlj0E3VXfKUNz2yTIowDtSkDeG7T
|
||||
zjZ8V5cnAgMBAAECggEAB6ZeWfMCVb1I3YyaJobIURcPrA6G5/0WI4wrkunWs+OF
|
||||
uxQ3tgY6Ubl3kU/c69+BzX+570MDQFZyfhWYgfq6j/CCK++4LgTPcWpjSMYHB/m1
|
||||
ON84g0wVXwUG/BmX4GNkklZYa9FudE3rwv0DwjXuByfrdEdSbt/e6X3zgp8sZAGZ
|
||||
oJnIWVvGxqIS1EvPHWkYlmDEnfNk1iYaQyNuYDxCxwwrLdyvhrsh1eiiGbabN7UK
|
||||
CtqHgpZXXW/3hvCRJkl6EJVLXbegMEt73hN73Mn++iX0MVEDd+GfuEmojbM5rTpz
|
||||
6CjD//CW43m9mJqq4Vx7QyZVQ9wJg9P4AvrD2gw9GQKBgQDJw+ThwWmmixXnsLxN
|
||||
CpYqk77cWogTSEzyKnWYUMfiHUdCOVVEYmG4gnrC5NOuoNU2735rwDslUrGVpFRW
|
||||
lPD8Ocptq6pbtKPlUVucJQVlgfrD2XWd4RuBhEX8mL6lGfTiW82wLeS7QgfDPhnh
|
||||
YtBA+FASdZtsW34ce4+u6nbQqwKBgQC35qk5vXelRkp3gQpzfPLdmvR0UsSkEdD1
|
||||
DvEjixGm5VcNRCdRlxeYCPNt4ADe0EGLKQn+oCwIvrAz95ZUjcAy+nLQJA++AyGi
|
||||
X8TmHhmpJS82Jo2H7h7ZFCBuep+xb4a77DnpK8feYBH7MgL1skwFOJEq3k4Iv40Y
|
||||
Uydzc/irdQKBgE58q86+RHEK7eyBLd7yXVQWwUpK1WBa4cPajIBB/F+TcCLs1qSR
|
||||
eN4js8mY5leqLQb/xzf3QYrVTkud70j3C3+yo3JiMxUVgiQ0r+Rf6meAVqJVN5HA
|
||||
/cg2Qltut8rV/BMKD0uXrsDBgO+MetjYbZa4gb2MjndqZ/aAgnZSswGdAoGAN2Cv
|
||||
PuLuH4feLsRd+E7893yM9mZiLqHq0ZCxTqm3JBHVt/n4+RnNkgvH+iNFP9NomVY/
|
||||
WzyyZeO+Pbflvgp9gRxn7IOfdfGNdE7whPc1dPjskZrkbbVn9qiX54znf8/8u6Q0
|
||||
ACId6rn1UDZMK96IA9534HfW+c1s2JFZxOt8S20CgYBtV6D3iPRzaaDJy7J2Csyu
|
||||
p+4nIeudRfVmzf2VRQOFqyULWNU35I2tBjq5rzN1yAmJCgE2kW1Z4iyfmLhBrF51
|
||||
Wm3OY0R8Q5FvO9CCpL6XaZokEyWIcfEqjHKIIHf7lHeC4fs7YplRaxm7n1vV8hHK
|
||||
UsP/rg6j/qZP+/WKNhsoBg==
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -1,18 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC9DCCAdygAwIBAgIUcPhqC08YW+4RYTuVucv4UXLd2kQwDQYJKoZIhvcNAQEL
|
||||
BQAwFDESMBAGA1UEAwwJRXNwcmVzc2lmMCAXDTI1MDEyODEzMjkxMloYDzIyOTgx
|
||||
MTEyMTMyOTEyWjAOMQwwCgYDVQQDDANlc3AwggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQCQ8NP82CE2OJaZA07nbHyfhOdv/dnZXcemxFtoiEw1v29t5pld
|
||||
xBPUwy9/eg85+z1H1CTuFfHj2pzKyyB1eJojTtQlJRZn1cZJ/0/LZu7naNACsndX
|
||||
mQcc0b6Cvn/jOuiqvAqFgLknLdElIun2NSgeot3lafXy/yuLbKWHRDzsZIEpu/1i
|
||||
UlGx6UAQTBL+HVj2VM3hejdt33gnPwdS+otmv+2A4ZBhbrL7EmtDJLM1wISo5PRp
|
||||
3YSknLJc8PdH5DQE5kaxh8RN/MDecm7kTeNeL2eN+nj9HvDUJ2yVF2P3ZaW6RtCw
|
||||
Flj0E3VXfKUNz2yTIowDtSkDeG7TzjZ8V5cnAgMBAAGjQjBAMB0GA1UdDgQWBBRT
|
||||
WBz6pzNCJ5iMbbxr26mwLic+5zAfBgNVHSMEGDAWgBQn5CyOO5LXQ60QRxTRaHZe
|
||||
FdNrVjANBgkqhkiG9w0BAQsFAAOCAQEAYOfwiCz+pzl9uE0WMOYU0NlSmOchN05m
|
||||
CInOXuU7d38+QGjbnjs5IFmvquf8Ink6Z9hJitpPWHCN6rudT2BbFzzFQVmckMke
|
||||
rbTSxUgyG/Xy4YgvTz49MUlK2fZc0Uun20Fu3vnCWvEPEYAfFdaUfegXtdFkI31J
|
||||
U6EiwwMPzdlX6qLc2h3nKjm5yURvhSlFhKI1DMDhHF0wi09WH0T3CufLY3AQ2npK
|
||||
4Vg3lP4F5Dh3FsaVj0h7BWhd4RfE6oyHkxRRgTfLuANdv6wOt2IR5OZAPedTGD9e
|
||||
W0F0EyQXxsKhfqBeZsKpcYGRPWpOfdwR8nMV4QPuTPwTONmIYLFU5w==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQHePIq3//PykNJRiP
|
||||
8SJIiwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEGd76hqfyLtr9f/w
|
||||
fETYk2QEggTQaLOK5NeAXOodW9eokEvmLeCSSHMfqXJWVSnHEbEJv5b5/lk6BoR0
|
||||
y7BYsWwRs0lvX4AZPflJJpM82VUt3HZdv7I6ANHV71BIkaHc8h5aWUoOFhKsGIqf
|
||||
AibxMYDVs7st6YJFFzXidc0c8zCEDPjtDSdiaXz+lF6cbY7MUz2Ej7yJnECQiRqY
|
||||
PC8tFJdQeUDbqhDSk4VyevgJPLIYILdg0m9PpJYJr97lFYjWyX6Q1FnAX8NPLnTw
|
||||
yQ03OJNkuv1h5Y/nJgtAoISS3dPLn2KjDehJ9xbd6TiiBhyU2dRxKGmx71oOZvbj
|
||||
yLs5TcJs76DcA/0ExxMZz2+pUOpXg/hGtdNCvHL2vrjcQ/f4qpMBd2FiazOzCTtJ
|
||||
fu7DPYtirt+2xlt2htjWkXlIxE0sw4FxQYJPVVruiTfVpGtDuRGQUmAWFq5JASVi
|
||||
2GguLex69JxeQb+Gv0SFwn/6eC14qWy+m3gCUdjW+qkSD+0Mk7mOxNnSIyyHXzhz
|
||||
sXZ7ZncU/5Q3AEtlTYKoFV7BTmaHFRgPG6r7lKKNu2RdPRa8R3fa8HizhnIsdGe/
|
||||
m8H3ESKnpQLDiqA7cIM6eweErrOGMAwHBQSS3IdblZwdb6BPvpNUfp7lQ7YHdOYA
|
||||
Vtl7gkwjniWQgSEOWqfvJ66Cr+u4wfV0rroTVP54pPeBGzort7L7Le3/ACO06ELN
|
||||
Jdv6oTOsSZWs+AzwnU8/NQseB6xjvKafCBEbnYVoajTz29k52UNl/3fru3+e53Wu
|
||||
WqJs8mCK9SGFLZfSp9Brecz0fpFNpQYAEEbd+HRkzT4lXCPPYGiPt+QdlcJtrwjq
|
||||
NNSrCxsYxhsqEXpPzYj5ROvRBHjFGCpv6N33f05HoYQZf1hoXrABI/BQIZgXy8oD
|
||||
AYKgBdrcCzJCuZyP9f66vSW7unxCAedhk4w7l6tozoPIFD2WXJ48ska9xvAjncMa
|
||||
D3OAg95vEW4jfzTdLNSQnk5alOfqwX2CTHcXrzQn0OVnHG3xr1uCtTw605LoKEdf
|
||||
6WQFihRnyIZOHAQyu8DVVGkhqpxH9d49VOrx5iVAhxSeK0vyhlKlZcq915VU6+mi
|
||||
GEqjjywGJlN7Qk1bSfTr3AO6M8+Yd2YsBOzcGxtLkTxiUB94ss8QZzhb8qZWkSJ8
|
||||
XxhCYyL3brsnQJVjPLyJYwNaJGHcEOeSEFHichicont6tD/FdzS6hiMfVO/367f6
|
||||
q3tCLeaRYYBpM2600TjhgjfgupRJ3Y94QY0ukjwOPwx2xaciXR3RkXV0C0G4EiKH
|
||||
zXJSUXxuBtdlHMyNlfh3EKRq17TkzacsbYuZ5jrGV7MIqpLF+dyqkeqMzsGFCnXN
|
||||
S0gRAb2C1JwB3yWZnKtjZbUCwmwxna4YGEQZsGBxFkphvXZDJJpeDjGZHCKSkdRl
|
||||
yY5UrKl6KW+n2h3CkWzuZPbAOs89o3N+pZdAxsaLUy3U4GAOev06z9fhwqjs7zsk
|
||||
R/cDu/D7sIFlJfXW+QT/dXszDuLJmG/fZDBZOOshVmV8AD8nkQG802qPu47VtXLL
|
||||
4NTb3XNO1ayqcrdEu/kdw9XnsXRvvRZ8Fc53qNp0zYF0/DqVnmGtHp9ttVXKDX7d
|
||||
9grf6ltOzqlKfaabXTgaLkcYpeRXOLuDTPCUMRVJuxuhoWI6tQgzVx0=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
@@ -1,4 +0,0 @@
|
||||
idf_component_register(SRCS "publish_test.c" "connect_test.c" "publish_connect_test.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES mqtt nvs_flash console esp_netif)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
@@ -1,94 +0,0 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_BROKER_SSL_URI
|
||||
string "Broker SSL URL"
|
||||
default "mqtts://mqtt.eclipseprojects.io:8883"
|
||||
help
|
||||
URL of an mqtt broker for ssl transport
|
||||
|
||||
config EXAMPLE_BROKER_TCP_URI
|
||||
string "Broker TCP URL"
|
||||
default "mqtt://mqtt.eclipseprojects.io:1883"
|
||||
help
|
||||
URL of an mqtt broker for tcp transport
|
||||
|
||||
config EXAMPLE_BROKER_WS_URI
|
||||
string "Broker WS URL"
|
||||
default "ws://mqtt.eclipseprojects.io:80/mqtt"
|
||||
help
|
||||
URL of an mqtt broker for ws transport
|
||||
|
||||
config EXAMPLE_BROKER_WSS_URI
|
||||
string "Broker WSS URL"
|
||||
default "wss://mqtt.eclipseprojects.io:443/mqtt"
|
||||
help
|
||||
URL of an mqtt broker for wss transport
|
||||
|
||||
config EXAMPLE_BROKER_CERTIFICATE_OVERRIDE
|
||||
string "Broker certificate override"
|
||||
default ""
|
||||
help
|
||||
Please leave empty if broker certificate included from a textfile; otherwise fill in a base64 part of PEM
|
||||
format certificate
|
||||
|
||||
config EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN
|
||||
bool
|
||||
default y if EXAMPLE_BROKER_CERTIFICATE_OVERRIDE != ""
|
||||
|
||||
config EXAMPLE_RUN_LOCAL_BROKER
|
||||
bool "Run local mosquitto"
|
||||
default n
|
||||
help
|
||||
If enabled, this tests uses local mosquitto broker
|
||||
running on the same endpoint as the client
|
||||
|
||||
config EXAMPLE_BROKER_HOST
|
||||
string "Broker host address"
|
||||
default "0.0.0.0"
|
||||
depends on EXAMPLE_RUN_LOCAL_BROKER
|
||||
help
|
||||
Host name of the endpoint to bind the mosquitto listener.
|
||||
|
||||
config EXAMPLE_BROKER_PORT
|
||||
int "Broker port"
|
||||
default 1234
|
||||
depends on EXAMPLE_RUN_LOCAL_BROKER
|
||||
help
|
||||
Port of the endpoint to bind the mosquitto listener
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_NO_CERT
|
||||
# Note: All the below config values (EXAMPLE_CONNECT_CASE...) are hidden and
|
||||
# used to give symbolic names to test cases, which are then referenced from both
|
||||
# the embedded C code as well as the test counterpart in python
|
||||
int
|
||||
default 1
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_SERVER_CERT
|
||||
int
|
||||
default 2
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH
|
||||
int
|
||||
default 3
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT
|
||||
int
|
||||
default 4
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_SERVER_DER_CERT
|
||||
int
|
||||
default 5
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD
|
||||
int
|
||||
default 6
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT
|
||||
int
|
||||
default 7
|
||||
|
||||
config EXAMPLE_CONNECT_CASE_NO_CERT_ALPN
|
||||
int
|
||||
default 8
|
||||
|
||||
endmenu
|
||||
@@ -1,197 +0,0 @@
|
||||
/* MQTT connect test
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_console.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "publish_connect_test.h"
|
||||
|
||||
#if (!defined(CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT)) || \
|
||||
(!defined(CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN))
|
||||
#error "Some mandatory test case not defined!"
|
||||
#endif
|
||||
|
||||
extern const uint8_t ca_local_crt[] asm("_binary_ca_crt_start");
|
||||
extern const uint8_t ca_der_start[] asm("_binary_ca_der_start");
|
||||
extern const uint8_t ca_der_end[] asm("_binary_ca_der_end");
|
||||
extern const uint8_t client_pwd_crt[] asm("_binary_client_pwd_crt_start");
|
||||
extern const uint8_t client_pwd_key[] asm("_binary_client_pwd_key_start");
|
||||
extern const uint8_t client_inv_crt[] asm("_binary_client_inv_crt_start");
|
||||
extern const uint8_t client_no_pwd_key[] asm("_binary_client_no_pwd_key_start");
|
||||
|
||||
static const char *TAG = "connect_test";
|
||||
static int running_test_case = 0;
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
(void)handler_args;
|
||||
(void)base;
|
||||
(void)event_id;
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
ESP_LOGD(TAG, "Event: %d, Test case: %d", event->event_id, running_test_case);
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_BEFORE_CONNECT:
|
||||
break;
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED: Test=%d", running_test_case);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR: Test=%d", running_test_case);
|
||||
if (event->error_handle->error_type == MQTT_ERROR_TYPE_ESP_TLS) {
|
||||
ESP_LOGI(TAG, "ESP-TLS ERROR: %s", esp_err_to_name(event->error_handle->esp_tls_last_esp_err));
|
||||
} else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
|
||||
ESP_LOGI(TAG, "MQTT ERROR: 0x%x", event->error_handle->connect_return_code);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_no_certs(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
ESP_LOGI(TAG, "Runnning :CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT");
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_client_key_password(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)ca_local_crt,
|
||||
.credentials.authentication.certificate = (const char *)client_pwd_crt,
|
||||
.credentials.authentication.key = (const char *)client_pwd_key,
|
||||
.credentials.authentication.key_password = "esp32",
|
||||
.credentials.authentication.key_password_len = 5
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_server_der_cert(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)ca_der_start,
|
||||
.broker.verification.certificate_len = ca_der_end - ca_der_start,
|
||||
.credentials.authentication.certificate = "NULL",
|
||||
.credentials.authentication.key = "NULL"
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_wrong_server_cert(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)client_pwd_crt,
|
||||
.credentials.authentication.certificate = "NULL",
|
||||
.credentials.authentication.key = "NULL"
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_server_cert(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)ca_local_crt,
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_server_client_certs(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)ca_local_crt,
|
||||
.credentials.authentication.certificate = (const char *)client_pwd_crt,
|
||||
.credentials.authentication.key = (const char *)client_no_pwd_key
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_invalid_client_certs(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.certificate = (const char *)ca_local_crt,
|
||||
.credentials.authentication.certificate = (const char *)client_inv_crt,
|
||||
.credentials.authentication.key = (const char *)client_no_pwd_key
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
static void connect_with_alpn(esp_mqtt_client_handle_t client, const char *uri)
|
||||
{
|
||||
const char *alpn_protos[] = { "mymqtt", NULL };
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = uri,
|
||||
.broker.verification.alpn_protos = alpn_protos
|
||||
};
|
||||
esp_mqtt_set_config(client, &mqtt_cfg);
|
||||
}
|
||||
|
||||
void connect_setup(command_context_t * ctx) {
|
||||
esp_mqtt_client_register_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, ctx->data);
|
||||
}
|
||||
|
||||
void connect_teardown(command_context_t * ctx) {
|
||||
esp_mqtt_client_unregister_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler);
|
||||
}
|
||||
void connection_test(command_context_t * ctx, const char *uri, int test_case)
|
||||
{
|
||||
ESP_LOGI(TAG, "CASE:%d, connecting to %s", test_case, uri);
|
||||
running_test_case = test_case;
|
||||
switch (test_case) {
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT:
|
||||
connect_no_certs(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT:
|
||||
connect_with_server_cert(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH:
|
||||
connect_with_server_client_certs(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT:
|
||||
connect_with_wrong_server_cert(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT:
|
||||
connect_with_server_der_cert(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD:
|
||||
connect_with_client_key_password(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT:
|
||||
connect_with_invalid_client_certs(ctx->mqtt_client, uri);
|
||||
break;
|
||||
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN:
|
||||
connect_with_alpn(ctx->mqtt_client, uri);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unknown test case %d ", test_case);
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "Test case:%d started", test_case);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/mosquitto:
|
||||
version: ">=2.0.20"
|
||||
protocol_examples_common:
|
||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
||||
espressif/mqtt:
|
||||
version: "*"
|
||||
override_path: "../../../.."
|
||||
idf:
|
||||
version: ">=4.1.0"
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
|
||||
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
|
||||
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
|
||||
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
|
||||
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
|
||||
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
|
||||
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
|
||||
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
|
||||
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
|
||||
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
|
||||
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
|
||||
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
|
||||
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
|
||||
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
|
||||
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
|
||||
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
|
||||
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
|
||||
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
|
||||
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
|
||||
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
|
||||
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
|
||||
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
|
||||
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
|
||||
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
|
||||
nLRbwHOoq7hHwg==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,334 +0,0 @@
|
||||
/* MQTT publish-connect test
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "esp_system.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
#include "publish_connect_test.h"
|
||||
#include "mosq_broker.h"
|
||||
|
||||
static const char *TAG = "publish_connect_test";
|
||||
|
||||
command_context_t command_context;
|
||||
connection_args_t connection_args;
|
||||
publish_setup_args_t publish_setup_args;
|
||||
publish_args_t publish_args;
|
||||
|
||||
#define RETURN_ON_PARSE_ERROR(args) do { \
|
||||
int nerrors = arg_parse(argc, argv, (void **) &(args)); \
|
||||
if (nerrors != 0) { \
|
||||
arg_print_errors(stderr, (args).end, argv[0]); \
|
||||
return 1; \
|
||||
}} while(0)
|
||||
|
||||
|
||||
static int do_free_heap(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
ESP_LOGI(TAG, "Note free memory: %d bytes", esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_init(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.broker.address.uri = "mqtt://127.0.0.1:1234",
|
||||
.network.disable_auto_reconnect = true
|
||||
};
|
||||
command_context.mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
if(!command_context.mqtt_client) {
|
||||
ESP_LOGE(TAG, "Failed to initialize client");
|
||||
return 1;
|
||||
}
|
||||
publish_init_flags();
|
||||
ESP_LOGI(TAG, "Mqtt client initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_start(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if(esp_mqtt_client_start(command_context.mqtt_client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start mqtt client task");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Mqtt client started");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_stop(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if(esp_mqtt_client_stop(command_context.mqtt_client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to stop mqtt client task");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Mqtt client stopped");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_disconnect(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if(esp_mqtt_client_disconnect(command_context.mqtt_client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to request disconnection");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Mqtt client disconnected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_connect_setup(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
connect_setup(&command_context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_connect_teardown(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
connect_teardown(&command_context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_reconnect(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if(esp_mqtt_client_reconnect(command_context.mqtt_client) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to request reconnection");
|
||||
return 1;
|
||||
}
|
||||
ESP_LOGI(TAG, "Mqtt client will reconnect");
|
||||
return 0;
|
||||
;
|
||||
}
|
||||
|
||||
static int do_destroy(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
esp_mqtt_client_destroy(command_context.mqtt_client);
|
||||
command_context.mqtt_client = NULL;
|
||||
ESP_LOGI(TAG, "mqtt client for tests destroyed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_connect(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &connection_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, connection_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if(!command_context.mqtt_client) {
|
||||
ESP_LOGE(TAG, "MQTT client not initialized, call init first");
|
||||
return 1;
|
||||
}
|
||||
connection_test(&command_context, *connection_args.uri->sval, *connection_args.test_case->ival);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_publish_setup(int argc, char **argv) {
|
||||
RETURN_ON_PARSE_ERROR(publish_setup_args);
|
||||
if(command_context.data) {
|
||||
free(command_context.data);
|
||||
}
|
||||
command_context.data = calloc(1, sizeof(publish_context_t));
|
||||
((publish_context_t*)command_context.data)->pattern = strdup(*publish_setup_args.pattern->sval);
|
||||
((publish_context_t*)command_context.data)->pattern_repetitions = *publish_setup_args.pattern_repetitions->ival;
|
||||
((publish_context_t*)command_context.data)->subscribe_to = strdup(*publish_setup_args.subscribe_to->sval);
|
||||
((publish_context_t*)command_context.data)->publish_to = strdup(*publish_setup_args.publish_to->sval);
|
||||
publish_setup(&command_context, *publish_setup_args.transport->sval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_publish(int argc, char **argv) {
|
||||
RETURN_ON_PARSE_ERROR(publish_args);
|
||||
publish_test(&command_context, publish_args.expected_to_publish->ival[0], publish_args.qos->ival[0], publish_args.enqueue->ival[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_publish_report(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
publish_context_t * ctx = command_context.data;
|
||||
ESP_LOGI(TAG,"Test Report : Messages received %d, %d expected", ctx->nr_of_msg_received, ctx->nr_of_msg_expected);
|
||||
|
||||
return 0;
|
||||
}
|
||||
void register_common_commands(void) {
|
||||
const esp_console_cmd_t init = {
|
||||
.command = "init",
|
||||
.help = "Run inition test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_init,
|
||||
};
|
||||
|
||||
const esp_console_cmd_t start = {
|
||||
.command = "start",
|
||||
.help = "Run startion test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_start,
|
||||
};
|
||||
const esp_console_cmd_t stop = {
|
||||
.command = "stop",
|
||||
.help = "Run stopion test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_stop,
|
||||
};
|
||||
const esp_console_cmd_t destroy = {
|
||||
.command = "destroy",
|
||||
.help = "Run destroyion test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_destroy,
|
||||
};
|
||||
const esp_console_cmd_t free_heap = {
|
||||
.command = "free_heap",
|
||||
.help = "Run destroyion test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_free_heap,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&init));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&start));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&stop));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&destroy));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&free_heap));
|
||||
}
|
||||
void register_publish_commands(void) {
|
||||
publish_setup_args.transport = arg_str1(NULL,NULL,"<transport>", "Selected transport to test");
|
||||
publish_setup_args.publish_to = arg_str1(NULL,NULL,"<transport>", "Selected publish_to to publish");
|
||||
publish_setup_args.subscribe_to = arg_str1(NULL,NULL,"<transport>", "Selected subscribe_to to publish");
|
||||
publish_setup_args.pattern = arg_str1(NULL,NULL,"<pattern>", "Message pattern repeated to build big messages");
|
||||
publish_setup_args.pattern_repetitions = arg_int1(NULL,NULL,"<pattern repetitions>", "How many times the pattern is repeated");
|
||||
publish_setup_args.end = arg_end(1);
|
||||
|
||||
publish_args.expected_to_publish = arg_int1(NULL,NULL,"<number of messages>", "How many times the pattern is repeated");
|
||||
publish_args.qos = arg_int1(NULL,NULL,"<qos>", "How many times the pattern is repeated");
|
||||
publish_args.enqueue = arg_int1(NULL,NULL,"<enqueue>", "How many times the pattern is repeated");
|
||||
publish_args.end = arg_end(1);
|
||||
const esp_console_cmd_t publish_setup = {
|
||||
.command = "publish_setup",
|
||||
.help = "Set publish test parameters\n",
|
||||
.hint = NULL,
|
||||
.func = &do_publish_setup,
|
||||
.argtable = &publish_setup_args
|
||||
};
|
||||
|
||||
const esp_console_cmd_t publish = {
|
||||
.command = "publish",
|
||||
.help = "Run publish test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_publish,
|
||||
.argtable = &publish_args
|
||||
};
|
||||
const esp_console_cmd_t publish_report = {
|
||||
.command = "publish_report",
|
||||
.help = "Run destroyion test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_publish_report,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&publish_setup));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&publish));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&publish_report));
|
||||
}
|
||||
void register_connect_commands(void){
|
||||
connection_args.uri = arg_str1(NULL,NULL,"<broker uri>", "Broker address");
|
||||
connection_args.test_case = arg_int1(NULL, NULL, "<test case>","Selected test case");
|
||||
connection_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t connect = {
|
||||
.command = "connect",
|
||||
.help = "Run connection test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_connect,
|
||||
.argtable = &connection_args
|
||||
};
|
||||
|
||||
const esp_console_cmd_t reconnect = {
|
||||
.command = "reconnect",
|
||||
.help = "Run reconnection test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_reconnect,
|
||||
};
|
||||
const esp_console_cmd_t connection_setup = {
|
||||
.command = "connection_setup",
|
||||
.help = "Run reconnection test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_connect_setup,
|
||||
};
|
||||
const esp_console_cmd_t connection_teardown = {
|
||||
.command = "connection_teardown",
|
||||
.help = "Run reconnection test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_connect_teardown,
|
||||
};
|
||||
const esp_console_cmd_t disconnect = {
|
||||
.command = "disconnect",
|
||||
.help = "Run disconnection test\n",
|
||||
.hint = NULL,
|
||||
.func = &do_disconnect,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&connect));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&disconnect));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&reconnect));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&connection_setup));
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&connection_teardown));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_RUN_LOCAL_BROKER
|
||||
static void broker_task(void* ctx)
|
||||
{
|
||||
// broker continues to run in this task
|
||||
struct mosq_broker_config config = { .host = CONFIG_EXAMPLE_BROKER_HOST, .port = CONFIG_EXAMPLE_BROKER_PORT };
|
||||
mosq_broker_run(&config);
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_RUN_LOCAL_BROKER
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
static const size_t max_line = 256;
|
||||
|
||||
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
|
||||
ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
esp_log_level_set("wifi", ESP_LOG_ERROR);
|
||||
esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
|
||||
esp_log_level_set("outbox", ESP_LOG_VERBOSE);
|
||||
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
#ifdef CONFIG_EXAMPLE_RUN_LOCAL_BROKER
|
||||
xTaskCreate(broker_task, "broker", 8192, NULL, 4, NULL);
|
||||
#endif
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
repl_config.prompt = "mqtt>";
|
||||
repl_config.max_cmdline_length = max_line;
|
||||
esp_console_register_help_command();
|
||||
register_common_commands();
|
||||
register_connect_commands();
|
||||
register_publish_commands();
|
||||
|
||||
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "mqtt_client.h"
|
||||
|
||||
typedef enum {NONE, TCP, SSL, WS, WSS} transport_t;
|
||||
|
||||
typedef struct {
|
||||
esp_mqtt_client_handle_t mqtt_client;
|
||||
void * data;
|
||||
} command_context_t;
|
||||
|
||||
typedef struct {
|
||||
transport_t selected_transport;
|
||||
char *pattern;
|
||||
char *subscribe_to;
|
||||
char *publish_to;
|
||||
int pattern_repetitions;
|
||||
int qos;
|
||||
char *expected;
|
||||
size_t expected_size;
|
||||
size_t nr_of_msg_received;
|
||||
size_t nr_of_msg_expected;
|
||||
char * received_data;
|
||||
} publish_context_t ;
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *uri;
|
||||
struct arg_int *test_case;
|
||||
struct arg_end *end;
|
||||
} connection_args_t;
|
||||
|
||||
typedef struct {
|
||||
struct arg_int *expected_to_publish;
|
||||
struct arg_int *qos;
|
||||
struct arg_int *enqueue;
|
||||
struct arg_end *end;
|
||||
} publish_args_t;
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *transport;
|
||||
struct arg_str *subscribe_to;
|
||||
struct arg_str *publish_to;
|
||||
struct arg_str *pattern;
|
||||
struct arg_int *pattern_repetitions;
|
||||
struct arg_end *end;
|
||||
} publish_setup_args_t;
|
||||
|
||||
void publish_init_flags(void);
|
||||
void publish_setup(command_context_t * ctx, char const * transport);
|
||||
void publish_teardown(command_context_t * ctx);
|
||||
void publish_test(command_context_t * ctx, int expect_to_publish, int qos, bool enqueue);
|
||||
void connection_test(command_context_t * ctx, const char *uri, int test_case);
|
||||
void connect_setup(command_context_t * ctx);
|
||||
void connect_teardown(command_context_t * ctx);
|
||||
@@ -1,229 +0,0 @@
|
||||
/* MQTT publish test
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include <freertos/event_groups.h>
|
||||
#include "esp_system.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "publish_connect_test.h"
|
||||
|
||||
static const char *TAG = "publish_test";
|
||||
|
||||
static EventGroupHandle_t mqtt_event_group;
|
||||
const static int CONNECTED_BIT = BIT0;
|
||||
#define CLIENT_ID_SUFFIX_SIZE 12
|
||||
#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1
|
||||
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
|
||||
#else
|
||||
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
|
||||
#endif
|
||||
extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end");
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
publish_context_t * test_data = handler_args;
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
esp_mqtt_client_handle_t client = event->client;
|
||||
static int msg_id = 0;
|
||||
static int actual_len = 0;
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_BEFORE_CONNECT:
|
||||
break;
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);
|
||||
msg_id = esp_mqtt_client_subscribe(client, test_data->subscribe_to, test_data->qos);
|
||||
ESP_LOGI(TAG, "sent subscribe successful %s , msg_id=%d", test_data->subscribe_to, msg_id);
|
||||
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
|
||||
ESP_LOGI(TAG, "ID=%d, total_len=%d, data_len=%d, current_data_offset=%d", event->msg_id, event->total_data_len, event->data_len, event->current_data_offset);
|
||||
if (event->current_data_offset == 0) {
|
||||
actual_len = event->data_len;
|
||||
msg_id = event->msg_id;
|
||||
if (event->total_data_len != test_data->expected_size) {
|
||||
ESP_LOGE(TAG, "Incorrect message size: %d != %d", event->total_data_len, test_data->expected_size);
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
actual_len += event->data_len;
|
||||
// check consistency with msg_id across multiple data events for single msg
|
||||
if (msg_id != event->msg_id) {
|
||||
ESP_LOGE(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
if (event->current_data_offset + event->data_len > test_data->expected_size) {
|
||||
ESP_LOGE(TAG, "Buffer overflow detected: offset %d + data_len %d > buffer size %d", event->current_data_offset, event->data_len, test_data->expected_size);
|
||||
abort();
|
||||
}
|
||||
if (memcmp(test_data->expected + event->current_data_offset, event->data, event->data_len) != 0) {
|
||||
ESP_LOGE(TAG, "Data mismatch at offset %d: \n expected %.*s, \n got %.*s", event->current_data_offset, event->data_len, test_data->expected + event->current_data_offset, event->data_len, event->data);
|
||||
abort();
|
||||
}
|
||||
|
||||
memcpy(test_data->received_data + event->current_data_offset, event->data, event->data_len);
|
||||
if (actual_len == event->total_data_len) {
|
||||
if (0 == memcmp(test_data->received_data, test_data->expected, test_data->expected_size)) {
|
||||
memset(test_data->received_data, 0, test_data->expected_size);
|
||||
test_data->nr_of_msg_received++;
|
||||
if (test_data->nr_of_msg_received == test_data->nr_of_msg_expected) {
|
||||
ESP_LOGI(TAG, "Correct pattern received exactly x times");
|
||||
ESP_LOGI(TAG, "Test finished correctly!");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "FAILED!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGE(TAG, "MQTT_EVENT_ERROR");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void test_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
void pattern_setup(publish_context_t * test_data)
|
||||
{
|
||||
int pattern_size = strlen(test_data->pattern);
|
||||
free(test_data->expected);
|
||||
free(test_data->received_data);
|
||||
test_data->nr_of_msg_received = 0;
|
||||
test_data->expected_size = (size_t)(pattern_size) * test_data->pattern_repetitions;
|
||||
test_data->expected = malloc(test_data->expected_size);
|
||||
test_data->received_data = malloc(test_data->expected_size);
|
||||
for (int i = 0; i < test_data->pattern_repetitions; i++) {
|
||||
memcpy(test_data->expected + (ptrdiff_t)(i * pattern_size), test_data->pattern, pattern_size);
|
||||
}
|
||||
ESP_LOGI(TAG, "EXPECTED STRING %.*s, SIZE:%d", test_data->expected_size, test_data->expected, test_data->expected_size);
|
||||
}
|
||||
|
||||
static void configure_client(command_context_t * ctx, const char *transport)
|
||||
{
|
||||
publish_context_t * test_data = ctx->data;
|
||||
ESP_LOGI(TAG, "Configuration");
|
||||
transport_t selected_transport;
|
||||
if (0 == strcmp(transport, "tcp")) {
|
||||
selected_transport = TCP;
|
||||
} else if (0 == strcmp(transport, "ssl")) {
|
||||
selected_transport = SSL;
|
||||
} else if (0 == strcmp(transport, "ws")) {
|
||||
selected_transport = WS;
|
||||
} else if (0 == strcmp(transport, "wss")) {
|
||||
selected_transport = WSS;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unexpected transport %s", transport);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
if (selected_transport != test_data->selected_transport) {
|
||||
test_data->selected_transport = selected_transport;
|
||||
esp_mqtt_client_config_t config = {0};
|
||||
switch (selected_transport) {
|
||||
case NONE:
|
||||
break;
|
||||
case TCP:
|
||||
ESP_LOGI(TAG, "[TCP transport] Startup..");
|
||||
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_TCP_URI;
|
||||
break;
|
||||
case SSL:
|
||||
ESP_LOGI(TAG, "[SSL transport] Startup..");
|
||||
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_SSL_URI;
|
||||
break;
|
||||
case WS:
|
||||
ESP_LOGI(TAG, "[WS transport] Startup..");
|
||||
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_WS_URI;
|
||||
break;
|
||||
case WSS:
|
||||
ESP_LOGI(TAG, "[WSS transport] Startup..");
|
||||
config.broker.address.uri = CONFIG_EXAMPLE_BROKER_WSS_URI;
|
||||
break;
|
||||
}
|
||||
if (selected_transport == SSL || selected_transport == WSS) {
|
||||
ESP_LOGI(TAG, "Set certificate");
|
||||
config.broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start;
|
||||
}
|
||||
// Generate a random client id for each iteration
|
||||
char client_id[CLIENT_ID_SUFFIX_SIZE] = {0};
|
||||
snprintf(client_id, sizeof(client_id), "esp32-%08X", esp_random());
|
||||
config.credentials.client_id = client_id;
|
||||
esp_mqtt_set_config(ctx->mqtt_client, &config);
|
||||
}
|
||||
}
|
||||
|
||||
void publish_init_flags(void) {
|
||||
mqtt_event_group = xEventGroupCreate();
|
||||
}
|
||||
|
||||
void publish_setup(command_context_t * ctx, char const * const transport) {
|
||||
xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
|
||||
publish_context_t * data = (publish_context_t*)ctx->data;
|
||||
pattern_setup(data);
|
||||
configure_client(ctx, transport);
|
||||
esp_mqtt_client_register_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, data);
|
||||
}
|
||||
|
||||
void publish_teardown(command_context_t * ctx)
|
||||
{
|
||||
esp_mqtt_client_unregister_event(ctx->mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler);
|
||||
}
|
||||
|
||||
void publish_test(command_context_t * ctx, int expect_to_publish, int qos, bool enqueue)
|
||||
{
|
||||
publish_context_t * data = (publish_context_t*)ctx->data;
|
||||
data->nr_of_msg_expected = expect_to_publish;
|
||||
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d", data->pattern, data->pattern_repetitions, data->nr_of_msg_expected);
|
||||
|
||||
xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
for (int i = 0; i < data->nr_of_msg_expected; i++) {
|
||||
int msg_id;
|
||||
if (enqueue) {
|
||||
msg_id = esp_mqtt_client_enqueue(ctx->mqtt_client, data->publish_to, data->expected, data->expected_size, qos, 0, true);
|
||||
} else {
|
||||
msg_id = esp_mqtt_client_publish(ctx->mqtt_client, data->publish_to, data->expected, data->expected_size, qos, 0);
|
||||
if(msg_id < 0) {
|
||||
ESP_LOGE(TAG, "Failed to publish");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "Publishing msg_id=%d", msg_id);
|
||||
}
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import socketserver
|
||||
import ssl
|
||||
import subprocess
|
||||
from threading import Thread
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from common_test_methods import get_host_ip4_by_dest_ip
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
SERVER_PORT = 2222
|
||||
|
||||
|
||||
def _path(f): # type: (str) -> str
|
||||
return os.path.join(os.path.dirname(os.path.realpath(__file__)), f)
|
||||
|
||||
|
||||
def set_server_cert_cn(ip): # type: (str) -> None
|
||||
arg_list = [
|
||||
['openssl', 'req', '-out', _path('srv.csr'), '-key', _path('server.key'), '-subj', '/CN={}'.format(ip), '-new'],
|
||||
[
|
||||
'openssl',
|
||||
'x509',
|
||||
'-req',
|
||||
'-in',
|
||||
_path('srv.csr'),
|
||||
'-CA',
|
||||
_path('ca.crt'),
|
||||
'-CAkey',
|
||||
_path('ca.key'),
|
||||
'-CAcreateserial',
|
||||
'-out',
|
||||
_path('srv.crt'),
|
||||
'-days',
|
||||
'360',
|
||||
],
|
||||
]
|
||||
for args in arg_list:
|
||||
if subprocess.check_call(args) != 0:
|
||||
raise RuntimeError('openssl command {} failed'.format(args))
|
||||
|
||||
|
||||
class MQTTHandler(socketserver.StreamRequestHandler):
|
||||
def handle(self) -> None:
|
||||
logging.info(' - connection from: {}'.format(self.client_address))
|
||||
data = bytearray(self.request.recv(1024))
|
||||
message = ''.join(format(x, '02x') for x in data)
|
||||
if message[0:16] == '101800044d515454':
|
||||
if self.server.refuse_connection is False: # type: ignore
|
||||
logging.info(' - received mqtt connect, sending ACK')
|
||||
self.request.send(bytearray.fromhex('20020000'))
|
||||
else:
|
||||
# injecting connection not authorized error
|
||||
logging.info(' - received mqtt connect, sending NAK')
|
||||
self.request.send(bytearray.fromhex('20020005'))
|
||||
else:
|
||||
raise Exception(' - error process_mqtt_connect unexpected connect received: {}'.format(message))
|
||||
|
||||
|
||||
# Simple server for mqtt over TLS connection
|
||||
class TlsServer(socketserver.TCPServer):
|
||||
timeout = 30.0
|
||||
allow_reuse_address = True
|
||||
allow_reuse_port = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
port: int = SERVER_PORT,
|
||||
ServerHandler: Callable[[Any, Any, Any], socketserver.BaseRequestHandler] = MQTTHandler,
|
||||
client_cert: bool = False,
|
||||
refuse_connection: bool = False,
|
||||
use_alpn: bool = False,
|
||||
):
|
||||
self.refuse_connection = refuse_connection
|
||||
self.context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
self.ssl_error = ''
|
||||
self.alpn_protocol: Optional[str] = None
|
||||
if client_cert:
|
||||
self.context.verify_mode = ssl.CERT_REQUIRED
|
||||
self.context.load_verify_locations(cafile=_path('ca.crt'))
|
||||
self.context.load_cert_chain(certfile=_path('srv.crt'), keyfile=_path('server.key'))
|
||||
if use_alpn:
|
||||
self.context.set_alpn_protocols(['mymqtt', 'http/1.1'])
|
||||
self.server_thread = Thread(target=self.serve_forever)
|
||||
super().__init__(('', port), ServerHandler)
|
||||
|
||||
def server_activate(self) -> None:
|
||||
self.socket = self.context.wrap_socket(self.socket, server_side=True)
|
||||
super().server_activate()
|
||||
|
||||
def __enter__(self): # type: ignore
|
||||
self.server_thread.start()
|
||||
return self
|
||||
|
||||
def server_close(self) -> None:
|
||||
try:
|
||||
self.shutdown()
|
||||
self.server_thread.join()
|
||||
super().server_close()
|
||||
except RuntimeError as e:
|
||||
logging.exception(e)
|
||||
|
||||
# We need to override it here to capture ssl.SSLError
|
||||
# The implementation is a slightly modified version from cpython original code.
|
||||
def _handle_request_noblock(self) -> None:
|
||||
try:
|
||||
request, client_address = self.get_request()
|
||||
self.alpn_protocol = request.selected_alpn_protocol() # type: ignore
|
||||
except ssl.SSLError as e:
|
||||
self.ssl_error = e.reason
|
||||
return
|
||||
except OSError:
|
||||
return
|
||||
if self.verify_request(request, client_address):
|
||||
try:
|
||||
self.process_request(request, client_address)
|
||||
except Exception:
|
||||
self.handle_error(request, client_address)
|
||||
self.shutdown_request(request)
|
||||
except: # noqa: E722
|
||||
self.shutdown_request(request)
|
||||
raise
|
||||
else:
|
||||
self.shutdown_request(request)
|
||||
|
||||
def last_ssl_error(self): # type: (TlsServer) -> str
|
||||
return self.ssl_error
|
||||
|
||||
def get_negotiated_protocol(self) -> Optional[str]:
|
||||
return self.alpn_protocol
|
||||
|
||||
|
||||
def get_test_cases(dut: Dut) -> Any:
|
||||
cases = {}
|
||||
try:
|
||||
# Get connection test cases configuration: symbolic names for test cases
|
||||
for case in [
|
||||
'EXAMPLE_CONNECT_CASE_NO_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_SERVER_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH',
|
||||
'EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD',
|
||||
'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT',
|
||||
'EXAMPLE_CONNECT_CASE_NO_CERT_ALPN',
|
||||
]:
|
||||
cases[case] = dut.app.sdkconfig.get(case)
|
||||
except Exception:
|
||||
logging.error('ENV_TEST_FAILURE: Some mandatory CONNECTION test case not found in sdkconfig')
|
||||
raise
|
||||
return cases
|
||||
|
||||
|
||||
def get_dut_ip(dut: Dut) -> Any:
|
||||
dut_ip = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30).group(1).decode()
|
||||
logging.info('Got IP={}'.format(dut_ip))
|
||||
return get_host_ip4_by_dest_ip(dut_ip)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def connect_dut(dut: Dut, uri: str, case_id: int) -> Any:
|
||||
dut.write('connection_setup')
|
||||
dut.write(f'connect {uri} {case_id}')
|
||||
dut.expect(f'Test case:{case_id} started')
|
||||
dut.write('reconnect')
|
||||
yield
|
||||
dut.write('connection_teardown')
|
||||
dut.write('disconnect')
|
||||
|
||||
|
||||
def run_cases(dut: Dut, uri: str, cases: Dict[str, int]) -> None:
|
||||
try:
|
||||
dut.write('init')
|
||||
dut.write(f'start')
|
||||
dut.write(f'disconnect')
|
||||
for case in [
|
||||
'EXAMPLE_CONNECT_CASE_NO_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_SERVER_CERT',
|
||||
'EXAMPLE_CONNECT_CASE_SERVER_DER_CERT',
|
||||
]:
|
||||
# All these cases connect to the server with no server verification or with server only verification
|
||||
with TlsServer(), connect_dut(dut, uri, cases[case]):
|
||||
logging.info(f'Running {case}: default server - expect to connect normally')
|
||||
dut.expect(f'MQTT_EVENT_CONNECTED: Test={cases[case]}', timeout=30)
|
||||
with TlsServer(refuse_connection=True), connect_dut(dut, uri, cases[case]):
|
||||
logging.info(f'Running {case}: ssl shall connect, but mqtt sends connect refusal')
|
||||
dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30)
|
||||
dut.expect('MQTT ERROR: 0x5') # expecting 0x5 ... connection not authorized error
|
||||
with TlsServer(client_cert=True) as server, connect_dut(dut, uri, cases[case]):
|
||||
logging.info(
|
||||
f'Running {case}: server with client verification - handshake error since client presents no client certificate'
|
||||
)
|
||||
dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30)
|
||||
dut.expect(
|
||||
'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED'
|
||||
) # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE)
|
||||
assert 'PEER_DID_NOT_RETURN_A_CERTIFICATE' in server.last_ssl_error()
|
||||
|
||||
for case in ['EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD']:
|
||||
# These cases connect to server with both server and client verification (client key might be password protected)
|
||||
with TlsServer(client_cert=True), connect_dut(dut, uri, cases[case]):
|
||||
logging.info(f'Running {case}: server with client verification - expect to connect normally')
|
||||
dut.expect(f'MQTT_EVENT_CONNECTED: Test={cases[case]}', timeout=30)
|
||||
|
||||
case = 'EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT'
|
||||
with TlsServer() as s, connect_dut(dut, uri, cases[case]):
|
||||
logging.info(f'Running {case}: invalid server certificate on default server - expect ssl handshake error')
|
||||
dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30)
|
||||
dut.expect(
|
||||
'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED'
|
||||
) # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA)
|
||||
if re.match('.*alert.*unknown.*ca', s.last_ssl_error(), flags=re.I) is None:
|
||||
raise Exception(f'Unexpected ssl error from the server: {s.last_ssl_error()}')
|
||||
|
||||
case = 'EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT'
|
||||
with TlsServer(client_cert=True) as s, connect_dut(dut, uri, cases[case]):
|
||||
logging.info(
|
||||
f'Running {case}: Invalid client certificate on server with client verification - expect ssl handshake error'
|
||||
)
|
||||
dut.expect(f'MQTT_EVENT_ERROR: Test={cases[case]}', timeout=30)
|
||||
dut.expect(
|
||||
'ESP-TLS ERROR: ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED'
|
||||
) # expect ... handshake error (CERTIFICATE_VERIFY_FAILED)
|
||||
if 'CERTIFICATE_VERIFY_FAILED' not in s.last_ssl_error():
|
||||
raise Exception('Unexpected ssl error from the server {}'.format(s.last_ssl_error()))
|
||||
|
||||
for case in ['EXAMPLE_CONNECT_CASE_NO_CERT', 'EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']:
|
||||
with TlsServer(use_alpn=True) as s, connect_dut(dut, uri, cases[case]):
|
||||
logging.info(f'Running {case}: server with alpn - expect connect, check resolved protocol')
|
||||
dut.expect(f'MQTT_EVENT_CONNECTED: Test={cases[case]}', timeout=30)
|
||||
if case == 'EXAMPLE_CONNECT_CASE_NO_CERT':
|
||||
assert s.get_negotiated_protocol() is None
|
||||
elif case == 'EXAMPLE_CONNECT_CASE_NO_CERT_ALPN':
|
||||
assert s.get_negotiated_protocol() == 'mymqtt'
|
||||
else:
|
||||
assert False, f'Unexpected negotiated protocol {s.get_negotiated_protocol()}'
|
||||
finally:
|
||||
dut.write('stop')
|
||||
dut.write('destroy')
|
||||
|
||||
|
||||
@pytest.mark.ethernet
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_mqtt_connect(
|
||||
dut: Dut,
|
||||
log_performance: Callable[[str, object], None],
|
||||
) -> None:
|
||||
"""
|
||||
steps:
|
||||
1. join AP
|
||||
2. connect to uri specified in the config
|
||||
3. send and receive data
|
||||
"""
|
||||
# check and log bin size
|
||||
binary_file = os.path.join(dut.app.binary_path, 'mqtt_publish_connect_test.bin')
|
||||
bin_size = os.path.getsize(binary_file)
|
||||
log_performance('mqtt_publish_connect_test_bin_size', f'{bin_size // 1024} KB')
|
||||
|
||||
ip = get_dut_ip(dut)
|
||||
set_server_cert_cn(ip)
|
||||
uri = f'mqtts://{ip}:{SERVER_PORT}'
|
||||
|
||||
# Look for test case symbolic names and publish configs
|
||||
cases = get_test_cases(dut)
|
||||
dut.expect_exact('mqtt>', timeout=30)
|
||||
run_cases(dut, uri, cases)
|
||||
@@ -1,335 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import contextlib
|
||||
import difflib
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import ssl
|
||||
import string
|
||||
import time
|
||||
from itertools import count
|
||||
from itertools import product
|
||||
from threading import Event
|
||||
from threading import Lock
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Tuple
|
||||
from typing import no_type_check
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import pexpect
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
DEFAULT_MSG_SIZE = 16
|
||||
|
||||
|
||||
# Publisher class creating a python client to send/receive published data from esp-mqtt client
|
||||
class MqttPublisher(mqtt.Client):
|
||||
def __init__(self, config, log_details=False): # type: (MqttPublisher, dict, bool) -> None
|
||||
self.log_details = log_details
|
||||
self.config = config
|
||||
self.expected_data = f'{config["pattern"] * config["scenario"]["msg_len"]}'
|
||||
self.received = 0
|
||||
self.subscribe_mid = 0
|
||||
self.lock = Lock()
|
||||
self.event_client_connected = Event()
|
||||
self.event_client_subscribed = Event()
|
||||
self.event_client_got_all = Event()
|
||||
transport = 'websockets' if self.config['transport'] in ['ws', 'wss'] else 'tcp'
|
||||
client_id = 'MqttTestRunner' + ''.join(
|
||||
random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(5)
|
||||
)
|
||||
super().__init__(client_id, userdata=0, transport=transport)
|
||||
|
||||
def print_details(self, text): # type: (str) -> None
|
||||
if self.log_details:
|
||||
logging.info(text)
|
||||
|
||||
def on_subscribe(self, client: Any, userdata: Any, mid: Any, granted_qos: Any) -> None:
|
||||
"""Verify successful subscription."""
|
||||
if mid == self.subscribe_mid:
|
||||
logging.info(f'Subscribed to {self.config["subscribe_topic"]} successfully with QoS: {granted_qos}')
|
||||
self.event_client_subscribed.set()
|
||||
|
||||
def on_connect(self, mqttc: Any, obj: Any, flags: Any, rc: int) -> None:
|
||||
self.event_client_connected.set()
|
||||
|
||||
def on_connect_fail(self, mqttc: Any, obj: Any) -> None:
|
||||
logging.error('Connect failed')
|
||||
|
||||
def on_message(self, mqttc: mqtt.Client, obj: Any, msg: mqtt.MQTTMessage) -> None:
|
||||
payload = msg.payload.decode('utf-8')
|
||||
if payload == self.expected_data:
|
||||
self.received += 1
|
||||
if self.received == self.config['scenario']['nr_of_msgs']:
|
||||
self.event_client_got_all.set()
|
||||
else:
|
||||
differences = len(list(filter(lambda data: data[0] != data[1], zip(payload, self.expected_data))))
|
||||
logging.error(
|
||||
f'Payload on topic "{msg.topic}" (QoS {msg.qos}) differs in {differences} positions '
|
||||
'from expected data. '
|
||||
f'Received size: {len(payload)}, expected size: {len(self.expected_data)}.'
|
||||
)
|
||||
logging.info(f'Repetitions: {payload.count(self.config["pattern"])}')
|
||||
logging.info(f'Pattern: {self.config["pattern"]}')
|
||||
logging.info(f'First: {payload[:DEFAULT_MSG_SIZE]}')
|
||||
logging.info(f'Last: {payload[-DEFAULT_MSG_SIZE:]}')
|
||||
matcher = difflib.SequenceMatcher(a=payload, b=self.expected_data)
|
||||
for match in matcher.get_matching_blocks():
|
||||
logging.info(f'Match: {match}')
|
||||
|
||||
def __enter__(self) -> Any:
|
||||
qos = self.config['qos']
|
||||
broker_host = self.config['broker_host_' + self.config['transport']]
|
||||
broker_port = self.config['broker_port_' + self.config['transport']]
|
||||
connect_timeout_seconds = self.config.get('client_connect_timeout', 30)
|
||||
|
||||
try:
|
||||
self.print_details('Connecting...')
|
||||
if self.config['transport'] in ['ssl', 'wss']:
|
||||
self.tls_set(None, None, None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
|
||||
self.tls_insecure_set(True)
|
||||
self.event_client_connected.clear()
|
||||
self.loop_start()
|
||||
self.connect(broker_host, broker_port, 60) # paho's keepalive
|
||||
except Exception:
|
||||
self.print_details(f'ENV_TEST_FAILURE: Unexpected error while connecting to broker {broker_host}')
|
||||
raise
|
||||
self.print_details(f'Connecting py-client to broker {broker_host}:{broker_port}...')
|
||||
|
||||
if not self.event_client_connected.wait(timeout=connect_timeout_seconds):
|
||||
raise ValueError(
|
||||
f'ENV_TEST_FAILURE: Test script cannot connect to broker: {broker_host} '
|
||||
f'within {connect_timeout_seconds}s'
|
||||
)
|
||||
self.event_client_got_all.clear()
|
||||
result, self.subscribe_mid = self.subscribe(self.config['subscribe_topic'], qos)
|
||||
assert result == 0
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback): # type: (MqttPublisher, str, str, dict) -> None
|
||||
self.disconnect()
|
||||
self.loop_stop()
|
||||
|
||||
|
||||
def get_configurations(dut: Dut, test_case: Any) -> Dict[str, Any]:
|
||||
publish_cfg = {}
|
||||
try:
|
||||
|
||||
@no_type_check
|
||||
def get_config_from_dut(dut, config_option):
|
||||
# logging.info('Option:', config_option, dut.app.sdkconfig.get(config_option))
|
||||
value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut.app.sdkconfig.get(config_option))
|
||||
if value is None:
|
||||
return None, None
|
||||
return value.group(1), int(value.group(2))
|
||||
|
||||
# Get publish test configuration
|
||||
publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_config_from_dut(
|
||||
dut, 'EXAMPLE_BROKER_SSL_URI'
|
||||
)
|
||||
publish_cfg['broker_host_tcp'], publish_cfg['broker_port_tcp'] = get_config_from_dut(
|
||||
dut, 'EXAMPLE_BROKER_TCP_URI'
|
||||
)
|
||||
publish_cfg['broker_host_ws'], publish_cfg['broker_port_ws'] = get_config_from_dut(dut, 'EXAMPLE_BROKER_WS_URI')
|
||||
publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_config_from_dut(
|
||||
dut, 'EXAMPLE_BROKER_WSS_URI'
|
||||
)
|
||||
|
||||
except Exception:
|
||||
logging.info('ENV_TEST_FAILURE: Some mandatory PUBLISH test case not found in sdkconfig')
|
||||
raise
|
||||
transport, qos, enqueue, scenario = test_case
|
||||
if publish_cfg['broker_host_' + transport] is None:
|
||||
pytest.skip(f'Skipping transport: {transport}...')
|
||||
publish_cfg['scenario'] = scenario
|
||||
publish_cfg['qos'] = qos
|
||||
publish_cfg['enqueue'] = enqueue
|
||||
publish_cfg['transport'] = transport
|
||||
publish_cfg['pattern'] = ''.join(
|
||||
random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(DEFAULT_MSG_SIZE)
|
||||
)
|
||||
publish_cfg['client_connect_timeout'] = 30
|
||||
publish_cfg['dut_subscribe_timeout'] = 60
|
||||
publish_cfg['publish_ack_timeout'] = 60
|
||||
publish_cfg['test_timeout'] = get_timeout(test_case)
|
||||
|
||||
unique_topic = ''.join(
|
||||
random.choice(string.ascii_uppercase + string.ascii_lowercase) for _ in range(DEFAULT_MSG_SIZE)
|
||||
)
|
||||
publish_cfg['subscribe_topic'] = 'test/subscribe_to/' + unique_topic
|
||||
publish_cfg['publish_topic'] = 'test/subscribe_to/' + unique_topic
|
||||
logging.info(f'configuration: {publish_cfg}')
|
||||
return publish_cfg
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def connected_and_subscribed(dut: Dut, config: Dict[str, Any]) -> Any:
|
||||
dut.write('start')
|
||||
dut_subscribe_timeout = config.get('dut_subscribe_timeout', 60)
|
||||
dut.expect(re.compile(rb'MQTT_EVENT_SUBSCRIBED'), timeout=dut_subscribe_timeout)
|
||||
yield
|
||||
dut.write('stop')
|
||||
|
||||
|
||||
def get_scenarios() -> List[Dict[str, int]]:
|
||||
scenarios = []
|
||||
# Initialize message sizes and repeat counts (if defined in the environment)
|
||||
for i in count(0):
|
||||
# Check env variable: MQTT_PUBLISH_MSG_{len|repeat}_{x}
|
||||
env_dict = {var: 'MQTT_PUBLISH_MSG_' + var + '_' + str(i) for var in ['len', 'repeat']}
|
||||
if os.getenv(env_dict['len']) and os.getenv(env_dict['repeat']):
|
||||
scenarios.append({var: int(os.getenv(env_dict[var])) for var in ['len', 'repeat']}) # type: ignore
|
||||
continue
|
||||
break
|
||||
if not scenarios: # No message sizes present in the env - set defaults
|
||||
logging.info('Using predefined cases')
|
||||
scenarios = [
|
||||
{'msg_len': 0, 'nr_of_msgs': 5}, # zero-sized messages
|
||||
{'msg_len': 2, 'nr_of_msgs': 5}, # short messages
|
||||
{'msg_len': 200, 'nr_of_msgs': 3}, # long messages
|
||||
]
|
||||
return scenarios
|
||||
|
||||
|
||||
def get_timeout(test_case: Any) -> int:
|
||||
transport, qos, enqueue, scenario = test_case
|
||||
timeout = int(scenario['nr_of_msgs'] * 20)
|
||||
if qos == 1:
|
||||
timeout += 30
|
||||
if qos == 2:
|
||||
timeout += 45
|
||||
if transport in ['ws', 'wss']:
|
||||
timeout += 30
|
||||
return timeout
|
||||
|
||||
|
||||
def run_publish_test_case(dut: Dut, config: Any) -> None:
|
||||
logging.info(
|
||||
f'Starting Publish test: transport:{config["transport"]}, qos:{config["qos"]},'
|
||||
f'nr_of_msgs:{config["scenario"]["nr_of_msgs"]},'
|
||||
f' msg_size:{config["scenario"]["msg_len"]}, enqueue:{config["enqueue"]}'
|
||||
)
|
||||
dut.write(
|
||||
f'publish_setup {config["transport"]} {config["publish_topic"]}'
|
||||
f' {config["subscribe_topic"]} {config["pattern"]} {config["scenario"]["msg_len"]}'
|
||||
)
|
||||
with MqttPublisher(config) as publisher, connected_and_subscribed(dut, config):
|
||||
py_client_subscribe_timeout = config.get('py_client_subscribe_timeout', config['test_timeout'])
|
||||
assert publisher.event_client_subscribed.wait(timeout=py_client_subscribe_timeout), 'Runner failed to subscribe'
|
||||
msgs_published: List[mqtt.MQTTMessageInfo] = []
|
||||
dut.write(f'publish {config["scenario"]["nr_of_msgs"]} {config["qos"]} {config["enqueue"]}')
|
||||
assert publisher.event_client_got_all.wait(timeout=config['test_timeout']), (
|
||||
f'Not all data received from ESP32: {config["transport"]} '
|
||||
f'qos={config["qos"]} received: {publisher.received} '
|
||||
f'expected: {config["scenario"]["nr_of_msgs"]}'
|
||||
)
|
||||
logging.info(' - all data received from ESP32')
|
||||
payload = config['pattern'] * config['scenario']['msg_len']
|
||||
for _ in range(config['scenario']['nr_of_msgs']):
|
||||
with publisher.lock:
|
||||
msg = publisher.publish(topic=config['publish_topic'], payload=payload, qos=config['qos'])
|
||||
if config['qos'] > 0:
|
||||
msgs_published.append(msg)
|
||||
logging.info(f'Published: {len(msgs_published)} messages from script with QoS > 0 needing ACK.')
|
||||
|
||||
if msgs_published:
|
||||
publish_ack_timeout_seconds = config.get('publish_ack_timeout', 60) # Default 60s, make configurable
|
||||
ack_wait_start_time = time.time()
|
||||
initial_unacked_count = len(msgs_published)
|
||||
logging.info(f'Waiting {initial_unacked_count} publish ack with timeout {publish_ack_timeout_seconds}s...')
|
||||
|
||||
while msgs_published:
|
||||
if time.time() - ack_wait_start_time > publish_ack_timeout_seconds:
|
||||
unacked_mids = [msg.mid for msg in msgs_published if msg.mid is not None and not msg.is_published()]
|
||||
logging.error(
|
||||
f'Timeout waiting for publish acknowledgements. '
|
||||
f'{len(unacked_mids)} of {initial_unacked_count} messages remain unacknowledged. '
|
||||
f'Unacked MIDs: {unacked_mids}'
|
||||
)
|
||||
# This will likely cause the test to fail at a later assertion,
|
||||
# or you could raise an explicit error here.
|
||||
# e.g. raise Exception('Timeout waiting for publish acknowledgements')
|
||||
break
|
||||
msgs_published = [msg for msg in msgs_published if not msg.is_published()]
|
||||
if msgs_published: # Avoid busy-looping if list is not empty
|
||||
time.sleep(0.1) # Brief pause
|
||||
if not msgs_published:
|
||||
logging.info('All script-published QoS > 0 messages acknowledged by broker.')
|
||||
|
||||
logging.info('All messages from runner published (or timed out waiting for ACK).')
|
||||
|
||||
try:
|
||||
dut.expect(re.compile(rb'Correct pattern received exactly x times'), timeout=config['test_timeout'])
|
||||
except pexpect.exceptions.ExceptionPexpect:
|
||||
dut.write('publish_report')
|
||||
dut.expect(re.compile(rb'Test Report'), timeout=30)
|
||||
raise
|
||||
logging.info('ESP32 received all data from runner')
|
||||
|
||||
|
||||
stress_scenarios = [{'msg_len': 20, 'nr_of_msgs': 30}] # many medium sized
|
||||
transport_cases = ['tcp', 'ws', 'wss', 'ssl']
|
||||
qos_cases = [0, 1, 2]
|
||||
enqueue_cases = [0, 1]
|
||||
local_broker_supported_transports = ['tcp']
|
||||
local_broker_scenarios = [
|
||||
{'msg_len': 0, 'nr_of_msgs': 5}, # zero-sized messages
|
||||
{'msg_len': 5, 'nr_of_msgs': 20}, # short messages
|
||||
{'msg_len': 500, 'nr_of_msgs': 10}, # long messages
|
||||
{'msg_len': 20, 'nr_of_msgs': 20},
|
||||
] # many medium sized
|
||||
|
||||
|
||||
def make_cases(transport: Any, scenarios: List[Dict[str, int]]) -> List[Tuple[str, int, int, Dict[str, int]]]:
|
||||
return [test_case for test_case in product(transport, qos_cases, enqueue_cases, scenarios)]
|
||||
|
||||
|
||||
test_cases = make_cases(transport_cases, get_scenarios())
|
||||
stress_test_cases = make_cases(transport_cases, stress_scenarios)
|
||||
|
||||
|
||||
@pytest.mark.ethernet
|
||||
@pytest.mark.parametrize('test_case', test_cases)
|
||||
@pytest.mark.parametrize('config', ['default'], indirect=True)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
@pytest.mark.flaky(reruns=1, reruns_delay=1)
|
||||
def test_mqtt_publish(dut: Dut, test_case: Any) -> None:
|
||||
publish_cfg = get_configurations(dut, test_case)
|
||||
dut.expect(re.compile(rb'mqtt>'), timeout=30)
|
||||
dut.confirm_write('init', expect_pattern='init', timeout=30)
|
||||
run_publish_test_case(dut, publish_cfg)
|
||||
|
||||
|
||||
@pytest.mark.ethernet_stress
|
||||
@pytest.mark.nightly_run
|
||||
@pytest.mark.parametrize('test_case', stress_test_cases)
|
||||
@pytest.mark.parametrize('config', ['default'], indirect=True)
|
||||
@pytest.mark.flaky(reruns=1, reruns_delay=1)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_mqtt_publish_stress(dut: Dut, test_case: Any) -> None:
|
||||
publish_cfg = get_configurations(dut, test_case)
|
||||
dut.expect(re.compile(rb'mqtt>'), timeout=30)
|
||||
dut.write('init')
|
||||
run_publish_test_case(dut, publish_cfg)
|
||||
|
||||
|
||||
@pytest.mark.ethernet
|
||||
@pytest.mark.parametrize('test_case', make_cases(local_broker_supported_transports, local_broker_scenarios))
|
||||
@pytest.mark.parametrize('config', ['local_broker'], indirect=True)
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_mqtt_publish_local(dut: Dut, test_case: Any) -> None:
|
||||
if test_case[0] not in local_broker_supported_transports:
|
||||
pytest.skip(f'Skipping transport: {test_case[0]}...')
|
||||
dut_ip = dut.expect(r'esp_netif_handlers: .+ ip: (\d+\.\d+\.\d+\.\d+),').group(1)
|
||||
publish_cfg = get_configurations(dut, test_case)
|
||||
publish_cfg['broker_host_tcp'] = dut_ip
|
||||
publish_cfg['broker_port_tcp'] = 1234
|
||||
dut.expect(re.compile(rb'mqtt>'), timeout=30)
|
||||
dut.confirm_write('init', expect_pattern='init', timeout=30)
|
||||
run_publish_test_case(dut, publish_cfg)
|
||||
@@ -1,20 +0,0 @@
|
||||
CONFIG_EXAMPLE_BROKER_SSL_URI="mqtts://${EXAMPLE_MQTT_BROKER_SSL}"
|
||||
CONFIG_EXAMPLE_BROKER_TCP_URI="mqtt://${EXAMPLE_MQTT_BROKER_TCP}"
|
||||
CONFIG_EXAMPLE_BROKER_WS_URI="ws://${EXAMPLE_MQTT_BROKER_WS}/ws"
|
||||
CONFIG_EXAMPLE_BROKER_WSS_URI="wss://${EXAMPLE_MQTT_BROKER_WSS}/ws"
|
||||
CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE="${EXAMPLE_MQTT_BROKER_CERTIFICATE}"
|
||||
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
|
||||
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
|
||||
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=16384
|
||||
CONFIG_ESP_TLS_INSECURE=y
|
||||
CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS=y
|
||||
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||
@@ -1,13 +0,0 @@
|
||||
CONFIG_EXAMPLE_BROKER_SSL_URI=""
|
||||
CONFIG_EXAMPLE_BROKER_TCP_URI="mqtt://127.0.0.1:1234"
|
||||
CONFIG_EXAMPLE_BROKER_WS_URI=""
|
||||
CONFIG_EXAMPLE_BROKER_WSS_URI=""
|
||||
CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE=""
|
||||
CONFIG_ESP_TLS_INSECURE=y
|
||||
CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y
|
||||
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||
CONFIG_MQTT_USE_CUSTOM_CONFIG=y
|
||||
CONFIG_MQTT_POLL_READ_TIMEOUT_MS=50
|
||||
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
|
||||
CONFIG_EXAMPLE_RUN_LOCAL_BROKER=y
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAlUCywNhVv4RO2y9h/XGKZ1azzk3jzHpSBzIGO9LoiA8trC/p
|
||||
1ykGaUfYPJllYK4HMhC4fUyE3J7tVL2Eskzl26LNPLbEoaBWZM9NhV3iA1/1EtOu
|
||||
p6umLx+y3sDfvK35YAOUbjdAlBfhnJ4r8h7oTsxl3J5jZ18zgjJnJi2NEFq/yTpO
|
||||
MiwHLWPjy25fDFixfV9UzSvbgt1JaGPmC7c4QkhHzjyp0+ikuvRIw0p9BBNeqBV2
|
||||
da3qBMB5FtodUJTAz6o6OKWbTalLjQi6C1H6z9TnY7IrJBUOy/FWkQH/sEsLdscD
|
||||
hHa1Dz2oT203QjhzyOSfnNF95D/1MdNcMt6l0wIDAQABAoIBAC1JJTOoMFRc48RT
|
||||
myrYQYNbZlEphv3q+2qdfhC2zMFDwbrmCtCy7PQSzYSNkpoEE8DYG/JAvmtmeWJl
|
||||
4pZrCK9ctWM/nWfhC3WpBL97nfEiM20T94F+bn0L5Cz8XqaULv839th+QUTt/hGU
|
||||
WIctY5VNJXcMQ+MAmtNdUbjex1d3iuxiKHUo4nDoZ8digKFNdtdP5B5nlMq5chCL
|
||||
mxNRcsGsx2dDAxbGUapdTVPWHPJKpLOBoSkluDsfd2KZADFU2R1SJpAX9+RYh3HM
|
||||
5FTUdHTUaISxbKkgeDKlEM0lqk2TtGUwCyEj098ewi7Wzsu9w60IplPPUJx5FRG6
|
||||
jp3wzLkCgYEAxKp5T20rf/7ysX7x053I7VCjDXUxAaWOEj1uS3AhOkl0NaZg7Di+
|
||||
y53fWNkcHdkt2n2LqMt/43UgMYq3TVVcq2eunPNF11e1bJw8CjDafwDs4omwwyVn
|
||||
lYhPuB4dK2OAib+vU5Zqpp0kZMoxk2MZVgon8z+s8DW/zmB6aFqAWeUCgYEAwkhC
|
||||
OgmXKMdjOCVy5t2f5UbY8Y9rV3w8eUATuJ47MMwLr4pGYnKoEn9JB4ltWrHv/u5S
|
||||
fOv3tIrrCEvnCoCbOILwCsY5LqTNXgqova8FB6RpMUQCzhDd8LHuvdHv0WMnMzX1
|
||||
3PKuqwh8JS55m4WqZRhzr5BFKG4fHPVs4IcaJVcCgYAzzCaJSdqUKqTnJOUydDNQ
|
||||
ddWMHNqccWs62J0tF0pZHLGT089hSAzQejMyJnSmU+Ykzr4y5e44DUg+ZCelIZ93
|
||||
saYmxlgVwI8THQ8fLADQRIEfpV4996MRmkZM2vmZzOo03Zyi6lIKsga82Rg3lnk8
|
||||
1Q3ynknBNpbfF0AGLhfyFQKBgBYlxJ73HutAJ5hr9HhLBYJOnEaVUehMOlycKGNg
|
||||
bmD2sdJWEgYBChXpurqIORYguLo4EuE4ySkkuPxeIr14wbkkfBbOWBBwKxUwY+IT
|
||||
xKAFZxR9q1AwbgyVTCEJgKw/AGX/HcMNS0omEnjunmBTUYRq0C1QZgHg490aQUor
|
||||
PJjLAoGAevzdTpFlVeuKeYh1oDubGO1LinyXpBv7fPFjl+zu4AVbjojcU6yC4OO6
|
||||
QvqopE6SyAECKy8kAOFcESPsGc9Lta2XUvI203z7pIVlNVEcJ0+90mQh3Mn1U46l
|
||||
sZ49PdRvNwNb5wvkh1UqNsMlGFbRlzMbIk45ou4311kCobowZek=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,17 +0,0 @@
|
||||
# The following four lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
list(APPEND EXTRA_COMPONENT_DIRS
|
||||
"$ENV{IDF_PATH}/tools/mocks/esp_hw_support/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/freertos/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/esp_timer/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/esp_event/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/lwip/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/esp-tls/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/http_parser/"
|
||||
"$ENV{IDF_PATH}/tools/mocks/tcp_transport/")
|
||||
|
||||
project(host_mqtt_client_test)
|
||||
@@ -1,30 +0,0 @@
|
||||
| Supported Targets | Linux |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Description
|
||||
|
||||
This directory contains test code for the mqtt client that runs on host.
|
||||
|
||||
Tests are written using [Catch2](https://github.com/catchorg/Catch2) test framework
|
||||
|
||||
# Build
|
||||
|
||||
Tests build regularly like an idf project.
|
||||
|
||||
```
|
||||
idf.py build
|
||||
```
|
||||
|
||||
# Run
|
||||
|
||||
The build produces an executable in the build folder.
|
||||
|
||||
Just run:
|
||||
|
||||
```
|
||||
./build/host_mqtt_client_test.elf
|
||||
```
|
||||
|
||||
The test executable have some options provided by the test framework.
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
idf_component_register(SRCS "test_mqtt_client.cpp"
|
||||
REQUIRES cmock mqtt esp_timer esp_hw_support http_parser log
|
||||
WHOLE_ARCHIVE)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC -fsanitize=address -Wno-missing-field-initializers)
|
||||
target_link_options(${COMPONENT_LIB} PUBLIC -fsanitize=address)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC Catch2::Catch2WithMain)
|
||||
|
||||
idf_component_get_property(mqtt mqtt COMPONENT_LIB)
|
||||
target_compile_definitions(${mqtt} PRIVATE SOC_WIFI_SUPPORTED=1)
|
||||
target_compile_options(${mqtt} PUBLIC -fsanitize=address)
|
||||
target_link_options(${mqtt} PUBLIC -fsanitize=address)
|
||||
|
||||
if(CONFIG_GCOV_ENABLED)
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
|
||||
target_link_options(${COMPONENT_LIB} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
|
||||
|
||||
idf_component_get_property(mqtt mqtt COMPONENT_LIB)
|
||||
target_compile_options(${mqtt} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
|
||||
target_link_options(${mqtt} PUBLIC --coverage -fprofile-arcs -ftest-coverage)
|
||||
endif()
|
||||
@@ -1,9 +0,0 @@
|
||||
menu "Host-test config"
|
||||
|
||||
config GCOV_ENABLED
|
||||
bool "Coverage analyzer"
|
||||
default n
|
||||
help
|
||||
Enables coverage analyzing for host tests.
|
||||
|
||||
endmenu
|
||||
@@ -1,9 +0,0 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/catch2: "^3.5.2"
|
||||
espressif/mqtt:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
||||
## Required IDF version
|
||||
idf:
|
||||
version: ">=5.0.0"
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <net/if.h>
|
||||
#include <random>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include "esp_transport.h"
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "mqtt_client.h"
|
||||
extern "C" {
|
||||
#include "Mockesp_event.h"
|
||||
#include "Mockesp_mac.h"
|
||||
#include "Mockesp_transport.h"
|
||||
#include "Mockesp_transport_ssl.h"
|
||||
#include "Mockesp_transport_tcp.h"
|
||||
#include "Mockesp_transport_ws.h"
|
||||
#include "Mockevent_groups.h"
|
||||
#include "Mockhttp_parser.h"
|
||||
#include "Mockqueue.h"
|
||||
#include "Mocktask.h"
|
||||
#if __has_include ("Mockidf_additions.h")
|
||||
/* Some functions were moved from "task.h" to "idf_additions.h" */
|
||||
#include "Mockidf_additions.h"
|
||||
#endif
|
||||
#include "Mockesp_timer.h"
|
||||
|
||||
/*
|
||||
* The following functions are not directly called but the generation of them
|
||||
* from cmock is broken, so we need to define them here.
|
||||
*/
|
||||
esp_err_t esp_tls_get_and_clear_last_error(esp_tls_error_handle_t h, int *esp_tls_code, int *esp_tls_flags)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
auto random_string(std::size_t n)
|
||||
{
|
||||
static constexpr std::string_view char_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456790";
|
||||
std::string str;
|
||||
std::sample(char_set.begin(), char_set.end(), std::back_inserter(str), n,
|
||||
std::mt19937 {std::random_device{}()});
|
||||
return str;
|
||||
}
|
||||
|
||||
using unique_mqtt_client = std::unique_ptr < std::remove_pointer_t<esp_mqtt_client_handle_t>, decltype([](esp_mqtt_client_handle_t client)
|
||||
{
|
||||
esp_mqtt_client_destroy(client);
|
||||
}) >;
|
||||
|
||||
SCENARIO("MQTT Client Operation")
|
||||
{
|
||||
// Set expectations for the mocked calls.
|
||||
int mtx = 0;
|
||||
int transport_list = 0;
|
||||
int transport = 0;
|
||||
int event_group = 0;
|
||||
uint8_t mac[] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
|
||||
esp_timer_get_time_IgnoreAndReturn(0);
|
||||
xQueueTakeMutexRecursive_IgnoreAndReturn(true);
|
||||
xQueueGiveMutexRecursive_IgnoreAndReturn(true);
|
||||
xQueueCreateMutex_ExpectAnyArgsAndReturn(
|
||||
reinterpret_cast<QueueHandle_t>(&mtx));
|
||||
xEventGroupCreate_IgnoreAndReturn(reinterpret_cast<EventGroupHandle_t>(&event_group));
|
||||
esp_transport_list_init_IgnoreAndReturn(reinterpret_cast<esp_transport_list_handle_t>(&transport_list));
|
||||
esp_transport_tcp_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
|
||||
esp_transport_ssl_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
|
||||
esp_transport_ws_init_IgnoreAndReturn(reinterpret_cast<esp_transport_handle_t>(&transport));
|
||||
esp_transport_ws_set_subprotocol_IgnoreAndReturn(ESP_OK);
|
||||
esp_transport_list_add_IgnoreAndReturn(ESP_OK);
|
||||
esp_transport_set_default_port_IgnoreAndReturn(ESP_OK);
|
||||
http_parser_url_init_Ignore();
|
||||
esp_event_loop_create_IgnoreAndReturn(ESP_OK);
|
||||
esp_read_mac_IgnoreAndReturn(ESP_OK);
|
||||
esp_read_mac_ReturnThruPtr_mac(mac);
|
||||
esp_transport_list_destroy_IgnoreAndReturn(ESP_OK);
|
||||
esp_transport_destroy_IgnoreAndReturn(ESP_OK);
|
||||
vEventGroupDelete_Ignore();
|
||||
vQueueDelete_Ignore();
|
||||
GIVEN("An a minimal config") {
|
||||
esp_mqtt_client_config_t config{};
|
||||
config.broker.address.uri = "mqtt://1.1.1.1";
|
||||
struct http_parser_url ret_uri = {
|
||||
.field_set = 1 | (1 << 1),
|
||||
.port = 0,
|
||||
.field_data = { { 0, 4 } /*mqtt*/, { 7, 1 } } // at least *scheme* and *host*
|
||||
};
|
||||
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
|
||||
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
|
||||
xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE);
|
||||
SECTION("Client with minimal config") {
|
||||
auto client = unique_mqtt_client{esp_mqtt_client_init(&config)};
|
||||
REQUIRE(client != nullptr);
|
||||
SECTION("User will set a new uri") {
|
||||
struct http_parser_url ret_uri = {
|
||||
.field_set = 1,
|
||||
.port = 0,
|
||||
.field_data = { { 0, 1} }
|
||||
};
|
||||
SECTION("User set a correct URI") {
|
||||
http_parser_parse_url_StopIgnore();
|
||||
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
|
||||
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
|
||||
auto res = esp_mqtt_client_set_uri(client.get(), " ");
|
||||
REQUIRE(res == ESP_OK);
|
||||
}
|
||||
SECTION("Incorrect URI from user") {
|
||||
http_parser_parse_url_StopIgnore();
|
||||
http_parser_parse_url_ExpectAnyArgsAndReturn(1);
|
||||
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
|
||||
auto res = esp_mqtt_client_set_uri(client.get(), " ");
|
||||
REQUIRE(res == ESP_FAIL);
|
||||
}
|
||||
}
|
||||
SECTION("User set interface to use"){
|
||||
http_parser_parse_url_ExpectAnyArgsAndReturn(0);
|
||||
http_parser_parse_url_ReturnThruPtr_u(&ret_uri);
|
||||
struct ifreq if_name = {};
|
||||
strncpy(if_name.ifr_name, "custom", IFNAMSIZ - 1);
|
||||
if_name.ifr_name[IFNAMSIZ - 1] = '\0';;
|
||||
config.network.if_name = &if_name;
|
||||
SECTION("Client is not started"){
|
||||
REQUIRE(esp_mqtt_set_config(client.get(), &config)== ESP_OK);
|
||||
}
|
||||
}
|
||||
SECTION("After Start Client Is Cleanly destroyed") {
|
||||
REQUIRE(esp_mqtt_client_start(client.get()) == ESP_OK);
|
||||
// Only need to start the client, destroy is called automatically at the end of
|
||||
// scope
|
||||
}
|
||||
}
|
||||
SECTION("Client with all allocating configuration set") {
|
||||
auto host = random_string(20);
|
||||
auto path = random_string(10);
|
||||
auto username = random_string(10);
|
||||
auto client_id = random_string(10);
|
||||
auto password = random_string(10);
|
||||
auto lw_topic = random_string(10);
|
||||
auto lw_msg = random_string(10);
|
||||
|
||||
config.broker = {.address = {
|
||||
.hostname = host.data(),
|
||||
.path = path.data()
|
||||
}
|
||||
};
|
||||
config.credentials = {
|
||||
.username = username.data(),
|
||||
.client_id = client_id.data(),
|
||||
.authentication = {
|
||||
.password = password.data()
|
||||
}
|
||||
};
|
||||
config.session = {
|
||||
.last_will {
|
||||
.topic = lw_topic.data(),
|
||||
.msg = lw_msg.data()
|
||||
}
|
||||
};
|
||||
auto client = unique_mqtt_client{esp_mqtt_client_init(&config)};
|
||||
REQUIRE(client != nullptr);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1991-1993 The Regents of the University of California
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* Implementation from BSD headers*/
|
||||
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
|
||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
@@ -1 +0,0 @@
|
||||
CONFIG_GCOV_ENABLED=y
|
||||
@@ -1,6 +0,0 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_COMPILER_CXX_RTTI=y
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
|
||||
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
|
||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
||||
Reference in New Issue
Block a user