This is an automated email from the ASF dual-hosted git repository.

sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 7797b37814ed57baf6153852f5cb80413ee9b480
Author: Szymon Janc <[email protected]>
AuthorDate: Wed Oct 14 23:55:36 2026 +0200

    net/mqtt/coremqtt: Add unit tests for socket transport
    
    Tests run coreMQTT over Mynewt socket transport against minimal MQTT
    broker listening on loopback interface. They cover connection failure,
    subscribe and QoS 1 publish round trip, publish spanning multiple
    mbufs and socket reads, ping, receive timeout and broker closing the
    connection.
    
    Assisted-by: Claude:claude-opus-5-5
---
 net/mqtt/coremqtt/selftest/pkg.yml             |  33 +++
 net/mqtt/coremqtt/selftest/src/coremqtt_test.c | 333 +++++++++++++++++++++++++
 net/mqtt/coremqtt/selftest/src/coremqtt_test.h |  62 +++++
 net/mqtt/coremqtt/selftest/src/test_broker.c   | 265 ++++++++++++++++++++
 net/mqtt/coremqtt/selftest/syscfg.yml          |  25 ++
 5 files changed, 718 insertions(+)

diff --git a/net/mqtt/coremqtt/selftest/pkg.yml 
b/net/mqtt/coremqtt/selftest/pkg.yml
new file mode 100644
index 000000000..62da3ac9a
--- /dev/null
+++ b/net/mqtt/coremqtt/selftest/pkg.yml
@@ -0,0 +1,33 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: net/mqtt/coremqtt/selftest
+pkg.type: unittest
+pkg.description: "coreMQTT and Mynewt socket transport unit tests."
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/net/ip/mn_socket"
+    - "@apache-mynewt-core/net/mqtt/coremqtt"
+    - "@apache-mynewt-core/net/mqtt/coremqtt/transport/mn_socket"
+    - "@apache-mynewt-core/sys/console/stub"
+    - "@apache-mynewt-core/sys/log/stub"
+    - "@apache-mynewt-core/test/testutil"
diff --git a/net/mqtt/coremqtt/selftest/src/coremqtt_test.c 
b/net/mqtt/coremqtt/selftest/src/coremqtt_test.c
new file mode 100644
index 000000000..d4828e880
--- /dev/null
+++ b/net/mqtt/coremqtt/selftest/src/coremqtt_test.c
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+#include "mn_socket/mn_socket.h"
+#include "core_mqtt.h"
+#include "coremqtt/coremqtt.h"
+#include "coremqtt/mqtt_mn_socket.h"
+#include "coremqtt_test.h"
+
+#define TEST_TOPIC      "mynewt/test"
+#define TEST_TIMEOUT_MS 2000
+#define TEST_LARGE_LEN  3000
+
+static NetworkContext_t test_net;
+static MQTTContext_t test_ctx;
+static uint8_t test_buf[TEST_LARGE_LEN + 64];
+static MQTTPubAckInfo_t test_outgoing[2];
+static MQTTPubAckInfo_t test_incoming[2];
+static uint8_t test_payload[TEST_LARGE_LEN];
+
+static struct {
+    int suback;
+    int puback;
+    int rx;
+    uint8_t payload[TEST_LARGE_LEN];
+    size_t len;
+} test_ev;
+
+static bool
+test_event(MQTTContext_t *ctx, MQTTPacketInfo_t *pkt,
+           MQTTDeserializedInfo_t *info, MQTTSuccessFailReasonCode_t *reason,
+           MQTTPropBuilder_t *send_props, MQTTPropBuilder_t *get_props)
+{
+    MQTTPublishInfo_t *pub;
+
+    switch (pkt->type & 0xF0) {
+    case MQTT_PACKET_TYPE_SUBACK:
+        test_ev.suback++;
+        break;
+    case MQTT_PACKET_TYPE_PUBACK:
+        test_ev.puback++;
+        break;
+    case MQTT_PACKET_TYPE_PUBLISH:
+        pub = info->pPublishInfo;
+        TEST_ASSERT(pub->topicNameLength == strlen(TEST_TOPIC));
+        TEST_ASSERT(memcmp(pub->pTopicName, TEST_TOPIC, pub->topicNameLength) 
== 0);
+        TEST_ASSERT_FATAL(pub->payloadLength <= sizeof(test_ev.payload));
+        memcpy(test_ev.payload, pub->pPayload, pub->payloadLength);
+        test_ev.len = pub->payloadLength;
+        test_ev.rx++;
+        break;
+    default:
+        break;
+    }
+
+    return true;
+}
+
+static int
+test_net_connect(uint16_t port)
+{
+    struct mn_sockaddr_in sin;
+
+    memset(&sin, 0, sizeof(sin));
+    sin.msin_len = sizeof(sin);
+    sin.msin_family = MN_AF_INET;
+    sin.msin_port = htons(port);
+    mn_inet_pton(MN_AF_INET, "127.0.0.1", &sin.msin_addr);
+
+    return mqtt_mn_socket_connect(&test_net, (struct mn_sockaddr *)&sin,
+                                  TEST_TIMEOUT_MS);
+}
+
+static MQTTStatus_t
+test_mqtt_connect(void)
+{
+    TransportInterface_t transport;
+    MQTTFixedBuffer_t buf;
+    MQTTConnectInfo_t conn;
+    MQTTStatus_t status;
+    bool session_present;
+    int rc;
+
+    memset(&test_ev, 0, sizeof(test_ev));
+
+    rc = test_net_connect(TEST_BROKER_PORT);
+    TEST_ASSERT_FATAL(rc == 0, "connect rc=%d", rc);
+
+    mqtt_mn_socket_transport(&test_net, &transport);
+    buf.pBuffer = test_buf;
+    buf.size = sizeof(test_buf);
+
+    status = MQTT_Init(&test_ctx, &transport, coremqtt_time_ms, test_event, 
&buf);
+    TEST_ASSERT_FATAL(status == MQTTSuccess);
+    status = MQTT_InitStatefulQoS(&test_ctx, test_outgoing, 2, test_incoming,
+                                  2, NULL, 0);
+    TEST_ASSERT_FATAL(status == MQTTSuccess);
+
+    memset(&conn, 0, sizeof(conn));
+    conn.cleanSession = true;
+    conn.keepAliveSeconds = 60;
+    conn.pClientIdentifier = "test";
+    conn.clientIdentifierLength = 4;
+
+    return MQTT_Connect(&test_ctx, &conn, NULL, TEST_TIMEOUT_MS,
+                        &session_present, NULL, NULL);
+}
+
+static void
+test_mqtt_disconnect(void)
+{
+    MQTTStatus_t status;
+
+    status = MQTT_Disconnect(&test_ctx, NULL, NULL);
+    TEST_ASSERT(status == MQTTSuccess);
+    mqtt_mn_socket_disconnect(&test_net);
+    test_broker_wait_idle();
+    TEST_ASSERT(test_broker.err == 0);
+}
+
+static void
+test_process_until(int *cnt, int target)
+{
+    MQTTStatus_t status;
+    uint32_t start;
+
+    start = coremqtt_time_ms();
+    while (*cnt < target) {
+        status = MQTT_ProcessLoop(&test_ctx);
+        TEST_ASSERT_FATAL(status == MQTTSuccess || status == MQTTNeedMoreBytes,
+                          "status=%d", status);
+        TEST_ASSERT_FATAL(coremqtt_time_ms() - start < TEST_TIMEOUT_MS);
+    }
+}
+
+static void
+test_subscribe(void)
+{
+    MQTTSubscribeInfo_t sub;
+    MQTTStatus_t status;
+
+    memset(&sub, 0, sizeof(sub));
+    sub.qos = MQTTQoS1;
+    sub.pTopicFilter = TEST_TOPIC;
+    sub.topicFilterLength = strlen(TEST_TOPIC);
+
+    status = MQTT_Subscribe(&test_ctx, &sub, 1, MQTT_GetPacketId(&test_ctx), 
NULL);
+    TEST_ASSERT_FATAL(status == MQTTSuccess);
+    test_process_until(&test_ev.suback, 1);
+}
+
+static void
+test_publish(const void *payload, size_t len)
+{
+    MQTTPublishInfo_t pub;
+    MQTTStatus_t status;
+
+    memset(&pub, 0, sizeof(pub));
+    pub.qos = MQTTQoS1;
+    pub.pTopicName = TEST_TOPIC;
+    pub.topicNameLength = strlen(TEST_TOPIC);
+    pub.pPayload = payload;
+    pub.payloadLength = len;
+
+    status = MQTT_Publish(&test_ctx, &pub, MQTT_GetPacketId(&test_ctx), NULL);
+    TEST_ASSERT_FATAL(status == MQTTSuccess);
+}
+
+static void
+coremqtt_test_connect_refused(void)
+{
+    int rc;
+
+    /* Nothing listens on this port */
+    rc = test_net_connect(TEST_BROKER_PORT + 1);
+    TEST_ASSERT(rc != 0);
+    TEST_ASSERT(test_net.sock == NULL);
+}
+
+static void
+coremqtt_test_pubsub(void)
+{
+    TEST_ASSERT_FATAL(test_mqtt_connect() == MQTTSuccess);
+    TEST_ASSERT(test_broker.connects == 1);
+
+    test_subscribe();
+
+    test_publish("hello", 5);
+    test_process_until(&test_ev.rx, 1);
+    test_process_until(&test_ev.puback, 1);
+    TEST_ASSERT(test_ev.len == 5);
+    TEST_ASSERT(memcmp(test_ev.payload, "hello", 5) == 0);
+    TEST_ASSERT(test_broker.publishes == 1);
+
+    test_mqtt_disconnect();
+    TEST_ASSERT(test_broker.disconnects == 1);
+}
+
+static void
+coremqtt_test_large_publish(void)
+{
+    size_t i;
+
+    for (i = 0; i < sizeof(test_payload); i++) {
+        test_payload[i] = i * 7;
+    }
+
+    TEST_ASSERT_FATAL(test_mqtt_connect() == MQTTSuccess);
+    test_subscribe();
+
+    /* Spans several mbufs and several socket reads in both directions */
+    test_publish(test_payload, sizeof(test_payload));
+    test_process_until(&test_ev.rx, 1);
+    test_process_until(&test_ev.puback, 1);
+    TEST_ASSERT(test_ev.len == sizeof(test_payload));
+    TEST_ASSERT(memcmp(test_ev.payload, test_payload, sizeof(test_payload)) == 
0);
+
+    test_mqtt_disconnect();
+}
+
+static void
+coremqtt_test_ping(void)
+{
+    MQTTStatus_t status;
+    uint32_t start;
+
+    TEST_ASSERT_FATAL(test_mqtt_connect() == MQTTSuccess);
+
+    status = MQTT_Ping(&test_ctx);
+    TEST_ASSERT_FATAL(status == MQTTSuccess);
+    TEST_ASSERT(test_ctx.waitingForPingResp);
+
+    start = coremqtt_time_ms();
+    while (test_ctx.waitingForPingResp) {
+        status = MQTT_ProcessLoop(&test_ctx);
+        TEST_ASSERT_FATAL(status == MQTTSuccess);
+        TEST_ASSERT_FATAL(coremqtt_time_ms() - start < TEST_TIMEOUT_MS);
+    }
+    TEST_ASSERT(test_broker.pings == 1);
+
+    test_mqtt_disconnect();
+}
+
+static void
+coremqtt_test_recv_timeout(void)
+{
+    MQTTStatus_t status;
+    uint32_t start;
+    uint32_t elapsed;
+
+    TEST_ASSERT_FATAL(test_mqtt_connect() == MQTTSuccess);
+
+    /* With nothing to receive, the process loop waits for the timeout */
+    mqtt_mn_socket_set_recv_timeout(&test_net, 200);
+    start = coremqtt_time_ms();
+    status = MQTT_ProcessLoop(&test_ctx);
+    elapsed = coremqtt_time_ms() - start;
+    TEST_ASSERT(status == MQTTSuccess);
+    TEST_ASSERT(elapsed >= 150 && elapsed < 1000, "elapsed=%u", 
(unsigned)elapsed);
+
+    /* Without a timeout it returns right away */
+    mqtt_mn_socket_set_recv_timeout(&test_net, 0);
+    start = coremqtt_time_ms();
+    status = MQTT_ProcessLoop(&test_ctx);
+    elapsed = coremqtt_time_ms() - start;
+    TEST_ASSERT(status == MQTTSuccess);
+    TEST_ASSERT(elapsed < 100, "elapsed=%u", (unsigned)elapsed);
+
+    test_mqtt_disconnect();
+}
+
+static void
+coremqtt_test_broker_close(void)
+{
+    MQTTStatus_t status;
+
+    /* Broker drops the connection instead of answering CONNECT */
+    test_broker.close_on_connect = 1;
+    status = test_mqtt_connect();
+    test_broker.close_on_connect = 0;
+    TEST_ASSERT(status != MQTTSuccess);
+    TEST_ASSERT(test_ctx.connectStatus != MQTTConnected);
+
+    /* Further use of the closed socket fails instead of blocking */
+    TEST_ASSERT(mqtt_mn_socket_recv(&test_net, test_buf, 1) < 0);
+    TEST_ASSERT(mqtt_mn_socket_send(&test_net, "x", 1) < 0);
+
+    mqtt_mn_socket_disconnect(&test_net);
+    test_broker_wait_idle();
+}
+
+TEST_CASE_TASK(coremqtt_test_transport)
+{
+    test_broker_start();
+
+    coremqtt_test_connect_refused();
+    coremqtt_test_pubsub();
+    coremqtt_test_large_publish();
+    coremqtt_test_ping();
+    coremqtt_test_recv_timeout();
+    coremqtt_test_broker_close();
+}
+
+TEST_SUITE(coremqtt_test_all)
+{
+    coremqtt_test_transport();
+}
+
+int
+main(int argc, char **argv)
+{
+    coremqtt_test_all();
+    return tu_any_failed;
+}
diff --git a/net/mqtt/coremqtt/selftest/src/coremqtt_test.h 
b/net/mqtt/coremqtt/selftest/src/coremqtt_test.h
new file mode 100644
index 000000000..fb93e5eba
--- /dev/null
+++ b/net/mqtt/coremqtt/selftest/src/coremqtt_test.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_COREMQTT_TEST_
+#define H_COREMQTT_TEST_
+
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TEST_BROKER_PORT 18883
+
+/*
+ * Minimal MQTT v5.0 broker for tests, listening on 127.0.0.1. Accepts one
+ * client at a time, acknowledges CONNECT, SUBSCRIBE, PUBLISH (QoS 1) and
+ * PINGREQ, and echoes every PUBLISH back to the client. Runs in the socket
+ * provider's task.
+ */
+struct test_broker {
+    struct mn_socket *listen;
+    struct mn_socket *conn;
+    uint8_t rx[4608];
+    size_t rx_len;
+    /* Close the connection instead of sending CONNACK */
+    volatile int close_on_connect;
+    volatile int connects;
+    volatile int publishes;
+    volatile int pings;
+    volatile int disconnects;
+    /* Non-zero if the broker failed (unexpected input or send error) */
+    volatile int err;
+};
+
+extern struct test_broker test_broker;
+
+void test_broker_start(void);
+void test_broker_wait_idle(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/net/mqtt/coremqtt/selftest/src/test_broker.c 
b/net/mqtt/coremqtt/selftest/src/test_broker.c
new file mode 100644
index 000000000..d5657c936
--- /dev/null
+++ b/net/mqtt/coremqtt/selftest/src/test_broker.c
@@ -0,0 +1,265 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include "os/mynewt.h"
+#include "mn_socket/mn_socket.h"
+#include "coremqtt_test.h"
+
+struct test_broker test_broker;
+
+static void
+test_broker_close(void)
+{
+    if (test_broker.conn) {
+        mn_close(test_broker.conn);
+        test_broker.conn = NULL;
+    }
+    test_broker.rx_len = 0;
+}
+
+static void
+test_broker_send(const uint8_t *data, size_t len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    om = os_msys_get_pkthdr(len, 0);
+    if (!om) {
+        test_broker.err = MN_ENOBUFS;
+        return;
+    }
+    if (os_mbuf_append(om, data, len)) {
+        os_mbuf_free_chain(om);
+        test_broker.err = MN_ENOBUFS;
+        return;
+    }
+
+    rc = mn_sendto(test_broker.conn, om, NULL);
+    if (rc) {
+        if (rc == MN_EAGAIN) {
+            os_mbuf_free_chain(om);
+        }
+        test_broker.err = rc;
+    }
+}
+
+static void
+test_broker_handle(const uint8_t *pkt, size_t hdr_len, size_t len)
+{
+    const uint8_t *var = pkt + hdr_len;
+    uint8_t rsp[6];
+    size_t topic_len;
+    int qos;
+
+    switch (pkt[0] & 0xF0) {
+    case 0x10:
+        /* CONNECT -> CONNACK, no session, success, no properties */
+        test_broker.connects++;
+        if (test_broker.close_on_connect) {
+            test_broker_close();
+            return;
+        }
+        rsp[0] = 0x20;
+        rsp[1] = 3;
+        rsp[2] = 0;
+        rsp[3] = 0;
+        rsp[4] = 0;
+        test_broker_send(rsp, 5);
+        break;
+    case 0x80:
+        /* SUBSCRIBE -> SUBACK granting QoS 1 */
+        rsp[0] = 0x90;
+        rsp[1] = 4;
+        rsp[2] = var[0];
+        rsp[3] = var[1];
+        rsp[4] = 0;
+        rsp[5] = 1;
+        test_broker_send(rsp, 6);
+        break;
+    case 0x30:
+        /* PUBLISH -> PUBACK (QoS 1), then deliver it back to the client */
+        test_broker.publishes++;
+        qos = (pkt[0] >> 1) & 0x03;
+        if (qos) {
+            topic_len = (var[0] << 8) | var[1];
+            rsp[0] = 0x40;
+            rsp[1] = 2;
+            rsp[2] = var[2 + topic_len];
+            rsp[3] = var[3 + topic_len];
+            test_broker_send(rsp, 4);
+        }
+        test_broker_send(pkt, len);
+        break;
+    case 0xC0:
+        /* PINGREQ -> PINGRESP */
+        test_broker.pings++;
+        rsp[0] = 0xD0;
+        rsp[1] = 0;
+        test_broker_send(rsp, 2);
+        break;
+    case 0xE0:
+        test_broker.disconnects++;
+        test_broker_close();
+        break;
+    case 0x40:
+        /* PUBACK for a delivered message */
+        break;
+    default:
+        test_broker.err = -1;
+        test_broker_close();
+        break;
+    }
+}
+
+static void
+test_broker_process(void)
+{
+    size_t rem_len;
+    size_t total;
+    size_t i;
+    int shift;
+
+    while (test_broker.conn && test_broker.rx_len >= 2) {
+        rem_len = 0;
+        shift = 0;
+        i = 1;
+        do {
+            if (i >= test_broker.rx_len) {
+                return;
+            }
+            rem_len |= (test_broker.rx[i] & 0x7F) << shift;
+            shift += 7;
+        } while (test_broker.rx[i++] & 0x80 && i < 5);
+
+        total = i + rem_len;
+        if (total > test_broker.rx_len) {
+            return;
+        }
+
+        test_broker_handle(test_broker.rx, i, total);
+        if (!test_broker.conn) {
+            return;
+        }
+
+        test_broker.rx_len -= total;
+        memmove(test_broker.rx, test_broker.rx + total, test_broker.rx_len);
+    }
+}
+
+static void
+test_broker_readable(void *arg, int err)
+{
+    struct os_mbuf *om;
+    uint16_t len;
+    int rc;
+
+    while (test_broker.conn) {
+        rc = mn_recvfrom(test_broker.conn, &om, NULL);
+        if (rc == MN_EAGAIN) {
+            break;
+        }
+        if (rc) {
+            /* Client closed the connection */
+            test_broker_close();
+            break;
+        }
+
+        len = OS_MBUF_PKTLEN(om);
+        if (test_broker.rx_len + len > sizeof(test_broker.rx)) {
+            os_mbuf_free_chain(om);
+            test_broker.err = MN_ENOBUFS;
+            test_broker_close();
+            break;
+        }
+        os_mbuf_copydata(om, 0, len, test_broker.rx + test_broker.rx_len);
+        test_broker.rx_len += len;
+        os_mbuf_free_chain(om);
+
+        test_broker_process();
+    }
+}
+
+static void
+test_broker_writable(void *arg, int err)
+{
+}
+
+static const union mn_socket_cb test_broker_conn_cbs = {
+    .socket = {
+        .readable = test_broker_readable,
+        .writable = test_broker_writable,
+    },
+};
+
+static int
+test_broker_newconn(void *arg, struct mn_socket *new)
+{
+    if (test_broker.conn) {
+        return -1;
+    }
+
+    test_broker.conn = new;
+    test_broker.rx_len = 0;
+    mn_socket_set_cbs(new, NULL, &test_broker_conn_cbs);
+
+    return 0;
+}
+
+static const union mn_socket_cb test_broker_listen_cbs = {
+    .listen = {
+        .newconn = test_broker_newconn,
+    },
+};
+
+void
+test_broker_start(void)
+{
+    struct mn_sockaddr_in sin;
+    int rc;
+
+    memset(&test_broker, 0, sizeof(test_broker));
+
+    rc = mn_socket(&test_broker.listen, MN_PF_INET, MN_SOCK_STREAM, 0);
+    TEST_ASSERT_FATAL(rc == 0);
+    mn_socket_set_cbs(test_broker.listen, NULL, &test_broker_listen_cbs);
+
+    memset(&sin, 0, sizeof(sin));
+    sin.msin_len = sizeof(sin);
+    sin.msin_family = MN_AF_INET;
+    sin.msin_port = htons(TEST_BROKER_PORT);
+    mn_inet_pton(MN_AF_INET, "127.0.0.1", &sin.msin_addr);
+
+    rc = mn_bind(test_broker.listen, (struct mn_sockaddr *)&sin);
+    TEST_ASSERT_FATAL(rc == 0, "bind rc=%d", rc);
+
+    rc = mn_listen(test_broker.listen, 2);
+    TEST_ASSERT_FATAL(rc == 0, "listen rc=%d", rc);
+}
+
+void
+test_broker_wait_idle(void)
+{
+    int i;
+
+    for (i = 0; i < 100 && test_broker.conn; i++) {
+        os_time_delay(os_time_ms_to_ticks32(20));
+    }
+    TEST_ASSERT_FATAL(test_broker.conn == NULL);
+}
diff --git a/net/mqtt/coremqtt/selftest/syscfg.yml 
b/net/mqtt/coremqtt/selftest/syscfg.yml
new file mode 100644
index 000000000..e61d12e9a
--- /dev/null
+++ b/net/mqtt/coremqtt/selftest/syscfg.yml
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.vals:
+    # Room for large publishes in both directions
+    MSYS_1_BLOCK_COUNT: 64
+    MSYS_1_BLOCK_SIZE: 256
+    # Host printf needs more stack than the test task has
+    COREMQTT_LOG_LVL: 4

Reply via email to