Merge branch 'feature/mqtt_unit_test' into 'master'

mqtt: basic set of unit tests, modify example tests to check ssl connect

See merge request espressif/esp-idf!7393
This commit is contained in:
Angus Gratton
2020-02-10 15:10:56 +08:00
32 changed files with 1052 additions and 336 deletions

View File

@@ -1,13 +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.5)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mqtt_publish)
target_add_binary_data(mqtt_publish.elf "main/mqtt_eclipse_org.pem" TEXT)

View File

@@ -1,9 +0,0 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := mqtt_publish
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
include $(IDF_PATH)/make/project.mk

View File

@@ -1,85 +0,0 @@
# ESP-MQTT advanced published test
(See the README.md file in the upper level 'examples' directory for more information about examples.)
Main purpose of this example 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
## How to use example
This example waits for user input to provide these parameters:
- 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 example can be executed on any ESP32 board, the only required interface is WiFi and connection to internet.
### Configure the project
* Open the project configuration menu (`idf.py menuconfig`)
* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
* When using Make build system, set `Default serial port` under `Serial flasher config`.
* Set brokers for all 4 transports (TCP, SSL, WS, WSS), also set certificate if needed
* Set topics for publishing from and to ESP32
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
```
I (4730) event: sta ip: 192.168.0.125, mask: 255.255.255.0, gw: 192.168.0.2
I (4730) PUBLISH_TEST: [APP] Free memory: 236728 bytes
I (4730) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
D (4740) MQTT_CLIENT: MQTT client_id=ESP32_09885C
I (31360) PUBLISH_TEST: PATTERN:1234 REPEATED:10 PUBLISHED:10
```
- User enters "tcp 1234 10 10 1"
```
EXPECTED STRING 1234123412341234123412341234123412341234, SIZE:40
W (31360) MQTT_CLIENT: Client asked to stop, but was not started
I (31360) PUBLISH_TEST: [TCP transport] Startup..
D (31370) MQTT_CLIENT: Core selection disabled
I (31370) PUBLISH_TEST: Note free memory: 224652 bytes
I (31370) PUBLISH_TEST: Other event id:7
D (31390) MQTT_CLIENT: Transport connected to mqtt://192.168.0.163:1883
I (31400) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
D (31410) MQTT_CLIENT: Connected
I (31410) PUBLISH_TEST: MQTT_EVENT_CONNECTED
D (31410) MQTT_CLIENT: mqtt_enqueue id: 31184, type=8 successful
D (31410) OUTBOX: ENQUEUE msgid=31184, msg_type=8, len=20, size=20
D (31420) MQTT_CLIENT: Sent subscribe topic=/xxx.topic123, id: 31184, type=8 successful
I (31430) PUBLISH_TEST: sent subscribe successful, msg_id=31184
D (31440) MQTT_CLIENT: mqtt_enqueue id: 16584, type=3 successful
D (31440) OUTBOX: ENQUEUE msgid=16584, msg_type=3, len=59, size=79
I (31450) PUBLISH_TEST: [16584] Publishing...
D (31450) MQTT_CLIENT: msg_type=9, msg_id=31184
D (31460) MQTT_CLIENT: pending_id=16584, pending_msg_count = 2
D (31460) OUTBOX: DELETED msgid=31184, msg_type=8, remain size=59
D (31470) MQTT_CLIENT: Subscribe successful
I (31470) PUBLISH_TEST: MQTT_EVENT_SUBSCRIBED, msg_id=31184
D (31480) MQTT_CLIENT: msg_type=4, msg_id=16584
D (31480) MQTT_CLIENT: pending_id=16584, pending_msg_count = 1
D (31490) OUTBOX: DELETED msgid=16584, msg_type=3, remain size=0
D (31500) MQTT_CLIENT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish
I (31500) PUBLISH_TEST: MQTT_EVENT_PUBLISHED, msg_id=16584
D (31510) MQTT_CLIENT: mqtt_enqueue id: 44615, type=3 successful
D (31520) OUTBOX: ENQUEUE msgid=44615, msg_type=3, len=59, size=59
I (31530) PUBLISH_TEST: [44615] Publishing...
...
```

View File

@@ -1,2 +0,0 @@
idf_component_register(SRCS "publish_test.c"
INCLUDE_DIRS ".")

View File

@@ -1,50 +0,0 @@
menu "Example Configuration"
config EXAMPLE_BROKER_SSL_URI
string "Broker SSL URL"
default "mqtts://mqtt.eclipse.org:8883"
help
URL of an mqtt broker for ssl transport
config EXAMPLE_BROKER_TCP_URI
string "Broker TCP URL"
default "mqtt://mqtt.eclipse.org:1883"
help
URL of an mqtt broker for tcp transport
config EXAMPLE_BROKER_WS_URI
string "Broker WS URL"
default "ws://mqtt.eclipse.org:80/mqtt"
help
URL of an mqtt broker for ws transport
config EXAMPLE_BROKER_WSS_URI
string "Broker WSS URL"
default "wss://mqtt.eclipse.org:443/mqtt"
help
URL of an mqtt broker for wss transport
config EXAMPLE_PUBLISH_TOPIC
string "publish topic"
default "/topic/publish/esp2py"
help
topic to which esp32 client publishes
config EXAMPLE_SUBSCIBE_TOPIC
string "subscribe topic"
default "/topic/subscribe/py2esp"
help
topic to which esp32 client subsribes (and expects data)
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 != ""
endmenu

View File

@@ -1 +0,0 @@
COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem

View File

@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----

View File

@@ -1,226 +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 <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
static const char *TAG = "PUBLISH_TEST";
static EventGroupHandle_t mqtt_event_group;
const static int CONNECTED_BIT = BIT0;
static esp_mqtt_client_handle_t mqtt_client = NULL;
static char *expected_data = NULL;
static char *actual_data = NULL;
static size_t expected_size = 0;
static size_t expected_published = 0;
static size_t actual_published = 0;
static int qos_test = 0;
#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start");
#endif
extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end");
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t client = event->client;
static int msg_id = 0;
static int actual_len = 0;
// your_context_t *context = event->context;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);
msg_id = esp_mqtt_client_subscribe(client, CONFIG_EXAMPLE_SUBSCIBE_TOPIC, qos_test);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", 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_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
printf("ID=%d, total_len=%d, data_len=%d, current_data_offset=%d\n", event->msg_id, event->total_data_len, event->data_len, event->current_data_offset);
if (event->topic) {
actual_len = event->data_len;
msg_id = event->msg_id;
} else {
actual_len += event->data_len;
// check consisency with msg_id across multiple data events for single msg
if (msg_id != event->msg_id) {
ESP_LOGI(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id);
abort();
}
}
memcpy(actual_data + event->current_data_offset, event->data, event->data_len);
if (actual_len == event->total_data_len) {
if (0 == memcmp(actual_data, expected_data, expected_size)) {
printf("OK!");
memset(actual_data, 0, expected_size);
actual_published ++;
if (actual_published == expected_published) {
printf("Correct pattern received exactly x times\n");
ESP_LOGI(TAG, "Test finished correctly!");
}
} else {
printf("FAILED!");
abort();
}
}
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
return ESP_OK;
}
static void mqtt_app_start(void)
{
mqtt_event_group = xEventGroupCreate();
const esp_mqtt_client_config_t mqtt_cfg = {
.event_handle = mqtt_event_handler,
.cert_pem = (const char *)mqtt_eclipse_org_pem_start,
};
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
}
static void get_string(char *line, size_t size)
{
int count = 0;
while (count < size) {
int c = fgetc(stdin);
if (c == '\n') {
line[count] = '\0';
break;
} else if (c > 0 && c < 127) {
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void app_main(void)
{
char line[256];
char pattern[32];
char transport[32];
int repeat = 0;
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("MQTT_CLIENT", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE);
esp_log_level_set("TRANSPORT", 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());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
mqtt_app_start();
while (1) {
get_string(line, sizeof(line));
sscanf(line, "%s %s %d %d %d", transport, pattern, &repeat, &expected_published, &qos_test);
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d\n", pattern, repeat, expected_published);
int pattern_size = strlen(pattern);
free(expected_data);
free(actual_data);
actual_published = 0;
expected_size = pattern_size * repeat;
expected_data = malloc(expected_size);
actual_data = malloc(expected_size);
for (int i = 0; i < repeat; i++) {
memcpy(expected_data + i * pattern_size, pattern, pattern_size);
}
printf("EXPECTED STRING %.*s, SIZE:%d\n", expected_size, expected_data, expected_size);
esp_mqtt_client_stop(mqtt_client);
if (0 == strcmp(transport, "tcp")) {
ESP_LOGI(TAG, "[TCP transport] Startup..");
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_TCP_URI);
} else if (0 == strcmp(transport, "ssl")) {
ESP_LOGI(TAG, "[SSL transport] Startup..");
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_SSL_URI);
} else if (0 == strcmp(transport, "ws")) {
ESP_LOGI(TAG, "[WS transport] Startup..");
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WS_URI);
} else if (0 == strcmp(transport, "wss")) {
ESP_LOGI(TAG, "[WSS transport] Startup..");
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WSS_URI);
} else {
ESP_LOGE(TAG, "Unexpected transport");
abort();
}
xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
esp_mqtt_client_start(mqtt_client);
ESP_LOGI(TAG, "Note free memory: %d bytes", esp_get_free_heap_size());
xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
for (int i = 0; i < expected_published; i++) {
int msg_id = esp_mqtt_client_publish(mqtt_client, CONFIG_EXAMPLE_PUBLISH_TOPIC, expected_data, expected_size, qos_test, 0);
ESP_LOGI(TAG, "[%d] Publishing...", msg_id);
}
}
}

View File

@@ -1,9 +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_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=n

View File

@@ -1,19 +0,0 @@
CONFIG_IDF_TARGET_ESP32=y
CONFIG_EXAMPLE_USE_OPENETH=y
CONFIG_ETH_USE_OPENETH=y
CONFIG_ETH_OPENETH_DMA_RX_BUFFER_NUM=4
CONFIG_ETH_OPENETH_DMA_TX_BUFFER_NUM=1
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y
CONFIG_ESPTOOLPY_FLASHMODE_DOUT=y
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=16384
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_HARDWARE_AES=n
CONFIG_MBEDTLS_HARDWARE_MPI=n
CONFIG_MBEDTLS_HARDWARE_SHA=n