Skip to content

Commit

Permalink
tests/posix_netdb: add test
Browse files Browse the repository at this point in the history
  • Loading branch information
HendrikVE committed Jan 9, 2022
1 parent 74e4a27 commit 96aeab2
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 0 deletions.
43 changes: 43 additions & 0 deletions tests/posix_netdb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
include ../Makefile.tests_common

WIFI_SSID ?= "WIFI_SSID"
WIFI_PASS ?= "WIFI_PASS"

USEMODULE += ztimer
USEMODULE += ztimer_sec

USEMODULE += posix_netdb

USEMODULE += auto_init_sock_dns

LWIP_IPV4 ?= 1
LWIP_IPV6 ?= 1

USEMODULE += lwip
USEMODULE += lwip_netdev

ifneq (0,$(LWIP_IPV4))
USEMODULE += ipv4_addr
USEMODULE += lwip_arp
USEMODULE += lwip_ipv4
USEMODULE += lwip_dhcp_auto
CFLAGS += -DETHARP_SUPPORT_STATIC_ENTRIES=1
endif

ifneq (0,$(LWIP_IPV6))
USEMODULE += ipv6_addr
USEMODULE += lwip_ipv6
USEMODULE += lwip_ipv6_autoconfig
endif

# The test requires some setup (active internet connection) so it cannot
# currently be run
TEST_ON_CI_BLACKLIST += all

include $(RIOTBASE)/Makefile.include

# needs to be put after "include $(RIOTBASE)/Makefile.include"
ifneq (,$(filter arch_esp,$(FEATURES_USED)))
CFLAGS += -DESP_WIFI_SSID=\"$(WIFI_SSID)\"
CFLAGS += -DESP_WIFI_PASS=\"$(WIFI_PASS)\"
endif
9 changes: 9 additions & 0 deletions tests/posix_netdb/Makefile.board.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Put board specific dependencies here

ifneq (,$(filter arch_esp,$(FEATURES_USED)))
USEMODULE += esp_wifi
endif

ifeq ($(BOARD),native)
USEMODULE += netdev_default
endif
11 changes: 11 additions & 0 deletions tests/posix_netdb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Test for the posix module *netdb*

## Overview

This test application tests the *posix_netdb* module.

## Run the test

The test needs an upstream connection to the internet. This is easily done with
the module *esp_wifi* on an esp32. To run the test on an esp32 you can run:\
`WIFI_SSID='"Your WiFi SSID"' WIFI_PASS='"Your WiFi Password"' BOARD=esp32-wroom-32 make flash test`
314 changes: 314 additions & 0 deletions tests/posix_netdb/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
/*
* Copyright (C) 2022 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 Posix netdb test application
*
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
*
* @}
*/

#include <stdio.h>

#include <arpa/inet.h>
#include <netdb.h>

#include "test_utils/expect.h"
#include "net/sock/dns.h"
#include "ztimer.h"

#define CALL(fn) puts("Calling " # fn); fn;

#define HOST_NAME "example.com"
#define HOST_IPV4 "93.184.216.34"
#define HOST_IPV6 "2606:2800:220:1:248:1893:25c8:1946"

static void test_posix_netdb_getaddrinfo__EAI_BADFLAGS(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints;

/* non-existing flag */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= 0xff;
expect(EAI_BADFLAGS == getaddrinfo(HOST_NAME, NULL, &hints, &result));
freeaddrinfo(result);

/* invalid combination: AI_CANONNAME && nodename == NULL */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_CANONNAME;
expect(EAI_BADFLAGS == getaddrinfo(NULL, "0", &hints, &result));
freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__EAI_FAIL(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints = { 0 };

/* res = NULL */
expect(EAI_FAIL == getaddrinfo(HOST_NAME, NULL, &hints, NULL));

/* nodename too long */
char nodename[2 * SOCK_DNS_MAX_NAME_LEN] = { 0 };
for (size_t i = 0; i < sizeof(nodename) - 1; i++) {
nodename[i] = 'a';
}
expect(EAI_FAIL == getaddrinfo(nodename, NULL, &hints, &result));
freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__EAI_FAMILY(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints;

/* non-supported address family */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC + AF_INET + AF_INET6;
expect(EAI_FAMILY == getaddrinfo(HOST_NAME, NULL, &hints, &result));
freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__EAI_NONAME(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints;

/* neither nodename nor servname given */
memset(&hints, 0, sizeof(struct addrinfo));
expect(EAI_NONAME == getaddrinfo(NULL, NULL, &hints, &result));
freeaddrinfo(result);

/* nodename and servname are empty strings */
memset(&hints, 0, sizeof(struct addrinfo));
expect(EAI_NONAME == getaddrinfo("", "", &hints, &result));
freeaddrinfo(result);

/* invalid IPv4 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_INET;
expect(EAI_NONAME == getaddrinfo("1.2.3.4.5",
NULL, &hints, &result));
freeaddrinfo(result);

/* invalid IPv6 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_INET6;
expect(EAI_NONAME == getaddrinfo("1:2:3:4:5:6:7:8:9",
NULL, &hints, &result));
freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__EAI_SERVICE(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints;

/* non-numeric port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICSERV;
expect(EAI_SERVICE == getaddrinfo(NULL, "abc", &hints, &result));
freeaddrinfo(result);

/* invalid port ( port < 0 ) */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICSERV;
expect(EAI_SERVICE == getaddrinfo(NULL, "-1", &hints, &result));
freeaddrinfo(result);

/* invalid port ( port > 65535 ) */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICSERV;
expect(EAI_SERVICE == getaddrinfo(NULL, "70000", &hints, &result));
freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__AI_NUMERICHOST(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints;

#ifdef MODULE_IPV4_ADDR
char* test_ipv4 = "1.2.3.4";
char addr4_str[INET_ADDRSTRLEN];

/* explicit IPv4 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_INET;
expect(0 == getaddrinfo(test_ipv4, NULL, &hints, &result));
expect(result != NULL);
expect(result->ai_family == AF_INET);
expect(NULL != inet_ntop(AF_INET, &((struct sockaddr_in*)(result->ai_addr))->sin_addr,
addr4_str, sizeof(addr4_str)));
expect(strcmp(addr4_str, test_ipv4) == 0);
freeaddrinfo(result);

/* auto-detect IPv4 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
expect(0 == getaddrinfo(test_ipv4, NULL, &hints, &result));
expect(result != NULL);
expect(result->ai_family == AF_INET);
expect(NULL != inet_ntop(AF_INET, &((struct sockaddr_in*)(result->ai_addr))->sin_addr,
addr4_str, sizeof(addr4_str)));
expect(strcmp(addr4_str, test_ipv4) == 0);
freeaddrinfo(result);
#endif

#ifdef MODULE_IPV6_ADDR
char* test_ipv6 = "1:2:3:4:5:6:7:8";
char addr6_str[INET6_ADDRSTRLEN];

/* explicit IPv6 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_INET6;
expect(0 == getaddrinfo(test_ipv6, NULL, &hints, &result));
expect(result != NULL);
expect(result->ai_family == AF_INET6);
expect(NULL != inet_ntop(AF_INET6, &((struct sockaddr_in6*)(result->ai_addr))->sin6_addr,
addr6_str, sizeof(addr6_str)));
expect(strcmp(addr6_str, test_ipv6) == 0);
freeaddrinfo(result);

/* auto-detect IPv6 address */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
expect(0 == getaddrinfo(test_ipv6, NULL, &hints, &result));
expect(result != NULL);
expect(result->ai_family == AF_INET6);
expect(NULL != inet_ntop(AF_INET6, &((struct sockaddr_in6*)(result->ai_addr))->sin6_addr,
addr6_str, sizeof(addr6_str)));
expect(strcmp(addr6_str, test_ipv6) == 0);
freeaddrinfo(result);
#endif
}

static void test_posix_netdb_getaddrinfo__AI_NUMERICSERV(void)
{
struct addrinfo *result = NULL;
struct addrinfo hints = { 0 };
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICSERV;

#if defined(MODULE_IPV4_ADDR)
char* ip_addr = "1.2.3.4";
hints.ai_family = AF_INET;
#elif defined(MODULE_IPV6_ADDR)
char* ip_addr = "1:2:3:4:5:6:7:8";
hints.ai_family = AF_INET6;
#endif

expect(0 == getaddrinfo(ip_addr, "12345", &hints, &result));
expect(result != NULL);
/* sockaddr_in or sockaddr_in6 does not matter if we only access the port */
expect(ntohs(((struct sockaddr_in *)result->ai_addr)->sin_port) == 12345);
freeaddrinfo(result);
}

static void _test_posix_netdb_getaddrinfo__ai_family(int family)
{
expect(family == AF_UNSPEC
|| family == AF_INET
|| family == AF_INET6);

struct addrinfo *result = NULL;
struct addrinfo hints = { 0 };
hints.ai_family = family;

expect(0 == getaddrinfo(HOST_NAME, NULL, &hints, &result));
expect(result != NULL);

if (hints.ai_family != AF_UNSPEC) {
expect(result->ai_family == hints.ai_family);
}

char addr_str[INET6_ADDRSTRLEN];

switch (result->ai_family) {
#ifdef MODULE_IPV4_ADDR
case AF_INET:
inet_ntop(AF_INET, &((struct sockaddr_in*)(result->ai_addr))->sin_addr,
addr_str, sizeof(addr_str));

expect(strcmp(addr_str, HOST_IPV4) == 0);
break;
#endif
#ifdef MODULE_IPV6_ADDR
case AF_INET6:
inet_ntop(AF_INET6, &((struct sockaddr_in6*)(result->ai_addr))->sin6_addr,
addr_str, sizeof(addr_str));

expect(strcmp(addr_str, HOST_IPV6) == 0);
break;
#endif
default:
expect(false);
}

freeaddrinfo(result);
}

static void test_posix_netdb_getaddrinfo__AF_UNSPEC(void)
{
#if defined(MODULE_IPV4_ADDR) && defined(MODULE_IPV6_ADDR)
_test_posix_netdb_getaddrinfo__ai_family(AF_UNSPEC);
#endif
}

static void test_posix_netdb_getaddrinfo__AF_INET(void)
{
#ifdef MODULE_IPV4_ADDR
_test_posix_netdb_getaddrinfo__ai_family(AF_INET);
#endif
}

static void test_posix_netdb_getaddrinfo__AF_INET6(void)
{
#ifdef MODULE_IPV6_ADDR
_test_posix_netdb_getaddrinfo__ai_family(AF_INET6);
#endif
}

int main(void)
{
/* wait until connection has been established */
ztimer_sleep(ZTIMER_SEC, 5);

/* test error return values */
CALL(test_posix_netdb_getaddrinfo__EAI_BADFLAGS());
CALL(test_posix_netdb_getaddrinfo__EAI_FAIL());
CALL(test_posix_netdb_getaddrinfo__EAI_FAMILY());
CALL(test_posix_netdb_getaddrinfo__EAI_NONAME());
CALL(test_posix_netdb_getaddrinfo__EAI_SERVICE());

/* test input flags */
CALL(test_posix_netdb_getaddrinfo__AI_NUMERICHOST());
CALL(test_posix_netdb_getaddrinfo__AI_NUMERICSERV());
/* If the requirements are not met (enabled IPv4, IPv6 or both) some of
* these tests will be simply skipped such that the python test script does
* not need to be adjusted. */
CALL(test_posix_netdb_getaddrinfo__AF_UNSPEC());
CALL(test_posix_netdb_getaddrinfo__AF_INET());
CALL(test_posix_netdb_getaddrinfo__AF_INET6());

puts("ALL TESTS SUCCESSFUL");

return 0;
}
Loading

0 comments on commit 96aeab2

Please sign in to comment.