#include #include #include #include #include #include extern "C" { #include "drv/hl854x/udp.c" } using namespace std; struct test_drv_hl854x_readwrite_cb_items { size_t n; const char **tv; size_t tvlen; string writebuf; }; static struct test_drv_hl854x_readwrite_cb_items g_tvs; size_t test_drv_hl854x_read_cb(void *buf, size_t nbyte) { const size_t len = strlen(g_tvs.tv[g_tvs.n]); const char *str = g_tvs.tv[g_tvs.n]; if (nbyte < len) return 0; memcpy(buf, str, nbyte); g_tvs.n++; if (g_tvs.n == g_tvs.tvlen) g_tvs.n = 0; return len; } size_t test_drv_hl854x_write_cb(const void *buf, size_t nbyte) { g_tvs.writebuf.append(static_cast(buf), nbyte); return nbyte; } /** * Initialize an test string for reading (and set the correct UDP sessions states) * @param ctx Modem context (uinitialized) * @param str Mocked modem string readable by the driver */ void test_hl854x_udp_init(struct di_drv_hl854x_ctx *ctx, const char **tv, const size_t tvlen) { di_drv_hl854x_init(ctx); // The reader is default initialized as locked for the unit tests we must be able to // read synchronous. In the real world there is an async reader so we dont miss any // data. di_bsem_post(&ctx->lock.reader); di_drv_hl854x_set_read(ctx, test_drv_hl854x_read_cb); di_drv_hl854x_set_write(ctx, test_drv_hl854x_write_cb); g_tvs.n = 0; g_tvs.tv = tv; g_tvs.tvlen = tvlen; g_tvs.writebuf.clear(); ctx->carrier.status = HL854X_CARRIER_STATUS_REG_HOME; ctx->udp.session_id = HL854X_SESSION_ID_MIN; ctx->udp.state = HL854X_UDP_STATE_READY; } /** * Verify the initialisation is correct of the UDP session */ TEST(drv_hl854x_udp, init) { struct di_drv_hl854x_ctx ctx; di_drv_hl854x_init(&ctx); ASSERT_EQ(HL854X_SESSION_ID_UNKNOWN, ctx.udp.session_id); ASSERT_EQ(HL854X_UDP_STATE_UNKNOWN, ctx.udp.state); ASSERT_EQ(nullptr, ctx.udp.remote_addr); ASSERT_EQ(nullptr, ctx.udp.remote_port); } /** * Test the sending mechanism * * AT+KUDPSND=... * * Wait for modem `CONNECT\r\n` reply * * Write data bytes * * Wait for modem `OK` reply */ TEST(drv_hl854x_udp, send) { static const char *addr = "10.0.0.1"; static const char *port = "4000"; static const char *data = "hello world!"; static const char *tv[2] = {"CONNECT\r\n", "OK\r\n"}; struct di_drv_hl854x_ctx ctx; test_hl854x_udp_init(&ctx, tv, 2); di_drv_hl854x_udp_set_remote_endpoint(&ctx, addr, port); ASSERT_EQ(addr, ctx.udp.remote_addr); ASSERT_EQ(port, ctx.udp.remote_port); ASSERT_EQ(DNOK, di_drv_hl854x_udp_send(&ctx, data, strlen(data))); ASSERT_EQ(61, g_tvs.writebuf.size()); ASSERT_TRUE(nullptr != strstr(g_tvs.writebuf.c_str(), "AT+KUDPSND=1,\"10.0.0.1\",4000,12\r\n")); ASSERT_TRUE(nullptr != strstr(g_tvs.writebuf.c_str(), "hello world!")); } /** * Verify if the recv_wait_ndata_available works as expected when an async URC KUDP_DATA is send * * Test DNE_TIMEOUT on 1ms * * Recv 12 bytes KUDP_DATA URC * * Test DNOK on 1ms * * Check ndata_available is 12 bytes */ TEST(drv_hl854x_udp, recv_wait_ndata_available) { size_t ndata_available = 0; struct di_drv_hl854x_ctx ctx; static const char *tv[1] = {"+KUDP_DATA: 1,12\r\n"}; test_hl854x_udp_init(&ctx, tv, 1); // Check the mutex works and has a timeout because there are not data bytes available ASSERT_EQ(DNE_TIMEOUT, di_drv_hl854x_udp_recv_wait_ndata_available(&ctx, 1, &ndata_available)); ASSERT_EQ(ndata_available, 0); // Send URC for session 1 with 12 bytes ready di_drv_hl854x_read(&ctx); ASSERT_EQ(ctx.udp.ndata_available, 12); // Read amount of data bytes available ASSERT_EQ(DNOK, di_drv_hl854x_udp_recv_wait_ndata_available(&ctx, 1, &ndata_available)); // Check application has read the correct amount of bytes available and udp session // is reset to zero ASSERT_EQ(ndata_available, 12); ASSERT_EQ(ctx.udp.ndata_available, 0); } /** * Test the receive mechanism */ TEST(drv_hl854x_udp, recv) { size_t ndata_available = 0; uint8_t recv_buf[256]; static const char *tv[] = {"+KUDP_DATA: 1,8\r\n", "CONNECT\r\n", "TESTDATA--EOF--Pattern--\r\n", "OK\r\n"}; struct di_drv_hl854x_ctx ctx; memset(recv_buf, 0, sizeof(recv_buf)); test_hl854x_udp_init(&ctx, tv, DI_ARRAY_SIZE(tv)); // Send URC for session 1 with 8 bytes ready di_drv_hl854x_read(&ctx); ASSERT_EQ(8, ctx.udp.ndata_available); // Read amount of data bytes available ASSERT_EQ(DNOK, di_drv_hl854x_udp_recv_wait_ndata_available(&ctx, HL854X_TIMEOUT_INFINITE, &ndata_available)); // Check application has read the correct amount of bytes available and udp session ASSERT_EQ(8, ndata_available); ASSERT_EQ(8U, di_drv_hl854x_udp_recv(&ctx, recv_buf, sizeof(recv_buf))); EXPECT_TRUE( 0 == memcmp( "TESTDATA", recv_buf, 8 ) ); }