From 6bc0a0ce61e640a1f4c65b7407de6b0caed52c92 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 12 Aug 2016 22:14:16 +0200 Subject: [PATCH] tests: provide gnrc_sock_udp tests --- tests/gnrc_sock_udp/Makefile | 21 + tests/gnrc_sock_udp/constants.h | 44 ++ tests/gnrc_sock_udp/main.c | 705 ++++++++++++++++++++++++++++ tests/gnrc_sock_udp/stack.c | 172 +++++++ tests/gnrc_sock_udp/stack.h | 95 ++++ tests/gnrc_sock_udp/tests/01-run.py | 74 +++ 6 files changed, 1111 insertions(+) create mode 100644 tests/gnrc_sock_udp/Makefile create mode 100644 tests/gnrc_sock_udp/constants.h create mode 100644 tests/gnrc_sock_udp/main.c create mode 100644 tests/gnrc_sock_udp/stack.c create mode 100644 tests/gnrc_sock_udp/stack.h create mode 100755 tests/gnrc_sock_udp/tests/01-run.py diff --git a/tests/gnrc_sock_udp/Makefile b/tests/gnrc_sock_udp/Makefile new file mode 100644 index 000000000..bbfdfc3a7 --- /dev/null +++ b/tests/gnrc_sock_udp/Makefile @@ -0,0 +1,21 @@ +APPLICATION = gnrc_sock_udp + +BOARD ?= native + +RIOTBASE ?= $(CURDIR)/../.. + +USEMODULE += gnrc_sock_check_reuse +USEMODULE += gnrc_sock_udp +USEMODULE += gnrc_ipv6 +USEMODULE += ps + +CFLAGS += -DDEVELHELP +CFLAGS += -DGNRC_PKTBUF_SIZE=200 +CFLAGS += -DTEST_SUITES + +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include + +test: + ./tests/01-run.py diff --git a/tests/gnrc_sock_udp/constants.h b/tests/gnrc_sock_udp/constants.h new file mode 100644 index 000000000..fefe41663 --- /dev/null +++ b/tests/gnrc_sock_udp/constants.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup + * @ingroup + * @brief + * @{ + * + * @file + * @brief + * + * @author Martine Lenders + */ +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#define _TEST_PORT_LOCAL (0x2c94) +#define _TEST_PORT_REMOTE (0xa615) +#define _TEST_NETIF (31) +#define _TEST_TIMEOUT (1000000U) +#define _TEST_ADDR_LOCAL { 0x7f, 0xc4, 0x11, 0x5a, 0xe6, 0x91, 0x8d, 0x5d, \ + 0x8c, 0xd1, 0x47, 0x07, 0xb7, 0x6f, 0x9b, 0x48 } +#define _TEST_ADDR_REMOTE { 0xe8, 0xb3, 0xb2, 0xe6, 0x70, 0xd4, 0x55, 0xba, \ + 0x93, 0xcf, 0x11, 0xe1, 0x72, 0x44, 0xc5, 0x9d } +#define _TEST_ADDR_WRONG { 0x2a, 0xce, 0x5d, 0x4e, 0xc8, 0xbf, 0x86, 0xf7, \ + 0x85, 0x49, 0xb4, 0x19, 0xf2, 0x28, 0xde, 0x9b } + +#ifdef __cplusplus +} +#endif + +#endif /* CONSTANTS_H_ */ +/** @} */ diff --git a/tests/gnrc_sock_udp/main.c b/tests/gnrc_sock_udp/main.c new file mode 100644 index 000000000..043eae3e2 --- /dev/null +++ b/tests/gnrc_sock_udp/main.c @@ -0,0 +1,705 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test for UDP socks + * + * @author Martine Lenders + * @} + */ + +#include +#include +#include +#include + +#include "net/af.h" +#include "net/sock/udp.h" +#include "xtimer.h" + +#include "constants.h" +#include "stack.h" + +#define _TEST_BUFFER_SIZE (128) + +static uint8_t _test_buffer[_TEST_BUFFER_SIZE]; +static sock_udp_t _sock, _sock2; + +#define CALL(fn) puts("Calling " # fn); fn; tear_down() + +static void tear_down(void) +{ + sock_udp_close(&_sock); + memset(&_sock, 0, sizeof(_sock)); +} + +#ifdef MODULE_GNRC_SOCK_CHECK_REUSE +static void test_sock_udp_create__EADDRINUSE(void) +{ + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, 0)); + assert(-EADDRINUSE == sock_udp_create(&_sock2, &local, NULL, 0)); +} +#endif + +static void test_sock_udp_create__EAFNOSUPPORT(void) +{ + /* port may not be NULL according to doc */ + static const sock_udp_ep_t local = { .family = AF_UNSPEC, + .port = _TEST_PORT_LOCAL }; + /* port may not be NULL according to doc */ + static const sock_udp_ep_t remote = { .family = AF_UNSPEC, + .port = _TEST_PORT_REMOTE }; + + assert(-EAFNOSUPPORT == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(-EAFNOSUPPORT == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_udp_create__EINVAL_addr(void) +{ + /* port may not be NULL according to doc */ + static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + /* port may not be NULL according to doc */ + static const sock_udp_ep_t remote = { .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_REMOTE }; + + assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_udp_create__EINVAL_netif(void) +{ + /* port may not be NULL according to doc */ + static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + /* port may not be NULL according to doc */ + static const sock_udp_ep_t remote = { .family = AF_INET6, + .netif = (_TEST_NETIF + 1), + .port = _TEST_PORT_REMOTE, + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + + assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_udp_create__no_endpoints(void) +{ + sock_udp_ep_t ep; + + assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); + assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep)); + assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep)); +} + +static void test_sock_udp_create__only_local(void) +{ + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + sock_udp_ep_t ep; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_udp_get_local(&_sock, &ep)); + assert(AF_INET6 == ep.family); + assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6, + sizeof(ipv6_addr_t)) == 0); + assert(SOCK_ADDR_ANY_NETIF == ep.netif); + assert(_TEST_PORT_LOCAL == ep.port); + assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep)); +} + +static void test_sock_udp_create__only_local_reuse_ep(void) +{ + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + sock_udp_ep_t ep, ep2; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_udp_create(&_sock2, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_udp_get_local(&_sock, &ep)); + assert(0 == sock_udp_get_local(&_sock2, &ep2)); + assert(AF_INET6 == ep.family); + assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6, + sizeof(ipv6_addr_t)) == 0); + assert(SOCK_ADDR_ANY_NETIF == ep.netif); + assert(_TEST_PORT_LOCAL == ep.port); + assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep)); + assert(AF_INET6 == ep2.family); + assert(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6, + sizeof(ipv6_addr_t)) == 0); + assert(SOCK_ADDR_ANY_NETIF == ep2.netif); + assert(_TEST_PORT_LOCAL == ep2.port); + assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep2)); + sock_udp_close(&_sock2); +} + +static void test_sock_udp_create__only_remote(void) +{ + static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + sock_udp_ep_t ep; + + assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); + assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep)); + assert(0 == sock_udp_get_remote(&_sock, &ep)); + assert(AF_INET6 == ep.family); + assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); + assert(SOCK_ADDR_ANY_NETIF == ep.netif); + assert(_TEST_PORT_REMOTE == ep.port); +} + +static void test_sock_udp_create__full(void) +{ + static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + sock_udp_ep_t ep; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_udp_get_local(&_sock, &ep)); + assert(AF_INET6 == ep.family); + assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6, + sizeof(ipv6_addr_t)) == 0); + assert(_TEST_NETIF == ep.netif); + assert(_TEST_PORT_LOCAL == ep.port); + assert(0 == sock_udp_get_remote(&_sock, &ep)); + assert(AF_INET6 == ep.family); + assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0); + assert(SOCK_ADDR_ANY_NETIF == ep.netif); + assert(_TEST_PORT_REMOTE == ep.port); +} + +static void test_sock_udp_recv__EADDRNOTAVAIL(void) +{ + assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); + + assert(-EADDRNOTAVAIL == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), + SOCK_NO_TIMEOUT, NULL)); +} + +static void test_sock_udp_recv__EAGAIN(void) +{ + static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + + assert(-EAGAIN == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), + 0, NULL)); +} + +static void test_sock_udp_recv__ENOBUFS(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), _TEST_NETIF)); + assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT, + NULL)); + assert(_check_net()); +} + +static void test_sock_udp_recv__EPROTO(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(-EPROTO == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer), + SOCK_NO_TIMEOUT, NULL)); + assert(_check_net()); +} + +static void test_sock_udp_recv__ETIMEDOUT(void) +{ + static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + + puts(" * Calling sock_udp_recv()"); + assert(-ETIMEDOUT == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), _TEST_TIMEOUT, + NULL)); + printf(" * (timed out with timeout %lu)\n", (long unsigned)_TEST_TIMEOUT); +} + +static void test_sock_udp_recv__socketed(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), + SOCK_NO_TIMEOUT, NULL)); + assert(_check_net()); +} + +static void test_sock_udp_recv__socketed_with_remote(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + sock_udp_ep_t result; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), + SOCK_NO_TIMEOUT, &result)); + assert(AF_INET6 == result.family); + assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0); + assert(_TEST_PORT_REMOTE == result.port); + assert(_TEST_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_udp_recv__unsocketed(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), + SOCK_NO_TIMEOUT, NULL)); + assert(_check_net()); +} + +static void test_sock_udp_recv__unsocketed_with_remote(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + sock_udp_ep_t result; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), + SOCK_NO_TIMEOUT, &result)); + assert(AF_INET6 == result.family); + assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0); + assert(_TEST_PORT_REMOTE == result.port); + assert(_TEST_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_udp_recv__with_timeout(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + sock_udp_ep_t result; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), _TEST_TIMEOUT, + &result)); + assert(AF_INET6 == result.family); + assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0); + assert(_TEST_PORT_REMOTE == result.port); + assert(_TEST_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_udp_recv__non_blocking(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const sock_udp_ep_t local = { .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + sock_udp_ep_t result; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE, + _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), + _TEST_NETIF)); + assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer, + sizeof(_test_buffer), 0, &result)); + assert(AF_INET6 == result.family); + assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0); + assert(_TEST_PORT_REMOTE == result.port); + assert(_TEST_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_udp_send__EAFNOSUPPORT(void) +{ + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET, + .port = _TEST_PORT_REMOTE }; + + assert(-EAFNOSUPPORT == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_net()); +} + +static void test_sock_udp_send__EINVAL_addr(void) +{ + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .netif = _TEST_NETIF }; + static const sock_udp_ep_t remote = { .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .netif = _TEST_NETIF }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote)); + assert(_check_net()); +} + +static void test_sock_udp_send__EINVAL_netif(void) +{ + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .netif = _TEST_NETIF }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE, + .netif = _TEST_NETIF + 1 }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote)); + assert(_check_net()); +} + +static void test_sock_udp_send__EINVAL_port(void) +{ + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(-EINVAL == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), &remote)); + assert(_check_net()); +} + +static void test_sock_udp_send__ENOTCONN(void) +{ + assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); + assert(-ENOTCONN == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), NULL)); + assert(_check_net()); +} + +static void test_sock_udp_send__socketed_no_local_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + NULL)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + SOCK_ADDR_ANY_NETIF, true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__socketed_no_netif(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + NULL)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + SOCK_ADDR_ANY_NETIF, false)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__socketed_no_local(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + NULL)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF, + true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__socketed(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + NULL)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + _TEST_NETIF, false)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__socketed_other_remote(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t sock_remote = { .addr = { .ipv6 = _TEST_ADDR_WRONG }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE + _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, &sock_remote, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + _TEST_NETIF, false)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__unsocketed_no_local_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + SOCK_ADDR_ANY_NETIF, true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__unsocketed_no_netif(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + SOCK_ADDR_ANY_NETIF, false)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__unsocketed_no_local(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF, + true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__unsocketed(void) +{ + static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL }; + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_LOCAL }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + _TEST_NETIF, false)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__no_sock_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .port = _TEST_PORT_REMOTE }; + + assert(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + SOCK_ADDR_ANY_NETIF, true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_udp_send__no_sock(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF, + .port = _TEST_PORT_REMOTE }; + + assert(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), + &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0, + _TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), + _TEST_NETIF, true)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +int main(void) +{ + _net_init(); + tear_down(); +#ifdef MODULE_GNRC_SOCK_CHECK_REUSE + CALL(test_sock_udp_create__EADDRINUSE()); +#endif + CALL(test_sock_udp_create__EAFNOSUPPORT()); + CALL(test_sock_udp_create__EINVAL_addr()); + CALL(test_sock_udp_create__EINVAL_netif()); + CALL(test_sock_udp_create__no_endpoints()); + CALL(test_sock_udp_create__only_local()); + CALL(test_sock_udp_create__only_local_reuse_ep()); + CALL(test_sock_udp_create__only_remote()); + CALL(test_sock_udp_create__full()); + /* sock_udp_close() is tested in tear_down() */ + /* sock_udp_get_local() is tested in sock_udp_create() tests */ + /* sock_udp_get_remote() is tested in sock_udp_create() tests */ + CALL(test_sock_udp_recv__EADDRNOTAVAIL()); + CALL(test_sock_udp_recv__EAGAIN()); + CALL(test_sock_udp_recv__ENOBUFS()); + CALL(test_sock_udp_recv__EPROTO()); + CALL(test_sock_udp_recv__ETIMEDOUT()); + CALL(test_sock_udp_recv__socketed()); + CALL(test_sock_udp_recv__socketed_with_remote()); + CALL(test_sock_udp_recv__unsocketed()); + CALL(test_sock_udp_recv__unsocketed_with_remote()); + CALL(test_sock_udp_recv__with_timeout()); + CALL(test_sock_udp_recv__non_blocking()); + _prepare_send_checks(); + CALL(test_sock_udp_send__EAFNOSUPPORT()); + CALL(test_sock_udp_send__EINVAL_addr()); + CALL(test_sock_udp_send__EINVAL_netif()); + CALL(test_sock_udp_send__EINVAL_port()); + CALL(test_sock_udp_send__ENOTCONN()); + CALL(test_sock_udp_send__socketed_no_local_no_netif()); + CALL(test_sock_udp_send__socketed_no_netif()); + CALL(test_sock_udp_send__socketed_no_local()); + CALL(test_sock_udp_send__socketed()); + CALL(test_sock_udp_send__socketed_other_remote()); + CALL(test_sock_udp_send__unsocketed_no_local_no_netif()); + CALL(test_sock_udp_send__unsocketed_no_netif()); + CALL(test_sock_udp_send__unsocketed_no_local()); + CALL(test_sock_udp_send__unsocketed()); + CALL(test_sock_udp_send__no_sock_no_netif()); + CALL(test_sock_udp_send__no_sock()); + + puts("ALL TESTS SUCCESSFUL"); + + return 0; +} diff --git a/tests/gnrc_sock_udp/stack.c b/tests/gnrc_sock_udp/stack.c new file mode 100644 index 000000000..f9a556abc --- /dev/null +++ b/tests/gnrc_sock_udp/stack.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + + +#include "msg.h" +#include "net/gnrc/ipv6.h" +#include "net/gnrc/netif/hdr.h" +#include "net/gnrc/netreg.h" +#include "net/gnrc/udp.h" +#include "net/sock.h" +#include "sched.h" + +#include "stack.h" + +#define _MSG_QUEUE_SIZE (4) + +static msg_t _msg_queue[_MSG_QUEUE_SIZE]; +static gnrc_netreg_entry_t _udp_handler; + +void _net_init(void) +{ + msg_init_queue(_msg_queue, _MSG_QUEUE_SIZE); + gnrc_netreg_entry_init_pid(&_udp_handler, GNRC_NETREG_DEMUX_CTX_ALL, + sched_active_pid); +} + +void _prepare_send_checks(void) +{ + gnrc_netreg_register(GNRC_NETTYPE_UDP, &_udp_handler); +} + +static gnrc_pktsnip_t *_build_udp_packet(const ipv6_addr_t *src, + const ipv6_addr_t *dst, + uint16_t src_port, uint16_t dst_port, + void *data, size_t data_len, + uint16_t netif) +{ + gnrc_pktsnip_t *netif_hdr, *ipv6, *udp; + udp_hdr_t *udp_hdr; + ipv6_hdr_t *ipv6_hdr; + uint16_t csum = 0; + + if ((netif > INT16_MAX) || ((sizeof(udp_hdr_t) + data_len) > UINT16_MAX)) { + return NULL; + } + + udp = gnrc_pktbuf_add(NULL, NULL, sizeof(udp_hdr_t) + data_len, + GNRC_NETTYPE_UNDEF); + if (udp == NULL) { + return NULL; + } + udp_hdr = udp->data; + udp_hdr->src_port = byteorder_htons(src_port); + udp_hdr->dst_port = byteorder_htons(dst_port); + udp_hdr->length = byteorder_htons((uint16_t)udp->size); + udp_hdr->checksum.u16 = 0; + memcpy(udp_hdr + 1, data, data_len); + csum = inet_csum(csum, (uint8_t *)udp->data, udp->size); + ipv6 = gnrc_ipv6_hdr_build(NULL, src, dst); + if (ipv6 == NULL) { + return NULL; + } + ipv6_hdr = ipv6->data; + ipv6_hdr->len = byteorder_htons((uint16_t)udp->size); + ipv6_hdr->nh = PROTNUM_UDP; + ipv6_hdr->hl = 64; + csum = ipv6_hdr_inet_csum(csum, ipv6_hdr, PROTNUM_UDP, (uint16_t)udp->size); + if (csum == 0xffff) { + udp_hdr->checksum = byteorder_htons(csum); + } + else { + udp_hdr->checksum = byteorder_htons(~csum); + } + LL_APPEND(udp, ipv6); + netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + if (netif_hdr == NULL) { + return NULL; + } + ((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = (kernel_pid_t)netif; + LL_APPEND(udp, netif_hdr); + return udp; +} + + +bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst, + uint16_t src_port, uint16_t dst_port, + void *data, size_t data_len, uint16_t netif) +{ + gnrc_pktsnip_t *pkt = _build_udp_packet(src, dst, src_port, dst_port, + data, data_len, netif); + + if (pkt == NULL) { + return false; + } + return (gnrc_netapi_dispatch_receive(GNRC_NETTYPE_UDP, + GNRC_NETREG_DEMUX_CTX_ALL, pkt) > 0); +} + +bool _check_net(void) +{ + return (gnrc_pktbuf_is_sane() && gnrc_pktbuf_is_empty()); +} + +static inline bool _res(gnrc_pktsnip_t *pkt, bool res) +{ + gnrc_pktbuf_release(pkt); + return res; +} + +bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst, + uint16_t src_port, uint16_t dst_port, + void *data, size_t data_len, uint16_t iface, + bool random_src_port) +{ + gnrc_pktsnip_t *pkt, *ipv6, *udp; + ipv6_hdr_t *ipv6_hdr; + udp_hdr_t *udp_hdr; + msg_t msg; + + msg_receive(&msg); + if (msg.type != GNRC_NETAPI_MSG_TYPE_SND) { + return false; + } + pkt = msg.content.ptr; + if (iface != SOCK_ADDR_ANY_NETIF) { + gnrc_netif_hdr_t *netif_hdr; + + if (pkt->type != GNRC_NETTYPE_NETIF) { + return _res(pkt, false); + } + netif_hdr = pkt->data; + if (netif_hdr->if_pid != iface) { + return _res(pkt, false); + } + ipv6 = pkt->next; + } + else { + ipv6 = pkt; + } + if (ipv6->type != GNRC_NETTYPE_IPV6) { + return _res(pkt, false); + } + ipv6_hdr = ipv6->data; + udp = gnrc_pktsnip_search_type(ipv6, GNRC_NETTYPE_UDP); + if (udp == NULL) { + return _res(pkt, false); + } + udp_hdr = udp->data; + return _res(pkt, (memcmp(src, &ipv6_hdr->src, sizeof(ipv6_addr_t)) == 0) && + (memcmp(dst, &ipv6_hdr->dst, sizeof(ipv6_addr_t)) == 0) && + (ipv6_hdr->nh == PROTNUM_UDP) && + (random_src_port || (src_port == byteorder_ntohs(udp_hdr->src_port))) && + (dst_port == byteorder_ntohs(udp_hdr->dst_port)) && + (udp->next != NULL) && + (data_len == udp->next->size) && + (memcmp(data, udp->next->data, data_len) == 0)); +} + + +/** @} */ diff --git a/tests/gnrc_sock_udp/stack.h b/tests/gnrc_sock_udp/stack.h new file mode 100644 index 000000000..415057a3a --- /dev/null +++ b/tests/gnrc_sock_udp/stack.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup + * @ingroup + * @brief + * @{ + * + * @file + * @brief + * + * @author Martine Lenders + */ +#ifndef STACK_H_ +#define STACK_H_ + +#include +#include + +#include "net/ipv6/addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initializes networking for tests + */ +void _net_init(void); + +/** + * @brief Does what ever preparations are needed to check the packets sent + */ +void _prepare_send_checks(void); + +/** + * @brief Injects a received UDP packet into the stack + * + * @param[in] src The source address of the UDP packet + * @param[in] dst The destination address of the UDP packet + * @param[in] src_port The source port of the UDP packet + * @param[in] dst_port The destination port of the UDP packet + * @param[in] data The payload of the UDP packet + * @param[in] data_len The payload length of the UDP packet + * @param[in] netif The interface the packet came over + * + * @return true, if packet was successfully injected + * @return false, if an error occured during injection + */ +bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst, + uint16_t src_port, uint16_t dst_port, + void *data, size_t data_len, uint16_t netif); + +/** + * @brief Checks networking state (e.g. packet buffer state) + * + * @return true, if networking component is still in valid state + * @return false, if networking component is in an invalid state + */ +bool _check_net(void); + +/** + * @brief Checks if a UDP packet was sent by the networking component + * + * @param[in] src Expected source address of the UDP packet + * @param[in] dst Expected destination address of the UDP packet + * @param[in] src_port Expected source port of the UDP packet + * @param[in] dst_port Expected destination port of the UDP packet + * @param[in] data Expected payload of the UDP packet + * @param[in] data_len Expected payload length of the UDP packet + * @param[in] netif Expected interface the packet is supposed to + * be send over + * @param[in] random_src_port Do not check source port, it might be random + * + * @return true, if all parameters match as expected + * @return false, if not. + */ +bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst, + uint16_t src_port, uint16_t dst_port, + void *data, size_t data_len, uint16_t netif, + bool random_src_port); + + +#ifdef __cplusplus +} +#endif + +#endif /* STACK_H_ */ +/** @} */ diff --git a/tests/gnrc_sock_udp/tests/01-run.py b/tests/gnrc_sock_udp/tests/01-run.py new file mode 100755 index 000000000..8d0df09d6 --- /dev/null +++ b/tests/gnrc_sock_udp/tests/01-run.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 Kaspar Schleiser +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import os +import sys + +from datetime import datetime + +sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) +import testrunner + +class InvalidTimeout(Exception): + pass + +def testfunc(child): + child.expect_exact(u"Calling test_sock_udp_create__EADDRINUSE()") + child.expect_exact(u"Calling test_sock_udp_create__EAFNOSUPPORT()") + child.expect_exact(u"Calling test_sock_udp_create__EINVAL_addr()") + child.expect_exact(u"Calling test_sock_udp_create__EINVAL_netif()") + child.expect_exact(u"Calling test_sock_udp_create__no_endpoints()") + child.expect_exact(u"Calling test_sock_udp_create__only_local()") + child.expect_exact(u"Calling test_sock_udp_create__only_local_reuse_ep()") + child.expect_exact(u"Calling test_sock_udp_create__only_remote()") + child.expect_exact(u"Calling test_sock_udp_create__full()") + child.expect_exact(u"Calling test_sock_udp_recv__EADDRNOTAVAIL()") + child.expect_exact(u"Calling test_sock_udp_recv__EAGAIN()") + child.expect_exact(u"Calling test_sock_udp_recv__ENOBUFS()") + child.expect_exact(u"Calling test_sock_udp_recv__EPROTO()") + child.expect_exact(u"Calling test_sock_udp_recv__ETIMEDOUT()") + child.match # get to ensure program reached that point + start = datetime.now() + child.expect_exact(u" * Calling sock_udp_recv()") + child.expect(u" \\* \\(timed out with timeout (\\d+)\\)") + exp_diff = int(child.match.group(1)) + stop = datetime.now() + diff = (stop - start) + diff = (diff.seconds * 1000000) + diff.microseconds + # fail within 5% of expected + if diff > (exp_diff + (exp_diff * 0.05)) or \ + diff < (exp_diff - (exp_diff * 0.05)): + raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff)); + else: + print("Timed out correctly: %d (expected %d)" % (diff, exp_diff)) + child.expect_exact(u"Calling test_sock_udp_recv__socketed()") + child.expect_exact(u"Calling test_sock_udp_recv__socketed_with_remote()") + child.expect_exact(u"Calling test_sock_udp_recv__unsocketed()") + child.expect_exact(u"Calling test_sock_udp_recv__unsocketed_with_remote()") + child.expect_exact(u"Calling test_sock_udp_recv__with_timeout()") + child.expect_exact(u"Calling test_sock_udp_recv__non_blocking()") + child.expect_exact(u"Calling test_sock_udp_send__EAFNOSUPPORT()") + child.expect_exact(u"Calling test_sock_udp_send__EINVAL_addr()") + child.expect_exact(u"Calling test_sock_udp_send__EINVAL_netif()") + child.expect_exact(u"Calling test_sock_udp_send__EINVAL_port()") + child.expect_exact(u"Calling test_sock_udp_send__ENOTCONN()") + child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local_no_netif()") + child.expect_exact(u"Calling test_sock_udp_send__socketed_no_netif()") + child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local()") + child.expect_exact(u"Calling test_sock_udp_send__socketed()") + child.expect_exact(u"Calling test_sock_udp_send__socketed_other_remote()") + child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local_no_netif()") + child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_netif()") + child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local()") + child.expect_exact(u"Calling test_sock_udp_send__unsocketed()") + child.expect_exact(u"Calling test_sock_udp_send__no_sock_no_netif()") + child.expect_exact(u"Calling test_sock_udp_send__no_sock()") + child.expect_exact(u"ALL TESTS SUCCESSFUL") + +if __name__ == "__main__": + sys.exit(testrunner.run(testfunc))