From 149d29bc6366969d61fdf230a8725cabe7dfcd25 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Thu, 25 Aug 2016 17:53:57 +0200 Subject: [PATCH] tests: provide gnrc_sock_ip tests --- sys/net/gnrc/sock/ip/gnrc_sock_ip.c | 4 +- tests/gnrc_sock_ip/Makefile | 20 + tests/gnrc_sock_ip/constants.h | 43 ++ tests/gnrc_sock_ip/main.c | 640 ++++++++++++++++++++++++++++ tests/gnrc_sock_ip/stack.c | 142 ++++++ tests/gnrc_sock_ip/stack.h | 90 ++++ tests/gnrc_sock_ip/tests/01-run.py | 70 +++ 7 files changed, 1007 insertions(+), 2 deletions(-) create mode 100644 tests/gnrc_sock_ip/Makefile create mode 100644 tests/gnrc_sock_ip/constants.h create mode 100644 tests/gnrc_sock_ip/main.c create mode 100644 tests/gnrc_sock_ip/stack.c create mode 100644 tests/gnrc_sock_ip/stack.h create mode 100755 tests/gnrc_sock_ip/tests/01-run.py diff --git a/sys/net/gnrc/sock/ip/gnrc_sock_ip.c b/sys/net/gnrc/sock/ip/gnrc_sock_ip.c index b5673c8338672..725da7500801e 100644 --- a/sys/net/gnrc/sock/ip/gnrc_sock_ip.c +++ b/sys/net/gnrc/sock/ip/gnrc_sock_ip.c @@ -43,8 +43,6 @@ int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, } memcpy(&sock->local, local, sizeof(sock_ip_t)); } - gnrc_sock_create(&sock->reg, GNRC_NETTYPE_IPV6, - proto); memset(&sock->remote, 0, sizeof(sock_ip_t)); if (remote != NULL) { if (gnrc_af_not_supported(remote->family)) { @@ -55,6 +53,8 @@ int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, } memcpy(&sock->remote, remote, sizeof(sock_ip_t)); } + gnrc_sock_create(&sock->reg, GNRC_NETTYPE_IPV6, + proto); sock->flags = flags; return 0; } diff --git a/tests/gnrc_sock_ip/Makefile b/tests/gnrc_sock_ip/Makefile new file mode 100644 index 0000000000000..8c06d87bbe175 --- /dev/null +++ b/tests/gnrc_sock_ip/Makefile @@ -0,0 +1,20 @@ +APPLICATION = gnrc_sock_ip + +BOARD ?= native + +RIOTBASE ?= $(CURDIR)/../.. + +USEMODULE += gnrc_sock_ip +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_ip/constants.h b/tests/gnrc_sock_ip/constants.h new file mode 100644 index 0000000000000..88776e4ee242e --- /dev/null +++ b/tests/gnrc_sock_ip/constants.h @@ -0,0 +1,43 @@ +/* + * 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_PROTO (254) /* https://tools.ietf.org/html/rfc3692#section-2.1 */ +#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_ip/main.c b/tests/gnrc_sock_ip/main.c new file mode 100644 index 0000000000000..7938d5ea1af99 --- /dev/null +++ b/tests/gnrc_sock_ip/main.c @@ -0,0 +1,640 @@ +/* + * 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 examples + * @{ + * + * @file + * @brief Test for raw IP socks + * + * @author Martine Lenders + * @} + */ + +#include +#include +#include +#include + +#include "net/af.h" +#include "net/sock/ip.h" +#include "xtimer.h" + +#include "constants.h" +#include "stack.h" + +#define _TEST_BUFFER_SIZE (128) + +#define CALL(fn) puts("Calling " # fn); fn; tear_down() + +static sock_ip_t _sock, _sock2; +static uint8_t _test_buffer[_TEST_BUFFER_SIZE]; + +static void tear_down(void) +{ + sock_ip_close(&_sock); + memset(&_sock, 0, sizeof(_sock)); +} + +static void test_sock_ip_create__EAFNOSUPPORT(void) +{ + static const sock_ip_ep_t local = { .family = AF_UNSPEC }; + static const sock_ip_ep_t remote = { .family = AF_UNSPEC }; + + assert(-EAFNOSUPPORT == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-EAFNOSUPPORT == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_ip_create__EINVAL_addr(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .family = AF_INET6, + .netif = _TEST_NETIF }; + + assert(-EINVAL == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_ip_create__EINVAL_netif(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .family = AF_INET6, + .netif = (_TEST_NETIF + 1), + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + + assert(-EINVAL == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); +} + +static void test_sock_ip_create__no_endpoints(void) +{ + sock_ip_ep_t ep; + + assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-EADDRNOTAVAIL == sock_ip_get_local(&_sock, &ep)); + assert(-ENOTCONN == sock_ip_get_remote(&_sock, &ep)); +} + +static void test_sock_ip_create__only_local(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6 }; + sock_ip_ep_t ep; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_ip_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(-ENOTCONN == sock_ip_get_remote(&_sock, &ep)); +} + +static void test_sock_ip_create__only_local_reuse_ep(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6 }; + sock_ip_ep_t ep, ep2; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_ip_create(&_sock2, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_ip_get_local(&_sock, &ep)); + assert(0 == sock_ip_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(-ENOTCONN == sock_ip_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(-ENOTCONN == sock_ip_get_remote(&_sock, &ep2)); + sock_ip_close(&_sock2); +} + +static void test_sock_ip_create__only_remote(void) +{ + static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .family = AF_INET6, + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + sock_ip_ep_t ep; + + assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-EADDRNOTAVAIL == sock_ip_get_local(&_sock, &ep)); + assert(0 == sock_ip_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); +} + +static void test_sock_ip_create__full(void) +{ + static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .family = AF_INET6, + .addr = { .ipv6 = _TEST_ADDR_REMOTE } }; + sock_ip_ep_t ep; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(0 == sock_ip_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(0 == sock_ip_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); +} + +static void test_sock_ip_recv__EADDRNOTAVAIL(void) +{ + assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + + assert(-EADDRNOTAVAIL == sock_ip_recv(&_sock, _test_buffer, + sizeof(_test_buffer), SOCK_NO_TIMEOUT, + NULL)); +} + +static void test_sock_ip_recv__EAGAIN(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + + assert(-EAGAIN == sock_ip_recv(&_sock, _test_buffer, sizeof(_test_buffer), + 0, NULL)); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(-ENOBUFS == sock_ip_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT, + NULL)); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(-EPROTO == sock_ip_recv(&_sock, _test_buffer, sizeof(_test_buffer), + SOCK_NO_TIMEOUT, NULL)); + assert(_check_net()); +} + +static void test_sock_ip_recv__ETIMEDOUT(void) +{ + static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + + puts(" * Calling sock_ip_recv()"); + assert(-ETIMEDOUT == sock_ip_recv(&_sock, _test_buffer, + sizeof(_test_buffer), _TEST_TIMEOUT, + NULL)); + printf(" * (timed out with timeout %u)\n", _TEST_TIMEOUT); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer, + sizeof(_test_buffer), SOCK_NO_TIMEOUT, + NULL)); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + sock_ip_ep_t result; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_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_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer, + sizeof(_test_buffer), SOCK_NO_TIMEOUT, + NULL)); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + sock_ip_ep_t result; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_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_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + sock_ip_ep_t result; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_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_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .family = AF_INET6 }; + sock_ip_ep_t result; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + assert(sizeof("ABCD") == sock_ip_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_NETIF == result.netif); + assert(_check_net()); +} + +static void test_sock_ip_send__EAFNOSUPPORT(void) +{ + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET }; + + assert(-EAFNOSUPPORT == sock_ip_send(NULL, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_net()); +} + +static void test_sock_ip_send__EINVAL_addr(void) +{ + static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .family = AF_INET6, + .netif = _TEST_NETIF }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-EINVAL == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), _TEST_PROTO, + &remote)); + assert(_check_net()); +} + +static void test_sock_ip_send__EINVAL_netif(void) +{ + static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF + 1 }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-EINVAL == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), _TEST_PROTO, + &remote)); + assert(_check_net()); +} + +static void test_sock_ip_send__ENOTCONN(void) +{ + assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(-ENOTCONN == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, NULL)); + assert(_check_net()); +} + +static void test_sock_ip_send__socketed_no_local_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, NULL)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), SOCK_ADDR_ANY_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, NULL)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), SOCK_ADDR_ANY_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_send__socketed_no_local(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + + assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, NULL)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, NULL)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + static const sock_ip_ep_t sock_remote = { .addr = { .ipv6 = _TEST_ADDR_WRONG }, + .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, &sock_remote, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_send__unsocketed_no_local_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), SOCK_ADDR_ANY_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6 }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), SOCK_ADDR_ANY_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_send__unsocketed_no_local(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + + assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_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_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, + SOCK_FLAGS_REUSE_EP)); + assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_send__no_sock_no_netif(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6 }; + + assert(sizeof("ABCD") == sock_ip_send(NULL, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), SOCK_ADDR_ANY_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +static void test_sock_ip_send__no_sock(void) +{ + static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE }; + static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE }, + .family = AF_INET6, + .netif = _TEST_NETIF }; + + assert(sizeof("ABCD") == sock_ip_send(NULL, "ABCD", sizeof("ABCD"), + _TEST_PROTO, &remote)); + assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD", + sizeof("ABCD"), _TEST_NETIF)); + xtimer_usleep(1000); /* let GNRC stack finish */ + assert(_check_net()); +} + +int main(void) +{ + _net_init(); + tear_down(); + /* EADDRINUSE does not apply for GNRC */ + CALL(test_sock_ip_create__EAFNOSUPPORT()); + CALL(test_sock_ip_create__EINVAL_addr()); + CALL(test_sock_ip_create__EINVAL_netif()); + /* EPROTONOSUPPORT does not apply for gnrc_ipv6 */ + CALL(test_sock_ip_create__no_endpoints()); + CALL(test_sock_ip_create__only_local()); + CALL(test_sock_ip_create__only_local_reuse_ep()); + CALL(test_sock_ip_create__only_remote()); + CALL(test_sock_ip_create__full()); + /* sock_ip_close() is tested in tear_down() */ + /* sock_ip_get_local() is tested in sock_ip_create() tests */ + /* sock_ip_get_remote() is tested in sock_ip_create() tests */ + CALL(test_sock_ip_recv__EADDRNOTAVAIL()); + CALL(test_sock_ip_recv__EAGAIN()); + CALL(test_sock_ip_recv__ENOBUFS()); + CALL(test_sock_ip_recv__EPROTO()); + CALL(test_sock_ip_recv__ETIMEDOUT()); + CALL(test_sock_ip_recv__socketed()); + CALL(test_sock_ip_recv__socketed_with_remote()); + CALL(test_sock_ip_recv__unsocketed()); + CALL(test_sock_ip_recv__unsocketed_with_remote()); + CALL(test_sock_ip_recv__with_timeout()); + CALL(test_sock_ip_recv__non_blocking()); + _prepare_send_checks(); + CALL(test_sock_ip_send__EAFNOSUPPORT()); + CALL(test_sock_ip_send__EINVAL_addr()); + CALL(test_sock_ip_send__EINVAL_netif()); + CALL(test_sock_ip_send__ENOTCONN()); + /* EPROTOTYPE does not apply for gnrc_ipv6 */ + CALL(test_sock_ip_send__socketed_no_local_no_netif()); + CALL(test_sock_ip_send__socketed_no_netif()); + CALL(test_sock_ip_send__socketed_no_local()); + CALL(test_sock_ip_send__socketed()); + CALL(test_sock_ip_send__socketed_other_remote()); + CALL(test_sock_ip_send__unsocketed_no_local_no_netif()); + CALL(test_sock_ip_send__unsocketed_no_netif()); + CALL(test_sock_ip_send__unsocketed_no_local()); + CALL(test_sock_ip_send__unsocketed()); + CALL(test_sock_ip_send__no_sock_no_netif()); + CALL(test_sock_ip_send__no_sock()); + + puts("ALL TESTS SUCCESSFUL"); + + return 0; +} diff --git a/tests/gnrc_sock_ip/stack.c b/tests/gnrc_sock_ip/stack.c new file mode 100644 index 0000000000000..62196798290f0 --- /dev/null +++ b/tests/gnrc_sock_ip/stack.c @@ -0,0 +1,142 @@ +/* + * 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 "stack.h" + +#include "net/gnrc/ipv6.h" +#include "net/gnrc/netif/hdr.h" +#include "net/gnrc/netreg.h" +#include "net/sock.h" +#include "sched.h" + +#define _MSG_QUEUE_SIZE (4) + +static msg_t _msg_queue[_MSG_QUEUE_SIZE]; +static gnrc_netreg_entry_t _ip_handler; + +void _net_init(void) +{ + msg_init_queue(_msg_queue, _MSG_QUEUE_SIZE); + gnrc_netreg_entry_init_pid(&_ip_handler, GNRC_NETREG_DEMUX_CTX_ALL, + sched_active_pid); +} + +void _prepare_send_checks(void) +{ + gnrc_netreg_register(GNRC_NETTYPE_IPV6, &_ip_handler); +} + +static gnrc_pktsnip_t *_build_ipv6_packet(const ipv6_addr_t *src, + const ipv6_addr_t *dst, uint8_t nh, + void *data, size_t data_len, + uint16_t netif) +{ + gnrc_pktsnip_t *netif_hdr, *ipv6, *payload; + ipv6_hdr_t *ipv6_hdr; + + if ((netif > INT16_MAX) || (data_len > UINT16_MAX)) { + return NULL; + } + + payload = gnrc_pktbuf_add(NULL, data, data_len, GNRC_NETTYPE_UNDEF); + if (payload == NULL) { + return NULL; + } + ipv6 = gnrc_ipv6_hdr_build(NULL, src, dst); + if (ipv6 == NULL) { + return NULL; + } + ipv6_hdr = ipv6->data; + ipv6_hdr->len = byteorder_htons((uint16_t)payload->size); + ipv6_hdr->nh = nh; + ipv6_hdr->hl = 64; + LL_APPEND(payload, 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(payload, netif_hdr); + return payload; +} + + +bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst, + uint8_t proto, void *data, size_t data_len, + uint16_t netif) +{ + gnrc_pktsnip_t *pkt = _build_ipv6_packet(src, dst, proto, data, data_len, + netif); + + if (pkt == NULL) { + return false; + } + /* put directly in mbox, dispatching to IPv6 would result in the packet + * being dropped, since dst is not on any interface */ + return (gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, proto, 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, + uint8_t proto, void *data, size_t data_len, + uint16_t netif) +{ + gnrc_pktsnip_t *pkt, *ipv6; + ipv6_hdr_t *ipv6_hdr; + msg_t msg; + + msg_receive(&msg); + if (msg.type != GNRC_NETAPI_MSG_TYPE_SND) { + return false; + } + pkt = msg.content.ptr; + if (netif != 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 != netif) { + return _res(pkt, false); + } + ipv6 = pkt->next; + } + else { + ipv6 = pkt; + } + if (ipv6->type != GNRC_NETTYPE_IPV6) { + return _res(pkt, false); + } + ipv6_hdr = ipv6->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 == proto) && + (ipv6->next != NULL) && + (data_len == ipv6->next->size) && + (memcmp(data, ipv6->next->data, data_len) == 0)); +} + +/** @} */ diff --git a/tests/gnrc_sock_ip/stack.h b/tests/gnrc_sock_ip/stack.h new file mode 100644 index 0000000000000..637ef466f5ec2 --- /dev/null +++ b/tests/gnrc_sock_ip/stack.h @@ -0,0 +1,90 @@ +/* + * 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 IPv6 packet into the stack + * + * @param[in] src The source address of the IPv6 packet + * @param[in] dst The destination address of the IPv6 packet + * @param[in] proto The next header field of the IPv6 packet + * @param[in] data The payload of the IPv6 packet + * @param[in] data_len The payload length of the IPv6 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, + uint8_t proto, 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 IPv6 packet was sent by the networking component + * + * @param[in] src Expected source address of the IPv6 packet + * @param[in] dst Expected destination address of the IPv6 packet + * @param[in] proto Expected next header field of the IPv6 packet + * @param[in] data Expected payload of the IPv6 packet + * @param[in] data_len Expected payload length of the IPv6 packet + * @param[in] netif Expected interface the packet is supposed to + * be send over + * + * @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, + uint8_t proto, void *data, size_t data_len, uint16_t netif); + + +#ifdef __cplusplus +} +#endif + +#endif /* STACK_H_ */ +/** @} */ diff --git a/tests/gnrc_sock_ip/tests/01-run.py b/tests/gnrc_sock_ip/tests/01-run.py new file mode 100755 index 0000000000000..a42c3f5c660e8 --- /dev/null +++ b/tests/gnrc_sock_ip/tests/01-run.py @@ -0,0 +1,70 @@ +#!/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_ip_create__EAFNOSUPPORT()") + child.expect_exact(u"Calling test_sock_ip_create__EINVAL_addr()") + child.expect_exact(u"Calling test_sock_ip_create__EINVAL_netif()") + child.expect_exact(u"Calling test_sock_ip_create__no_endpoints()") + child.expect_exact(u"Calling test_sock_ip_create__only_local()") + child.expect_exact(u"Calling test_sock_ip_create__only_local_reuse_ep()") + child.expect_exact(u"Calling test_sock_ip_create__only_remote()") + child.expect_exact(u"Calling test_sock_ip_create__full()") + child.expect_exact(u"Calling test_sock_ip_recv__EADDRNOTAVAIL()") + child.expect_exact(u"Calling test_sock_ip_recv__ENOBUFS()") + child.expect_exact(u"Calling test_sock_ip_recv__EPROTO()") + child.expect_exact(u"Calling test_sock_ip_recv__ETIMEDOUT()") + child.match # get to ensure program reached that point + start = datetime.now() + child.expect_exact(u" * Calling sock_ip_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_ip_recv__socketed()") + child.expect_exact(u"Calling test_sock_ip_recv__socketed_with_remote()") + child.expect_exact(u"Calling test_sock_ip_recv__unsocketed()") + child.expect_exact(u"Calling test_sock_ip_recv__unsocketed_with_remote()") + child.expect_exact(u"Calling test_sock_ip_recv__with_timeout()") + child.expect_exact(u"Calling test_sock_ip_send__EAFNOSUPPORT()") + child.expect_exact(u"Calling test_sock_ip_send__EINVAL_addr()") + child.expect_exact(u"Calling test_sock_ip_send__EINVAL_netif()") + child.expect_exact(u"Calling test_sock_ip_send__ENOTCONN()") + child.expect_exact(u"Calling test_sock_ip_send__socketed_no_local_no_netif()") + child.expect_exact(u"Calling test_sock_ip_send__socketed_no_netif()") + child.expect_exact(u"Calling test_sock_ip_send__socketed_no_local()") + child.expect_exact(u"Calling test_sock_ip_send__socketed()") + child.expect_exact(u"Calling test_sock_ip_send__socketed_other_remote()") + child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_local_no_netif()") + child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_netif()") + child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_local()") + child.expect_exact(u"Calling test_sock_ip_send__unsocketed()") + child.expect_exact(u"Calling test_sock_ip_send__no_sock_no_netif()") + child.expect_exact(u"Calling test_sock_ip_send__no_sock()") + child.expect_exact(u"ALL TESTS SUCCESSFUL") + +if __name__ == "__main__": + sys.exit(testrunner.run(testfunc))