Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_program(VALGRIND_EXECUTABLE NAMES valgrind)
endif()

# Some hosts (notably macOS, whose default soft limit is 256) start test
# processes with too few file descriptors for descriptor-heavy tests such as
# test_event. Raise the soft limit before exec'ing each test; a failure to
# raise it (hard limit too low) is ignored so the test still runs.
if(NOT WIN32)
set(SS_TEST_LAUNCHER sh -c "ulimit -n 1024 2>/dev/null\; exec \"$0\" \"$@\"")
endif()

# Helper function to add a unit test
function(ss_add_test name sources libs)
if(WIN32 AND "${sources}" MATCHES "utils.c")
Expand All @@ -28,12 +36,12 @@ function(ss_add_test name sources libs)
else()
target_compile_options(${name} PRIVATE -UNDEBUG)
endif()
add_test(NAME ${name} COMMAND ${name})
add_test(NAME ${name} COMMAND ${SS_TEST_LAUNCHER} $<TARGET_FILE:${name}>)
set_tests_properties(${name} PROPERTIES LABELS "unit")

if(VALGRIND_EXECUTABLE)
add_test(NAME memcheck_${name}
COMMAND ${VALGRIND_EXECUTABLE}
COMMAND ${SS_TEST_LAUNCHER} ${VALGRIND_EXECUTABLE}
--tool=memcheck
--leak-check=full
--show-leak-kinds=definite,indirect
Expand Down
4 changes: 4 additions & 0 deletions tests/test_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ static void must_not_run(struct ss_loop *loop, ss_io *io, int events)
int main(void)
{
test_network_init();
/* 256 receivers + sender + loop internals must fit under RLIMIT_NOFILE. */
test_raise_fd_limit(512);
struct ss_loop *loop = ss_loop_new(0);
assert(loop);
#ifdef _WIN32
Expand All @@ -48,8 +50,10 @@ int main(void)
/* Exceed Winsock select's default 64 descriptors. */
struct receiver receivers[256] = {0};
ss_socket_t sender = socket(AF_INET, SOCK_DGRAM, 0);
assert((int)sender >= 0);
for (unsigned i = 0; i < 256; i++) {
int fd = (int)socket(AF_INET, SOCK_DGRAM, 0);
assert(fd >= 0);
struct sockaddr_in address = {0};
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Expand Down
22 changes: 22 additions & 0 deletions tests/test_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <stdio.h>
#include <stdlib.h>
#include "platform.h"
#ifndef _WIN32
#include <sys/resource.h>
#endif

static inline void test_network_cleanup(void)
{
Expand All @@ -19,6 +22,25 @@ static inline void test_network_init(void)
assert(atexit(test_network_cleanup) == 0);
#endif
}
/* Make sure at least `want` descriptors can be opened; the default soft
* limit is only 256 on macOS, which is below what descriptor-heavy tests
* such as test_event need. Windows sockets are not bounded by RLIMIT_NOFILE. */
static inline void test_raise_fd_limit(unsigned want)
{
#ifndef _WIN32
struct rlimit limit;
assert(getrlimit(RLIMIT_NOFILE, &limit) == 0);
if (limit.rlim_cur != RLIM_INFINITY && limit.rlim_cur < want) {
limit.rlim_cur = want;
if (limit.rlim_max != RLIM_INFINITY && limit.rlim_max < limit.rlim_cur) {
limit.rlim_cur = limit.rlim_max;
}
assert(setrlimit(RLIMIT_NOFILE, &limit) == 0);
}
#else
(void)want;
#endif
}
static inline FILE *test_tempfile(char *path, size_t size)
{
#ifdef _WIN32
Expand Down
Loading