From 7c493673bd4ba0a7083b62837e77d28bc9c2ad9a Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sun, 30 Aug 2026 20:04:32 +0200 Subject: [PATCH] test: deflake WASI poll timing checks Use a monotonic high-resolution clock for elapsed-time checks and allow a small tolerance for timer granularity. The previous whole-second clock could report an interval one second short when a slightly early timer coincided with a wall-clock boundary. Assisted-by: Codex Signed-off-by: Filip Skokan --- test/wasi/c/poll.c | 27 ++++++++++++++++++++------- test/wasi/c/poll_win.c | 27 ++++++++++++++++++++------- test/wasi/wasm/poll.wasm | Bin 34041 -> 34822 bytes test/wasi/wasm/poll_win.wasm | Bin 31734 -> 22440 bytes 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/test/wasi/c/poll.c b/test/wasi/c/poll.c index ba12f442654b..f65cf2c7056f 100644 --- a/test/wasi/c/poll.c +++ b/test/wasi/c/poll.c @@ -1,13 +1,24 @@ #include #include +#include #include #include #include #include +#define NANOS_PER_SECOND 1000000000LL +// Timer granularity can make a timeout expire slightly early. +#define TIMEOUT_TOLERANCE_NS 100000000LL + +static int64_t elapsed_nanoseconds(const struct timespec* before, + const struct timespec* after) { + return (after->tv_sec - before->tv_sec) * NANOS_PER_SECOND + + after->tv_nsec - before->tv_nsec; +} + int main(void) { struct pollfd fds[4]; - time_t before, now; + struct timespec before, now; int ret; char* platform; int is_aix_or_os400; @@ -18,18 +29,20 @@ int main(void) { is_win = platform != NULL && 0 == strcmp(platform, "win32"); // Test sleep() behavior. - time(&before); + assert(clock_gettime(CLOCK_MONOTONIC, &before) == 0); sleep(1); - time(&now); - assert(now - before >= 1); + assert(clock_gettime(CLOCK_MONOTONIC, &now) == 0); + assert(elapsed_nanoseconds(&before, &now) >= + NANOS_PER_SECOND - TIMEOUT_TOLERANCE_NS); // Test poll() timeout behavior. fds[0] = (struct pollfd){.fd = -1, .events = 0, .revents = 0}; - time(&before); + assert(clock_gettime(CLOCK_MONOTONIC, &before) == 0); ret = poll(fds, 1, 2000); - time(&now); + assert(clock_gettime(CLOCK_MONOTONIC, &now) == 0); assert(ret == 0); - assert(now - before >= 2); + assert(elapsed_nanoseconds(&before, &now) >= + 2 * NANOS_PER_SECOND - TIMEOUT_TOLERANCE_NS); // V8 has a bug that allows unsupported parts of this test to run, // causing the test to fail. poll_win.c is a workaround. diff --git a/test/wasi/c/poll_win.c b/test/wasi/c/poll_win.c index 9a22082f0eeb..e8e41ffd6a7e 100644 --- a/test/wasi/c/poll_win.c +++ b/test/wasi/c/poll_win.c @@ -1,26 +1,39 @@ #include #include +#include #include #include +#define NANOS_PER_SECOND 1000000000LL +// Timer granularity can make a timeout expire slightly early. +#define TIMEOUT_TOLERANCE_NS 100000000LL + +static int64_t elapsed_nanoseconds(const struct timespec* before, + const struct timespec* after) { + return (after->tv_sec - before->tv_sec) * NANOS_PER_SECOND + + after->tv_nsec - before->tv_nsec; +} + int main(void) { struct pollfd fds[4]; - time_t before, now; + struct timespec before, now; int ret; // Test sleep() behavior. - time(&before); + assert(clock_gettime(CLOCK_MONOTONIC, &before) == 0); sleep(1); - time(&now); - assert(now - before >= 1); + assert(clock_gettime(CLOCK_MONOTONIC, &now) == 0); + assert(elapsed_nanoseconds(&before, &now) >= + NANOS_PER_SECOND - TIMEOUT_TOLERANCE_NS); // Test poll() timeout behavior. fds[0] = (struct pollfd){.fd = -1, .events = 0, .revents = 0}; - time(&before); + assert(clock_gettime(CLOCK_MONOTONIC, &before) == 0); ret = poll(fds, 1, 2000); - time(&now); + assert(clock_gettime(CLOCK_MONOTONIC, &now) == 0); assert(ret == 0); - assert(now - before >= 2); + assert(elapsed_nanoseconds(&before, &now) >= + 2 * NANOS_PER_SECOND - TIMEOUT_TOLERANCE_NS); return 0; } diff --git a/test/wasi/wasm/poll.wasm b/test/wasi/wasm/poll.wasm index 07e09ddd39abc65b51cae134f31440719e0c561a..d1863d1351bf296a16834389198624218ce58765 100755 GIT binary patch delta 8168 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 Sx0SV~DtB#JpWx+bmi51~%{8C^ delta 7243 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 diff --git a/test/wasi/wasm/poll_win.wasm b/test/wasi/wasm/poll_win.wasm index f1f06db75469c3593eafc8ebb8daf2325d2532da..f26d0c8a0a6ea281a21ad8cda006643ef1d8af54 100644 GIT binary patch delta 3279 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