Merge branch 'bugfix/mqtt_pubconnect_test' into 'master'

MQTT: Publish connect test fix

See merge request espressif/esp-idf!14292
This commit is contained in:
David Čermák
2021-09-15 13:34:58 +00:00
8 changed files with 303 additions and 227 deletions

View File

@@ -57,7 +57,7 @@ These third party libraries can be included into the application (firmware) prod
* :component:`Asio <asio>`, Copyright (c) 2003-2018 Christopher M. Kohlhoff is licensed under the Boost Software License as described in :component_file:`COPYING file<asio/asio/asio/COPYING>`. * :component:`Asio <asio>`, Copyright (c) 2003-2018 Christopher M. Kohlhoff is licensed under the Boost Software License as described in :component_file:`COPYING file<asio/asio/asio/COPYING>`.
* :component:`ESP-MQTT <mqtt>` MQTT Package (contiki-mqtt) - Copyright (c) 2014, Stephen Robinson, MQTT-ESP - Tuan PM <tuanpm at live dot com> is licensed under Apache License 2,0 as described in :component_file:`LICENSE file <mqtt/esp-mqtt/LICENSE>`. * :component:`ESP-MQTT <mqtt>` MQTT Package (contiki-mqtt) - Copyright (c) 2014, Stephen Robinson, MQTT-ESP - Tuan PM <tuanpm at live dot com> is licensed under Apache License 2.0 as described in :component_file:`LICENSE file <mqtt/esp-mqtt/LICENSE>`.
* :component:`BLE Mesh <bt/esp_ble_mesh>` is adapted from Zephyr Project, Copyright (c) 2017-2018 Intel Corporation and licensed under Apache License 2.0 * :component:`BLE Mesh <bt/esp_ble_mesh>` is adapted from Zephyr Project, Copyright (c) 2017-2018 Intel Corporation and licensed under Apache License 2.0

View File

@@ -10,7 +10,7 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mqtt_publish_connect_test) project(mqtt_publish_connect_test)
target_add_binary_data(mqtt_publish_connect_test.elf "main/mqtt_eclipse_org.pem" TEXT) 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.crt" TEXT)
target_add_binary_data(mqtt_publish_connect_test.elf "ca.der" 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.key" TEXT)

View File

@@ -8,6 +8,7 @@ import socket
import ssl import ssl
import string import string
import subprocess import subprocess
import sys
from threading import Event, Thread from threading import Event, Thread
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
@@ -239,6 +240,73 @@ class TlsServer:
self.shutdown.set() self.shutdown.set()
def connection_tests(dut, cases):
ip = get_my_ip()
set_server_cert_cn(ip)
server_port = 2222
def teardown_connection_suite():
dut.write('conn teardown 0 0')
def start_connection_case(case, desc):
print('Starting {}: {}'.format(case, desc))
case_id = cases[case]
dut.write('conn {} {} {}'.format(ip, server_port, case_id))
dut.expect('Test case:{} started'.format(case_id))
return case_id
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT']:
# All these cases connect to the server with no server verification or with server only verification
with TlsServer(server_port):
test_nr = start_connection_case(case, 'default server - expect to connect normally')
dut.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
with TlsServer(server_port, refuse_connection=True):
test_nr = start_connection_case(case, 'ssl shall connect, but mqtt sends connect refusal')
dut.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut.expect('MQTT ERROR: 0x5') # expecting 0x5 ... connection not authorized error
with TlsServer(server_port, client_cert=True) as s:
test_nr = start_connection_case(case, 'server with client verification - handshake error since client presents no client certificate')
dut.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE)
if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' not in s.get_last_ssl_error():
raise('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', 'CONFIG_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(server_port, client_cert=True):
test_nr = start_connection_case(case, 'server with client verification - expect to connect normally')
dut.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
case = 'CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT'
with TlsServer(server_port) as s:
test_nr = start_connection_case(case, 'invalid server certificate on default server - expect ssl handshake error')
dut.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA)
if 'alert unknown ca' not in s.get_last_ssl_error():
raise Exception('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
case = 'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT'
with TlsServer(server_port, client_cert=True) as s:
test_nr = start_connection_case(case, 'Invalid client certificate on server with client verification - expect ssl handshake error')
dut.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (CERTIFICATE_VERIFY_FAILED)
if 'CERTIFICATE_VERIFY_FAILED' not in s.get_last_ssl_error():
raise Exception('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']:
with TlsServer(server_port, use_alpn=True) as s:
test_nr = start_connection_case(case, 'server with alpn - expect connect, check resolved protocol')
dut.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
if case == 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT' and s.get_negotiated_protocol() is None:
print(' - client with alpn off, no negotiated protocol: OK')
elif case == 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN' and s.get_negotiated_protocol() == 'mymqtt':
print(' - client with alpn on, negotiated protocol resolved: OK')
else:
raise Exception('Unexpected negotiated protocol {}'.format(s.get_negotiated_protocol()))
teardown_connection_suite()
@ttfw_idf.idf_custom_test(env_tag='Example_WIFI', group='test-apps') @ttfw_idf.idf_custom_test(env_tag='Example_WIFI', group='test-apps')
def test_app_protocol_mqtt_publish_connect(env, extra_data): def test_app_protocol_mqtt_publish_connect(env, extra_data):
""" """
@@ -256,6 +324,35 @@ def test_app_protocol_mqtt_publish_connect(env, extra_data):
# Look for test case symbolic names and publish configs # Look for test case symbolic names and publish configs
cases = {} cases = {}
publish_cfg = {} publish_cfg = {}
try:
# Get connection test cases configuration: symbolic names for test cases
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH',
'CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT',
'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']:
cases[case] = dut1.app.get_sdkconfig()[case]
except Exception:
print('ENV_TEST_FAILURE: Some mandatory CONNECTION test case not found in sdkconfig')
raise
dut1.start_app()
esp_ip = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
print('Got IP={}'.format(esp_ip[0]))
if not os.getenv('MQTT_SKIP_CONNECT_TEST'):
connection_tests(dut1,cases)
#
# start publish tests only if enabled in the environment (for weekend tests only)
if not os.getenv('MQTT_PUBLISH_TEST'):
return
# Get publish test configuration
try: try:
def get_host_port_from_dut(dut1, config_option): def get_host_port_from_dut(dut1, config_option):
value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut1.app.get_sdkconfig()[config_option]) value = re.search(r'\:\/\/([^:]+)\:([0-9]+)', dut1.app.get_sdkconfig()[config_option])
@@ -263,17 +360,6 @@ def test_app_protocol_mqtt_publish_connect(env, extra_data):
return None, None return None, None
return value.group(1), int(value.group(2)) return value.group(1), int(value.group(2))
# Get connection test cases configuration: symbolic names for test cases
for i in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH',
'CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD',
'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT',
'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']:
cases[i] = dut1.app.get_sdkconfig()[i]
# Get publish test configuration
publish_cfg['publish_topic'] = dut1.app.get_sdkconfig()['CONFIG_EXAMPLE_SUBSCIBE_TOPIC'].replace('"','') publish_cfg['publish_topic'] = dut1.app.get_sdkconfig()['CONFIG_EXAMPLE_SUBSCIBE_TOPIC'].replace('"','')
publish_cfg['subscribe_topic'] = dut1.app.get_sdkconfig()['CONFIG_EXAMPLE_PUBLISH_TOPIC'].replace('"','') publish_cfg['subscribe_topic'] = dut1.app.get_sdkconfig()['CONFIG_EXAMPLE_PUBLISH_TOPIC'].replace('"','')
publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_host_port_from_dut(dut1, 'CONFIG_EXAMPLE_BROKER_SSL_URI') publish_cfg['broker_host_ssl'], publish_cfg['broker_port_ssl'] = get_host_port_from_dut(dut1, 'CONFIG_EXAMPLE_BROKER_SSL_URI')
@@ -282,80 +368,9 @@ def test_app_protocol_mqtt_publish_connect(env, extra_data):
publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_host_port_from_dut(dut1, 'CONFIG_EXAMPLE_BROKER_WSS_URI') publish_cfg['broker_host_wss'], publish_cfg['broker_port_wss'] = get_host_port_from_dut(dut1, 'CONFIG_EXAMPLE_BROKER_WSS_URI')
except Exception: except Exception:
print('ENV_TEST_FAILURE: Some mandatory test case not found in sdkconfig') print('ENV_TEST_FAILURE: Some mandatory PUBLISH test case not found in sdkconfig')
raise raise
dut1.start_app()
esp_ip = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)
print('Got IP={}'.format(esp_ip[0]))
#
# start connection test
ip = get_my_ip()
set_server_cert_cn(ip)
server_port = 2222
def start_connection_case(case, desc):
print('Starting {}: {}'.format(case, desc))
case_id = cases[case]
dut1.write('conn {} {} {}'.format(ip, server_port, case_id))
dut1.expect('Test case:{} started'.format(case_id))
return case_id
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT']:
# All these cases connect to the server with no server verification or with server only verification
with TlsServer(server_port):
test_nr = start_connection_case(case, 'default server - expect to connect normally')
dut1.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
with TlsServer(server_port, refuse_connection=True):
test_nr = start_connection_case(case, 'ssl shall connect, but mqtt sends connect refusal')
dut1.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut1.expect('MQTT ERROR: 0x5') # expecting 0x5 ... connection not authorized error
with TlsServer(server_port, client_cert=True) as s:
test_nr = start_connection_case(case, 'server with client verification - handshake error since client presents no client certificate')
dut1.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut1.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE)
if 'PEER_DID_NOT_RETURN_A_CERTIFICATE' not in s.get_last_ssl_error():
raise('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH', 'CONFIG_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(server_port, client_cert=True):
test_nr = start_connection_case(case, 'server with client verification - expect to connect normally')
dut1.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
case = 'CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT'
with TlsServer(server_port) as s:
test_nr = start_connection_case(case, 'invalid server certificate on default server - expect ssl handshake error')
dut1.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut1.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA)
if 'alert unknown ca' not in s.get_last_ssl_error():
raise Exception('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
case = 'CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT'
with TlsServer(server_port, client_cert=True) as s:
test_nr = start_connection_case(case, 'Invalid client certificate on server with client verification - expect ssl handshake error')
dut1.expect('MQTT_EVENT_ERROR: Test={}'.format(test_nr), timeout=30)
dut1.expect('ESP-TLS ERROR: 0x8010') # expect ... handshake error (CERTIFICATE_VERIFY_FAILED)
if 'CERTIFICATE_VERIFY_FAILED' not in s.get_last_ssl_error():
raise Exception('Unexpected ssl error from the server {}'.format(s.get_last_ssl_error()))
for case in ['CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT', 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN']:
with TlsServer(server_port, use_alpn=True) as s:
test_nr = start_connection_case(case, 'server with alpn - expect connect, check resolved protocol')
dut1.expect('MQTT_EVENT_CONNECTED: Test={}'.format(test_nr), timeout=30)
if case == 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT' and s.get_negotiated_protocol() is None:
print(' - client with alpn off, no negotiated protocol: OK')
elif case == 'CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN' and s.get_negotiated_protocol() == 'mymqtt':
print(' - client with alpn on, negotiated protocol resolved: OK')
else:
raise Exception('Unexpected negotiated protocol {}'.format(s.get_negotiated_protocol()))
#
# start publish tests only if enabled in the environment (for weekend tests only)
if not os.getenv('MQTT_PUBLISH_TEST'):
return
def start_publish_case(transport, qos, repeat, published, queue): def start_publish_case(transport, qos, repeat, published, queue):
print('Starting Publish test: transport:{}, qos:{}, nr_of_msgs:{}, msg_size:{}, enqueue:{}' print('Starting Publish test: transport:{}, qos:{}, nr_of_msgs:{}, msg_size:{}, enqueue:{}'
.format(transport, qos, published, repeat * DEFAULT_MSG_SIZE, queue)) .format(transport, qos, published, repeat * DEFAULT_MSG_SIZE, queue))
@@ -375,4 +390,4 @@ def test_app_protocol_mqtt_publish_connect(env, extra_data):
if __name__ == '__main__': if __name__ == '__main__':
test_app_protocol_mqtt_publish_connect() test_app_protocol_mqtt_publish_connect(dut=ttfw_idf.ESP32QEMUDUT if sys.argv[1:] == ['qemu'] else ttfw_idf.ESP32DUT)

View File

@@ -42,34 +42,45 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_event_handle_t event = event_data; esp_mqtt_event_handle_t event = event_data;
ESP_LOGD(TAG, "Event: %d, Test case: %d", event->event_id, running_test_case); ESP_LOGD(TAG, "Event: %d, Test case: %d", event->event_id, running_test_case);
switch (event->event_id) { switch (event->event_id) {
case MQTT_EVENT_CONNECTED: case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED: Test=%d", running_test_case); ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED: Test=%d", running_test_case);
break; break;
case MQTT_EVENT_ERROR: case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR: Test=%d", running_test_case); ESP_LOGI(TAG, "MQTT_EVENT_ERROR: Test=%d", running_test_case);
if (event->error_handle->error_type == MQTT_ERROR_TYPE_ESP_TLS) { if (event->error_handle->error_type == MQTT_ERROR_TYPE_ESP_TLS) {
ESP_LOGI(TAG, "ESP-TLS ERROR: 0x%x", event->error_handle->esp_tls_last_esp_err); ESP_LOGI(TAG, "ESP-TLS ERROR: 0x%x", event->error_handle->esp_tls_last_esp_err);
} else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { } 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); ESP_LOGI(TAG, "MQTT ERROR: 0x%x", event->error_handle->connect_return_code);
} else { } else {
ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type); ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type);
} }
break; break;
default: default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id); ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break; break;
} }
} }
static void create_client(void) static void create_client(void)
{ {
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = "mqtts://127.0.0.1:1234" .uri = "mqtts://127.0.0.1:1234"
}; };
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
mqtt_client = client; mqtt_client = client;
esp_mqtt_client_start(client); esp_mqtt_client_start(client);
ESP_LOGI(TAG, "mqtt client created for connection tests");
}
static void destroy_client(void)
{
if (mqtt_client) {
esp_mqtt_client_stop(mqtt_client);
esp_mqtt_client_destroy(mqtt_client);
mqtt_client = NULL;
ESP_LOGI(TAG, "mqtt client for connection tests destroyed");
}
} }
static void connect_no_certs(const char *host, const int port) static void connect_no_certs(const char *host, const int port)
@@ -77,7 +88,7 @@ static void connect_no_certs(const char *host, const int port)
char uri[64]; char uri[64];
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri .uri = uri
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
@@ -89,12 +100,12 @@ static void connect_with_client_key_password(const char *host, const int port)
char uri[64]; char uri[64];
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri, .uri = uri,
.cert_pem = (const char *)ca_local_crt, .cert_pem = (const char *)ca_local_crt,
.client_cert_pem = (const char *)client_pwd_crt, .client_cert_pem = (const char *)client_pwd_crt,
.client_key_pem = (const char *)client_pwd_key, .client_key_pem = (const char *)client_pwd_key,
.clientkey_password = "esp32", .clientkey_password = "esp32",
.clientkey_password_len = 5 .clientkey_password_len = 5
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
@@ -106,11 +117,11 @@ static void connect_with_server_der_cert(const char *host, const int port)
char uri[64]; char uri[64];
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri, .uri = uri,
.cert_pem = (const char *)ca_der_start, .cert_pem = (const char *)ca_der_start,
.cert_len = ca_der_end - ca_der_start, .cert_len = ca_der_end - ca_der_start,
.client_cert_pem = "NULL", .client_cert_pem = "NULL",
.client_key_pem = "NULL" .client_key_pem = "NULL"
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
@@ -122,10 +133,10 @@ static void connect_with_wrong_server_cert(const char *host, const int port)
char uri[64]; char uri[64];
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri, .uri = uri,
.cert_pem = (const char *)client_pwd_crt, .cert_pem = (const char *)client_pwd_crt,
.client_cert_pem = "NULL", .client_cert_pem = "NULL",
.client_key_pem = "NULL" .client_key_pem = "NULL"
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
@@ -165,10 +176,10 @@ static void connect_with_invalid_client_certs(const char *host, const int port)
char uri[64]; char uri[64];
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri, .uri = uri,
.cert_pem = (const char *)ca_local_crt, .cert_pem = (const char *)ca_local_crt,
.client_cert_pem = (const char *)client_inv_crt, .client_cert_pem = (const char *)client_inv_crt,
.client_key_pem = (const char *)client_no_pwd_key .client_key_pem = (const char *)client_no_pwd_key
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
@@ -181,15 +192,15 @@ static void connect_with_alpn(const char *host, const int port)
const char *alpn_protos[] = { "mymqtt", NULL }; const char *alpn_protos[] = { "mymqtt", NULL };
sprintf(uri, "mqtts://%s:%d", host, port); sprintf(uri, "mqtts://%s:%d", host, port);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = uri, .uri = uri,
.alpn_protos = alpn_protos .alpn_protos = alpn_protos
}; };
esp_mqtt_set_config(mqtt_client, &mqtt_cfg); esp_mqtt_set_config(mqtt_client, &mqtt_cfg);
esp_mqtt_client_disconnect(mqtt_client); esp_mqtt_client_disconnect(mqtt_client);
esp_mqtt_client_reconnect(mqtt_client); esp_mqtt_client_reconnect(mqtt_client);
} }
void connection_test(const char* line) void connection_test(const char *line)
{ {
char test_type[32]; char test_type[32];
char host[32]; char host[32];
@@ -200,36 +211,39 @@ void connection_test(const char* line)
if (mqtt_client == NULL) { if (mqtt_client == NULL) {
create_client(); create_client();
} }
if (strcmp(host, "teardown") == 0) {
destroy_client();;
}
ESP_LOGI(TAG, "CASE:%d, connecting to mqtts://%s:%d ", test_case, host, port); ESP_LOGI(TAG, "CASE:%d, connecting to mqtts://%s:%d ", test_case, host, port);
running_test_case = test_case; running_test_case = test_case;
switch (test_case) { switch (test_case) {
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT: case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT:
connect_no_certs(host, port); connect_no_certs(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT: case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT:
connect_with_server_cert(host, port); connect_with_server_cert(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH: case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH:
connect_with_server_client_certs(host, port); connect_with_server_client_certs(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT: case CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT:
connect_with_wrong_server_cert(host, port); connect_with_wrong_server_cert(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT: case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT:
connect_with_server_der_cert(host, port); connect_with_server_der_cert(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD: case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD:
connect_with_client_key_password(host, port); connect_with_client_key_password(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT: case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT:
connect_with_invalid_client_certs(host, port); connect_with_invalid_client_certs(host, port);
break; break;
case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN: case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN:
connect_with_alpn(host, port); connect_with_alpn(host, port);
break; break;
default: default:
ESP_LOGE(TAG, "Unknown test case %d ", test_case); ESP_LOGE(TAG, "Unknown test case %d ", test_case);
break; break;
} }
ESP_LOGI(TAG, "Test case:%d started", test_case); ESP_LOGI(TAG, "Test case:%d started", test_case);
} }

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

@@ -0,0 +1,30 @@
-----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-----

View File

@@ -18,8 +18,8 @@
static const char *TAG = "PUBLISH_CONNECT_TEST"; static const char *TAG = "PUBLISH_CONNECT_TEST";
void connection_test(const char* line); void connection_test(const char *line);
void publish_test(const char* line); void publish_test(const char *line);
static void get_string(char *line, size_t size) static void get_string(char *line, size_t size)
{ {

View File

@@ -17,6 +17,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "mqtt_client.h" #include "mqtt_client.h"
#include "sdkconfig.h"
static const char *TAG = "PUBLISH_TEST"; static const char *TAG = "PUBLISH_TEST";
@@ -32,25 +33,27 @@ static size_t expected_published = 0;
static size_t actual_published = 0; static size_t actual_published = 0;
static int qos_test = 0; static int qos_test = 0;
#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1 #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-----"; static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else #else
extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif #endif
extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end");
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{ {
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client; esp_mqtt_client_handle_t client = event->client;
static int msg_id = 0; static int msg_id = 0;
static int actual_len = 0; static int actual_len = 0;
// your_context_t *context = event->context;
switch (event->event_id) { switch (event->event_id) {
case MQTT_EVENT_BEFORE_CONNECT:
break;
case MQTT_EVENT_CONNECTED: case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT); xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT);
msg_id = esp_mqtt_client_subscribe(client, CONFIG_EXAMPLE_SUBSCIBE_TOPIC, qos_test); msg_id = esp_mqtt_client_subscribe(client, CONFIG_EXAMPLE_SUBSCIBE_TOPIC, qos_test);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); ESP_LOGI(TAG, "sent subscribe successful %s , msg_id=%d", CONFIG_EXAMPLE_SUBSCIBE_TOPIC, msg_id);
break; break;
case MQTT_EVENT_DISCONNECTED: case MQTT_EVENT_DISCONNECTED:
@@ -76,7 +79,7 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
msg_id = event->msg_id; msg_id = event->msg_id;
} else { } else {
actual_len += event->data_len; actual_len += event->data_len;
// check consisency with msg_id across multiple data events for single msg // check consistency with msg_id across multiple data events for single msg
if (msg_id != event->msg_id) { if (msg_id != event->msg_id) {
ESP_LOGI(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id); ESP_LOGI(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id);
abort(); abort();
@@ -105,36 +108,24 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
ESP_LOGI(TAG, "Other event id:%d", event->event_id); ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break; break;
} }
return ESP_OK;
} }
typedef enum {NONE, TCP, SSL, WS, WSS} transport_t;
static transport_t current_transport;
static void mqtt_app_start(void)
void test_init(void)
{ {
mqtt_event_group = xEventGroupCreate(); mqtt_event_group = xEventGroupCreate();
const esp_mqtt_client_config_t mqtt_cfg = { esp_mqtt_client_config_t config = {0};
.event_handle = mqtt_event_handler, mqtt_client = esp_mqtt_client_init(&config);
.cert_pem = (const char *)mqtt_eclipse_org_pem_start, current_transport = NONE;
}; esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
} }
void publish_test(const char* line) void pattern_setup(char *pattern, int repeat)
{ {
char pattern[32];
char transport[32];
int repeat = 0;
int enqueue = 0;
static bool is_mqtt_init = false;
if (!is_mqtt_init) {
mqtt_app_start();
is_mqtt_init = true;
}
sscanf(line, "%s %s %d %d %d %d", transport, pattern, &repeat, &expected_published, &qos_test, &enqueue);
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d\n", pattern, repeat, expected_published);
int pattern_size = strlen(pattern); int pattern_size = strlen(pattern);
free(expected_data); free(expected_data);
free(actual_data); free(actual_data);
@@ -146,29 +137,82 @@ void publish_test(const char* line)
memcpy(expected_data + i * pattern_size, pattern, pattern_size); memcpy(expected_data + i * pattern_size, pattern, pattern_size);
} }
printf("EXPECTED STRING %.*s, SIZE:%d\n", expected_size, expected_data, expected_size); printf("EXPECTED STRING %.*s, SIZE:%d\n", expected_size, expected_data, expected_size);
esp_mqtt_client_stop(mqtt_client); }
static void configure_client(char *transport)
{
ESP_LOGI(TAG, "Configuration");
transport_t selected_transport;
if (0 == strcmp(transport, "tcp")) { if (0 == strcmp(transport, "tcp")) {
ESP_LOGI(TAG, "[TCP transport] Startup.."); selected_transport = TCP;
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_TCP_URI);
} else if (0 == strcmp(transport, "ssl")) { } else if (0 == strcmp(transport, "ssl")) {
ESP_LOGI(TAG, "[SSL transport] Startup.."); selected_transport = SSL;
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_SSL_URI);
} else if (0 == strcmp(transport, "ws")) { } else if (0 == strcmp(transport, "ws")) {
ESP_LOGI(TAG, "[WS transport] Startup.."); selected_transport = WS;
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WS_URI);
} else if (0 == strcmp(transport, "wss")) { } else if (0 == strcmp(transport, "wss")) {
ESP_LOGI(TAG, "[WSS transport] Startup.."); selected_transport = WSS;
esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WSS_URI);
} else { } else {
ESP_LOGE(TAG, "Unexpected transport"); ESP_LOGE(TAG, "Unexpected transport %s", transport);
abort(); 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);
if (selected_transport != current_transport) {
esp_mqtt_client_config_t config = {0};
switch (selected_transport) {
case NONE:
break;
case TCP:
ESP_LOGI(TAG, "[TCP transport] Startup..");
config.uri = CONFIG_EXAMPLE_BROKER_TCP_URI;
break;
case SSL:
ESP_LOGI(TAG, "[SSL transport] Startup..");
config.uri = CONFIG_EXAMPLE_BROKER_SSL_URI;
break;
case WS:
ESP_LOGI(TAG, "[WS transport] Startup..");
config.uri = CONFIG_EXAMPLE_BROKER_WS_URI;
break;
case WSS:
ESP_LOGI(TAG, "[WSS transport] Startup..");
config.uri = CONFIG_EXAMPLE_BROKER_WSS_URI;
break;
}
if (selected_transport == SSL || selected_transport == WSS) {
ESP_LOGI(TAG, "Set certificate");
config.cert_pem = (const char *)mqtt_eclipseprojects_io_pem_start;
}
esp_mqtt_set_config(mqtt_client, &config);
}
}
void publish_test(const char *line)
{
char pattern[32];
char transport[32];
int repeat = 0;
int enqueue = 0;
static bool is_test_init = false;
if (!is_test_init) {
test_init();
is_test_init = true;
} else {
esp_mqtt_client_stop(mqtt_client);
}
sscanf(line, "%s %s %d %d %d %d", transport, pattern, &repeat, &expected_published, &qos_test, &enqueue);
ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d\n", pattern, repeat, expected_published);
pattern_setup(pattern, repeat);
xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT);
configure_client(transport);
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++) { for (int i = 0; i < expected_published; i++) {
int msg_id; int msg_id;
if (enqueue) { if (enqueue) {