diff --git a/devices/grlib-multi/test-grlib-multi.c b/devices/grlib-multi/test-grlib-multi.c index 6928fff9b..7a1acc2fa 100644 --- a/devices/grlib-multi/test-grlib-multi.c +++ b/devices/grlib-multi/test-grlib-multi.c @@ -569,13 +569,15 @@ static void test_spwRxRead(const oid_t rxOid, const unsigned int firstDesc, uint .oid.port = rxOid.port, }; multi_i_t *idevctl = (multi_i_t *)msg.i.raw; + multi_o_t *odevctl = (multi_o_t *)msg.o.raw; idevctl->spw.type = spw_rx; idevctl->spw.task.rx.nPackets = nPackets; idevctl->spw.task.rx.firstDesc = firstDesc; TEST_ASSERT_EQUAL_INT(0, msgSend(rxOid.port, &msg)); - TEST_ASSERT_EQUAL_INT(nPackets, msg.o.err); + TEST_ASSERT_EQUAL_INT(0, msg.o.err); + TEST_ASSERT_EQUAL_INT(nPackets, odevctl->val); for (size_t i = 0; i < nPackets; i++) { rxBuf += spw_deserializeRxMsg(rxBuf, &packets[i]); diff --git a/devices/grspw2/test-grspw2.c b/devices/grspw2/test-grspw2.c index bd7e2940b..0d1ea2a9b 100644 --- a/devices/grspw2/test-grspw2.c +++ b/devices/grspw2/test-grspw2.c @@ -15,11 +15,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -38,6 +40,11 @@ #define TEST_SPW_ADDR1 0x4 #endif +#define TEST_RX_TIMEOUT 100000 + +#ifndef TEST_SPW_LOOPBACK +#define TEST_SPW_LOOPBACK 0 +#endif /* helper functions */ @@ -108,13 +115,15 @@ static void test_spwRxRead(const oid_t rxOid, const unsigned int firstDesc, uint .oid.port = rxOid.port, }; spw_t *idevctl = (spw_t *)msg.i.raw; + spw_o_t *odevctl = (spw_o_t *)msg.o.raw; idevctl->type = spw_rx; idevctl->task.rx.nPackets = nPackets; idevctl->task.rx.firstDesc = firstDesc; TEST_ASSERT_EQUAL_INT(0, msgSend(rxOid.port, &msg)); - TEST_ASSERT_EQUAL_INT(nPackets, msg.o.err); + TEST_ASSERT_EQUAL_INT(0, msg.o.err); + TEST_ASSERT_EQUAL_INT(nPackets, odevctl->val); for (size_t i = 0; i < nPackets; i++) { rxBuf += spw_deserializeRxMsg(rxBuf, &packets[i]); @@ -170,6 +179,131 @@ static void test_spwRxTx(const size_t nPackets, bool async) } +static void test_spwRxTimeout(uint32_t timeout) +{ + oid_t rxOid = test_getOid(TEST_SPW_PATH0); + + size_t nPackets = 1; + unsigned int firstDesc = test_spwConfigureRx(rxOid, nPackets); + + const size_t rxBufsz = (SPW_RX_MIN_BUFSZ)*nPackets; + uint8_t *rxBuf = malloc(rxBufsz); + TEST_ASSERT_NOT_NULL(rxBuf); + + msg_t msg = { + .type = mtDevCtl, + .i = { .data = NULL, .size = 0 }, + .o = { .data = rxBuf, .size = rxBufsz }, + .oid.id = TEST_SPW_ID0, + .oid.port = rxOid.port, + }; + spw_t *idevctl = (spw_t *)msg.i.raw; + spw_o_t *odevctl = (spw_o_t *)msg.o.raw; + + idevctl->type = spw_rx; + idevctl->task.rx.nPackets = nPackets; + idevctl->task.rx.firstDesc = firstDesc; + idevctl->task.rx.timeoutUs = timeout; + + struct timeval start, end; + gettimeofday(&start, NULL); + + int err = msgSend(rxOid.port, &msg); + gettimeofday(&end, NULL); + + uint32_t diff = ((end.tv_sec - start.tv_sec) * 1e6) + (end.tv_usec - start.tv_usec); + + TEST_ASSERT_EQUAL_INT(0, err); + + TEST_ASSERT_GREATER_OR_EQUAL_INT(timeout, diff); + TEST_ASSERT_LESS_OR_EQUAL_INT(timeout + 100000, diff); + + TEST_ASSERT_EQUAL_INT(-ETIME, msg.o.err); + TEST_ASSERT_EQUAL_INT(0, odevctl->val); + + free(rxBuf); +} + + +static size_t test_spwRxReadTimeout(const oid_t rxOid, const unsigned int firstDesc, uint8_t *rxBuf, size_t rxBufsz, spw_rxPacket_t *packets, const size_t nPackets, uint32_t timeout) +{ + msg_t msg = { + .type = mtDevCtl, + .i = { .data = NULL, .size = 0 }, + .o = { .data = rxBuf, .size = rxBufsz }, + .oid.id = TEST_SPW_ID0, + .oid.port = rxOid.port, + }; + spw_t *idevctl = (spw_t *)msg.i.raw; + spw_o_t *odevctl = (spw_o_t *)msg.o.raw; + + idevctl->type = spw_rx; + idevctl->task.rx.nPackets = nPackets; + idevctl->task.rx.firstDesc = firstDesc; + idevctl->task.rx.timeoutUs = timeout; + + TEST_ASSERT_EQUAL_INT(0, msgSend(rxOid.port, &msg)); + TEST_ASSERT_EQUAL_INT(-ETIME, msg.o.err); + + for (size_t i = 0; i < odevctl->val; i++) { + rxBuf += spw_deserializeRxMsg(rxBuf, &packets[i]); + } + + return odevctl->val; +} + + +static void test_spwRxTxTimeout(size_t nPackets, size_t nLost, uint32_t timeoutUs) +{ + oid_t rxOid = test_getOid(TEST_SPW_PATH0); + unsigned int firstDesc = test_spwConfigureRx(rxOid, nPackets); + size_t nSent = (nPackets - nLost); + + oid_t txOid = test_getOid(TEST_SPW_PATH1); + static const uint8_t hdr[] = { TEST_SPW_ADDR0, /* protocol ID */ 0x5 }, data[] = { 0x1, 0x2, 0x3, 0x4 }; + static const size_t hdrSz = sizeof(hdr), dataSz = sizeof(data); + const size_t txBufsz = (SPW_TX_MIN_BUFSZ + hdrSz + dataSz) * nSent; + uint8_t *txBuf = malloc(txBufsz); + TEST_ASSERT_NOT_NULL(txBuf); + + size_t size = 0; + for (size_t i = 0; i < nSent; i++) { + size_t ret = spw_serializeTxMsg(SPW_TX_FLG_HDR_LEN(hdrSz), dataSz, hdr, data, txBuf + size, txBufsz - size); + TEST_ASSERT_NOT_EQUAL(0, ret); + size += ret; + } + test_spwTx(txOid, txBuf, size, nSent, true); + + /* Receive packet */ + const size_t rxBufsz = (SPW_RX_MIN_BUFSZ + hdrSz + dataSz) * nPackets; + uint8_t *rxBuf = malloc(rxBufsz); + TEST_ASSERT_NOT_NULL(rxBuf); + + spw_rxPacket_t packets[nPackets]; + size_t rPackets = test_spwRxReadTimeout(rxOid, firstDesc, rxBuf, rxBufsz, packets, nPackets, timeoutUs); + + TEST_ASSERT_EQUAL_INT(nSent, rPackets); + +#if TEST_SPW_LOOPBACK + for (size_t i = 0; i < nSent; i++) { + TEST_ASSERT_EQUAL(hdrSz + dataSz, packets[i].flags & SPW_RX_LEN_MSK); + TEST_ASSERT_EQUAL_HEX8_ARRAY(hdr, packets[i].buf, hdrSz); + TEST_ASSERT_EQUAL_HEX8_ARRAY(data, packets[i].buf + hdrSz, dataSz); + } +#else + for (size_t i = 0; i < nSent; i++) { + /* first byte of header (phy address) consumed by router */ + TEST_ASSERT_EQUAL((hdrSz + dataSz - 1), packets[i].flags & SPW_RX_LEN_MSK); + TEST_ASSERT_EQUAL(hdr[1], packets[i].buf[0]); + TEST_ASSERT_EQUAL_HEX8_ARRAY(data, packets[i].buf + hdrSz - 1, dataSz); + } +#endif + + free(txBuf); + free(rxBuf); +} + + TEST_GROUP(test_spw); @@ -217,6 +351,12 @@ TEST(test_spw, spwSetAddress) } +TEST(test_spw, spwRxTimeout) +{ + test_spwRxTimeout(TEST_RX_TIMEOUT); +} + + TEST(test_spw, spwTxRxSinglePacketSync) { test_spwRxTx(1, false); @@ -254,15 +394,24 @@ TEST(test_spw, spwTxRxBigNumberOfPacketsAsync) } +TEST(test_spw, spwTxRxTimeoutMultiplePackets) +{ + /* Lost number of packets must be smaller then TX number of packets */ + test_spwRxTxTimeout(128, 20, TEST_RX_TIMEOUT); +} + + TEST_GROUP_RUNNER(test_spw) { RUN_TEST_CASE(test_spw, spwSetAddress); + RUN_TEST_CASE(test_spw, spwRxTimeout); RUN_TEST_CASE(test_spw, spwTxRxSinglePacketSync); RUN_TEST_CASE(test_spw, spwTxRxSinglePacketAsync); RUN_TEST_CASE(test_spw, spwTxRxMultiplePacketsSync); RUN_TEST_CASE(test_spw, spwTxRxMultiplePacketsAsync); RUN_TEST_CASE(test_spw, spwTxRxBigNumberOfPacketsSync); RUN_TEST_CASE(test_spw, spwTxRxBigNumberOfPacketsAsync); + RUN_TEST_CASE(test_spw, spwTxRxTimeoutMultiplePackets); } diff --git a/devices/grspwrtr/test-grspwrtr.c b/devices/grspwrtr/test-grspwrtr.c index c7249c6f6..0c8d7db9c 100644 --- a/devices/grspwrtr/test-grspwrtr.c +++ b/devices/grspwrtr/test-grspwrtr.c @@ -18,12 +18,14 @@ #include #include #include +#include #include #include -#define TEST_SPWRTR_PATH0 "/dev/spwrtr0" +#define TEST_SPWRTR_PATH0 "/dev/spwrtr0" +#define TEST_SPWRTR_IDIVISOR 0x13u /* helper functions */ @@ -151,10 +153,119 @@ TEST(test_spwrtr, spwrtrSetMapping) } +TEST(test_spwrtr, spwrtrGetClkdiv) +{ + struct { + uint8_t port; + uint8_t expected; + } tests[] = { + { + .port = 1u, + .expected = TEST_SPWRTR_IDIVISOR, + }, + { + .port = 2u, + .expected = TEST_SPWRTR_IDIVISOR, + }, + }; + + + oid_t oid = test_getOid(TEST_SPWRTR_PATH0); + msg_t msg = { + .type = mtDevCtl, + .i = { .data = NULL, .size = 0 }, + .o = { .data = NULL, .size = 0 }, + .oid.id = 0, + .oid.port = oid.port, + }; + spwrtr_t *ictl = (spwrtr_t *)msg.i.raw; + + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + char info[19]; + snprintf(info, 19, "Test nr %zu failed", i); + + ictl->type = spwrtr_clkdiv_get; + ictl->task.clkdiv.port = tests[i].port; + + TEST_ASSERT_EQUAL_INT_MESSAGE(0, msgSend(oid.port, &msg), info); + TEST_ASSERT_EQUAL_INT_MESSAGE(0, msg.o.err, info); + + spwrtr_o_t *octl = (spwrtr_o_t *)msg.o.raw; + TEST_ASSERT_EQUAL_UINT_MESSAGE(tests[i].expected, octl->val, info); + } +} + + +TEST(test_spwrtr, spwrtrSetClkdiv) +{ + struct { + uint8_t port; + uint8_t div; + int expected; + } tests[] = { + { + .port = 1u, + .div = 0x14u, + .expected = 0, + }, + { + .port = 2u, + .div = 0x14u, + .expected = 0, + }, + { + .port = 0u, + .div = 0x14u, + .expected = -EINVAL, + }, + { .port = SPWRTR_SPW_CNT + 1, + .div = 0x14u, + .expected = -EINVAL } + }; + + + oid_t oid = test_getOid(TEST_SPWRTR_PATH0); + msg_t msg = { + .type = mtDevCtl, + .i = { .data = NULL, .size = 0 }, + .o = { .data = NULL, .size = 0 }, + .oid.id = 0, + .oid.port = oid.port, + }; + spwrtr_t *ictl = (spwrtr_t *)msg.i.raw; + + for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + char info[19]; + snprintf(info, 19, "Test nr %zu failed", i); + + ictl->type = spwrtr_clkdiv_set; + ictl->task.clkdiv.port = tests[i].port; + ictl->task.clkdiv.div = tests[i].div; + + TEST_ASSERT_EQUAL_INT_MESSAGE(0, msgSend(oid.port, &msg), info); + TEST_ASSERT_EQUAL_INT_MESSAGE(tests[i].expected, msg.o.err, info); + + /* check if clkdiv was set clkdiv get */ + if (tests[i].expected == 0) { + ictl->type = spwrtr_clkdiv_get; + ictl->task.clkdiv.port = tests[i].port; + + TEST_ASSERT_EQUAL_INT_MESSAGE(0, msgSend(oid.port, &msg), info); + TEST_ASSERT_EQUAL_INT_MESSAGE(0, msg.o.err, info); + + spwrtr_o_t *octl = (spwrtr_o_t *)msg.o.raw; + TEST_ASSERT_EQUAL_UINT_MESSAGE(tests[i].div, octl->val, info); + } + } +} + + TEST_GROUP_RUNNER(test_spwrtr) { RUN_TEST_CASE(test_spwrtr, spwrtrGetMapping); RUN_TEST_CASE(test_spwrtr, spwrtrSetMapping); + RUN_TEST_CASE(test_spwrtr, spwrtrGetClkdiv); + RUN_TEST_CASE(test_spwrtr, spwrtrSetClkdiv); }