forked from espressif/esp-protocols
193 lines
6.1 KiB
C++
193 lines
6.1 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include "gethostname.h"
|
|
#include "ifaddrs.h"
|
|
#include "esp_netif.h"
|
|
#include "esp_event.h"
|
|
#include "catch2/catch_test_macros.hpp"
|
|
#include "catch2/catch_session.hpp"
|
|
|
|
#define TEST_PORT_NUMBER 3333
|
|
#define TEST_PORT_STRING "3333"
|
|
|
|
static char buffer[64];
|
|
|
|
static esp_err_t dummy_transmit(void *h, void *buffer, size_t len)
|
|
{
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_err_t dummy_transmit_wrap(void *h, void *buffer, size_t len, void *pbuf)
|
|
{
|
|
return ESP_OK;
|
|
}
|
|
|
|
static esp_netif_t *create_test_netif(const char *if_key, uint8_t last_octet)
|
|
{
|
|
esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
|
|
esp_netif_ip_info_t ip = { };
|
|
ip.ip.addr = ESP_IP4TOADDR(1, 2, 3, last_octet);
|
|
base_cfg.ip_info = &ip;
|
|
base_cfg.if_key = if_key;
|
|
// create a dummy driver, so the netif could be started and set up
|
|
base_cfg.flags = ESP_NETIF_FLAG_AUTOUP;
|
|
esp_netif_driver_ifconfig_t driver_cfg = {};
|
|
driver_cfg.handle = (esp_netif_iodriver_handle)1;
|
|
driver_cfg.transmit = dummy_transmit;
|
|
driver_cfg.transmit_wrap = dummy_transmit_wrap;
|
|
esp_netif_config_t cfg = { .base = &base_cfg, .driver = &driver_cfg, .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA };
|
|
esp_netif_t *netif = esp_netif_new(&cfg);
|
|
// need to start the netif to be considered in tests
|
|
esp_netif_action_start(netif, nullptr, 0, nullptr);
|
|
return netif;
|
|
}
|
|
|
|
TEST_CASE("esp_getnameinfo() for IPv4", "[sock_utils]")
|
|
{
|
|
struct sockaddr_in sock_addr = {};
|
|
sock_addr.sin_family = AF_INET;
|
|
sock_addr.sin_port = htons(TEST_PORT_NUMBER); // sock_addr fields are in network byte order
|
|
REQUIRE(esp_getnameinfo((struct sockaddr *)&sock_addr, sizeof(sock_addr), buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST) == 0);
|
|
CHECK(strcmp("0.0.0.0", buffer) == 0);
|
|
CHECK(esp_getnameinfo((struct sockaddr *)&sock_addr, sizeof(sock_addr), NULL, 0, buffer, sizeof(buffer), NI_NUMERICSERV) == 0);
|
|
CHECK(strcmp(TEST_PORT_STRING, buffer) == 0);
|
|
}
|
|
|
|
TEST_CASE("esp_getnameinfo() for IPv6", "[sock_utils]")
|
|
{
|
|
struct sockaddr_in sock_addr = {};
|
|
sock_addr.sin_family = AF_INET6;
|
|
// IPv6 not supported for now
|
|
CHECK(esp_getnameinfo((struct sockaddr *)&sock_addr, sizeof(sock_addr), buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST) != 0);
|
|
}
|
|
|
|
static void test_getifaddr(int expected_nr_of_addrs)
|
|
{
|
|
struct ifaddrs *addresses, *addr;
|
|
int nr_of_addrs = 0;
|
|
|
|
CHECK(esp_getifaddrs(&addresses) != -1);
|
|
addr = addresses;
|
|
|
|
while (addr) {
|
|
++nr_of_addrs;
|
|
if (addr->ifa_addr && addr->ifa_addr->sa_family == AF_INET) { // look for IP4 addresses
|
|
struct sockaddr_in *sock_addr = (struct sockaddr_in *) addr->ifa_addr;
|
|
if (esp_getnameinfo((struct sockaddr *)sock_addr, sizeof(*sock_addr),
|
|
buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST) != 0) {
|
|
printf("esp_getnameinfo() failed\n");
|
|
} else {
|
|
printf("IPv4 address of interface \"%s\": %s\n", addr->ifa_name, buffer);
|
|
if (strcmp(addr->ifa_name, "st1") == 0) {
|
|
CHECK(strcmp("1.2.3.1", buffer) == 0);
|
|
} else if (strcmp(addr->ifa_name, "st2") == 0) {
|
|
CHECK(strcmp("1.2.3.2", buffer) == 0);
|
|
} else {
|
|
FAIL("unexpected network interface");
|
|
}
|
|
}
|
|
}
|
|
addr = addr->ifa_next;
|
|
}
|
|
// check that we got 1 address with exact content
|
|
CHECK(nr_of_addrs == expected_nr_of_addrs);
|
|
esp_freeifaddrs(addresses);
|
|
}
|
|
|
|
TEST_CASE("esp_getifaddrs() with 0, 1, and 2 addresses", "[sock_utils]")
|
|
{
|
|
test_getifaddr(0);
|
|
esp_netif_t *esp_netif = create_test_netif("station", 1); // st1
|
|
REQUIRE(esp_netif != NULL);
|
|
test_getifaddr(1);
|
|
esp_netif_t *esp_netif2 = create_test_netif("station2", 2); // st2
|
|
REQUIRE(esp_netif2 != NULL);
|
|
test_getifaddr(2);
|
|
esp_netif_destroy(esp_netif);
|
|
esp_netif_destroy(esp_netif2);
|
|
}
|
|
|
|
static void test_pipe(int read_fd, int write_fd)
|
|
{
|
|
CHECK(read_fd >= 0);
|
|
CHECK(write_fd >= 0);
|
|
CHECK(write(write_fd, buffer, 1) > 0);
|
|
CHECK(write(write_fd, buffer, 1) > 0);
|
|
CHECK(read(read_fd, buffer, 1) == 1);
|
|
CHECK(read(read_fd, buffer, 1) == 1);
|
|
}
|
|
|
|
TEST_CASE("socketpair()", "[sock_utils]")
|
|
{
|
|
int fds[2];
|
|
CHECK(esp_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
|
|
printf("socketpair created fds: %d, %d\n", fds[0], fds[1]);
|
|
// check both directions
|
|
test_pipe(fds[0], fds[1]);
|
|
test_pipe(fds[1], fds[0]);
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
}
|
|
|
|
TEST_CASE("pipe()", "[sock_utils]")
|
|
{
|
|
int fds[2];
|
|
CHECK(esp_pipe(fds) == 0);
|
|
printf("pipe created fds: %d, %d\n", fds[0], fds[1]);
|
|
// check only one direction
|
|
test_pipe(fds[0], fds[1]);
|
|
close(fds[0]);
|
|
close(fds[1]);
|
|
}
|
|
|
|
TEST_CASE("gai_strerror()", "[sock_utils]")
|
|
{
|
|
const char *str_error = esp_gai_strerror(EAI_BADFLAGS);
|
|
CHECK(str_error != NULL);
|
|
}
|
|
|
|
TEST_CASE("gethostname()", "[sock_utils]")
|
|
{
|
|
const char *test_netif_name = "station";
|
|
char hostname[32];
|
|
int ret;
|
|
|
|
// expect failure
|
|
ret = gethostname(hostname, strlen(CONFIG_LWIP_LOCAL_HOSTNAME) - 1);
|
|
CHECK(ret == -1);
|
|
|
|
// happy flow with the default name
|
|
ret = gethostname(hostname, sizeof(hostname));
|
|
CHECK(ret == 0);
|
|
CHECK(strcmp(hostname, CONFIG_LWIP_LOCAL_HOSTNAME) == 0);
|
|
|
|
// happy flow with the netif name
|
|
esp_netif_t *esp_netif = create_test_netif(test_netif_name, 1);
|
|
REQUIRE(esp_netif != NULL);
|
|
CHECK(esp_netif_set_hostname(esp_netif, test_netif_name) == ESP_OK);
|
|
ret = gethostname(hostname, sizeof(hostname));
|
|
CHECK(ret == 0);
|
|
CHECK(strcmp(hostname, test_netif_name) == 0);
|
|
esp_netif_destroy(esp_netif);
|
|
}
|
|
|
|
extern "C" void app_main(void)
|
|
{
|
|
ESP_ERROR_CHECK(esp_netif_init());
|
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
|
|
|
Catch::Session session;
|
|
|
|
int failures = session.run();
|
|
if (failures > 0) {
|
|
printf("TEST FAILED! number of failures=%d\n", failures);
|
|
exit(1);
|
|
} else {
|
|
printf("Test passed!\n");
|
|
exit(0);
|
|
}
|
|
}
|