diff --git a/tests/net/socket/select/src/main.c b/tests/net/socket/select/src/main.c index d3a61c7c97..e7d3f43c7a 100644 --- a/tests/net/socket/select/src/main.c +++ b/tests/net/socket/select/src/main.c @@ -12,6 +12,20 @@ LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL); #include +#include "../../socket_helpers.h" + +#define BUF_AND_SIZE(buf) buf, sizeof(buf) - 1 +#define STRLEN(buf) (sizeof(buf) - 1) + +#define TEST_STR_SMALL "test" + +#define ANY_PORT 0 +#define SERVER_PORT 4242 +#define CLIENT_PORT 9898 + +/* On QEMU, poll() which waits takes +10ms from the requested time. */ +#define FUZZ 10 + void test_fd_set(void) { fd_set set; @@ -47,12 +61,113 @@ void test_fd_set(void) zassert_equal(set.bitset[1], 0, ""); } +void test_select(void) +{ + int res; + int c_sock; + int s_sock; + struct sockaddr_in6 c_addr; + struct sockaddr_in6 s_addr; + fd_set readfds; + u32_t tstamp; + ssize_t len; + char buf[10]; + struct timeval tval; + + prepare_sock_udp_v6(CONFIG_NET_CONFIG_MY_IPV6_ADDR, CLIENT_PORT, + &c_sock, &c_addr); + prepare_sock_udp_v6(CONFIG_NET_CONFIG_MY_IPV6_ADDR, SERVER_PORT, + &s_sock, &s_addr); + + res = bind(s_sock, (struct sockaddr *)&s_addr, sizeof(s_addr)); + zassert_equal(res, 0, "bind failed"); + + res = connect(c_sock, (struct sockaddr *)&s_addr, sizeof(s_addr)); + zassert_equal(res, 0, "connect failed"); + + FD_ZERO(&readfds); + FD_SET(c_sock, &readfds); + FD_SET(s_sock, &readfds); + + /* Poll non-ready fd's with timeout of 0 */ + tval.tv_sec = tval.tv_usec = 0; + tstamp = k_uptime_get_32(); + res = select(s_sock + 1, &readfds, NULL, NULL, &tval); + tstamp = k_uptime_get_32() - tstamp; + zassert_true(tstamp <= 1, ""); + zassert_equal(res, 0, ""); + + zassert_false(FD_ISSET(c_sock, &readfds), ""); + zassert_false(FD_ISSET(s_sock, &readfds), ""); + + /* Poll non-ready fd's with timeout of 10ms */ + FD_SET(c_sock, &readfds); + FD_SET(s_sock, &readfds); + tval.tv_sec = 0; + tval.tv_usec = 10 * 1000; + tstamp = k_uptime_get_32(); + res = select(s_sock + 1, &readfds, NULL, NULL, &tval); + tstamp = k_uptime_get_32() - tstamp; + zassert_true(tstamp >= 10 && tstamp <= 10 + FUZZ, ""); + zassert_equal(res, 0, ""); + + + /* Send pkt for s_sock and poll with timeout of 10ms */ + len = send(c_sock, BUF_AND_SIZE(TEST_STR_SMALL), 0); + zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len"); + + FD_SET(c_sock, &readfds); + FD_SET(s_sock, &readfds); + tval.tv_sec = 0; + tval.tv_usec = 10 * 1000; + tstamp = k_uptime_get_32(); + res = select(s_sock + 1, &readfds, NULL, NULL, &tval); + tstamp = k_uptime_get_32() - tstamp; + zassert_true(tstamp <= 1, ""); + zassert_equal(res, 1, ""); + + zassert_false(FD_ISSET(c_sock, &readfds), ""); + zassert_true(FD_ISSET(s_sock, &readfds), ""); + + + /* Recv pkt from s_sock and ensure no poll events happen */ + len = recv(s_sock, BUF_AND_SIZE(buf), 0); + zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid recv len"); + + FD_SET(c_sock, &readfds); + FD_SET(s_sock, &readfds); + tval.tv_sec = tval.tv_usec = 0; + tstamp = k_uptime_get_32(); + res = select(s_sock + 1, &readfds, NULL, NULL, &tval); + zassert_true(k_uptime_get_32() - tstamp <= 1, ""); + zassert_equal(res, 0, ""); + zassert_false(FD_ISSET(s_sock, &readfds), ""); + + + /* Close one socket and ensure POLLNVAL happens */ + res = close(c_sock); + zassert_equal(res, 0, "close failed"); + + FD_SET(c_sock, &readfds); + FD_SET(s_sock, &readfds); + tval.tv_sec = tval.tv_usec = 0; + tstamp = k_uptime_get_32(); + res = select(s_sock + 1, &readfds, NULL, NULL, &tval); + zassert_true(k_uptime_get_32() - tstamp <= 1, ""); + zassert_true(res < 0, ""); + zassert_equal(errno, EBADF, ""); + + res = close(s_sock); + zassert_equal(res, 0, "close failed"); +} + void test_main(void) { k_thread_system_pool_assign(k_current_get()); ztest_test_suite(socket_select, - ztest_user_unit_test(test_fd_set)); + ztest_user_unit_test(test_fd_set), + ztest_user_unit_test(test_select)); ztest_run_test_suite(socket_select); }