17#ifdef USE_ASSERT_CHECKING
23static int num_tests = 0;
29 ok_impl(OK, TEST, #OK, __FILE__, __LINE__)
32ok_impl(
bool ok,
const char *
test,
const char *teststr,
const char *file,
int line)
34 printf(
"%sok %d - %s\n", ok ?
"" :
"not ", ++num_tests,
test);
38 printf(
"# at %s:%d:\n", file, line);
39 printf(
"# expression is false: %s\n", teststr);
55#define is(THIS, THAT, TEST) \
60 ok_impl(this_ == that_, TEST, #THIS " == " #THAT, __FILE__, __LINE__), \
61 this_, #THIS, that_, #THAT \
66is_diag(
bool ok,
int this,
const char *thisstr,
int that,
const char *thatstr)
69 printf(
"# %s = %d; %s = %d\n", thisstr,
this, thatstr, that);
87 actx =
calloc(1,
sizeof(*actx));
114static char dummy_buf[4 * 1024];
134 w =
write(
fd, dummy_buf,
sizeof(dummy_buf));
139 perror(
"write to pipe");
158drain_pipe(
int fd, ssize_t n)
164 size_t to_read = (n <=
sizeof(dummy_buf)) ? n :
sizeof(dummy_buf);
167 drained =
read(
fd, dummy_buf, to_read);
170 perror(
"read from pipe");
190#define mux_is_ready(MUX, DEADLINE, TEST) \
192 int res_ = PQsocketPoll(MUX, 1, 0, DEADLINE); \
193 Assert(res_ != -1); \
194 ok(res_ > 0, "multiplexer is ready " TEST); \
200#define mux_is_not_ready(MUX, TEST) \
202 int res_ = PQsocketPoll(MUX, 1, 0, 0); \
203 Assert(res_ != -1); \
204 is(res_, 0, "multiplexer is not ready " TEST); \
217 struct async_ctx *actx = init_test_actx();
220 printf(
"# test_set_timer\n");
224 mux_is_ready(actx->
mux, deadline,
"when timer expires");
225 is(
timer_expired(actx), 1,
"timer_expired() returns 1 when timer expires");
229 mux_is_not_ready(actx->
mux,
"when timer is reset to the future");
230 is(
timer_expired(actx), 0,
"timer_expired() returns 0 with unexpired timer");
234 mux_is_ready(actx->
mux, deadline,
"when timer is re-expired");
235 is(
timer_expired(actx), 1,
"timer_expired() returns 1 when timer is re-expired");
239 mux_is_not_ready(actx->
mux,
"when timer is unset");
240 is(
timer_expired(actx), 0,
"timer_expired() returns 0 when timer is unset");
247 mux_is_ready(actx->
mux, deadline,
"when timer is re-expired (drain_timer_events)");
250 mux_is_not_ready(actx->
mux,
"when timer is drained after expiring");
251 is(expired, 1,
"drain_timer_events() reports expiration");
252 is(
timer_expired(actx), 0,
"timer_expired() returns 0 after timer is drained");
256 mux_is_not_ready(actx->
mux,
"when timer is drained a second time");
257 is(expired, 0,
"drain_timer_events() reports no expiration");
258 is(
timer_expired(actx), 0,
"timer_expired() still returns 0");
261 free_test_actx(actx);
265test_register_socket(
void)
267 struct async_ctx *actx = init_test_actx();
274 Assert(pipe(pipefd) == 0);
289 for (
int inout = 0; inout < 2; inout++)
291 const int in_event = inout ? CURL_POLL_INOUT : CURL_POLL_IN;
292 const int out_event = inout ? CURL_POLL_INOUT : CURL_POLL_OUT;
294 size_t bidi_pipe_size = 0;
296 printf(
"# test_register_socket %s\n", inout ?
"(INOUT)" :
"");
311 Assert((bidi_pipe_size = fill_pipe(rfd)) > 0);
315 mux_is_not_ready(actx->
mux,
"when fd is not readable");
319 mux_is_ready(actx->
mux, deadline,
"when fd is readable");
326 mux_is_not_ready(actx->
mux,
"when waiting for writes on readable fd");
330 mux_is_ready(actx->
mux, deadline,
"when waiting for reads again");
334 mux_is_not_ready(actx->
mux,
"when readable fd is removed");
338 mux_is_ready(actx->
mux, deadline,
"when readable fd is re-added");
344 Assert(drain_pipe(rfd, 1));
346 mux_is_not_ready(actx->
mux,
"when fd is drained");
350 Assert(drain_pipe(wfd, bidi_pipe_size));
355 mux_is_ready(actx->
mux, deadline,
"when fd is writable");
359 mux_is_not_ready(actx->
mux,
"when waiting for reads on writable fd");
363 mux_is_ready(actx->
mux, deadline,
"when waiting for writes again");
372 Assert((written = fill_pipe(wfd)) > 0);
373 printf(
"# pipe buffer is full at %zd bytes\n", written);
376 mux_is_not_ready(actx->
mux,
"when fd buffer is full");
379 Assert(drain_pipe(rfd, written));
380 mux_is_ready(actx->
mux, deadline,
"when fd buffer is drained");
385 mux_is_not_ready(actx->
mux,
"when fd is removed");
393 Assert((bidi_pipe_size = fill_pipe(rfd)) > 0);
403 mux_is_ready(actx->
mux, deadline,
"when fd is readable and timer expired");
415 Assert(drain_pipe(rfd, 1));
418 is(expired, 1,
"drain_timer_events() reports expiration");
420 mux_is_not_ready(actx->
mux,
"when fd is drained and timer reset");
427 Assert(drain_pipe(wfd, bidi_pipe_size));
436 Assert(pipe(pipefd) == 0);
443 Assert((bidi_pipe_size = fill_pipe(rfd)) > 0);
444 Assert(fill_pipe(rfd2) == bidi_pipe_size);
454 mux_is_ready(actx->
mux, deadline,
"when two fds are readable");
460 Assert(drain_pipe(rfd, 1));
461 Assert(drain_pipe(rfd2, 1));
463 mux_is_not_ready(actx->
mux,
"when two fds are drained");
472 Assert(drain_pipe(wfd, bidi_pipe_size));
473 Assert(drain_pipe(wfd2, bidi_pipe_size));
483 free_test_actx(actx);
487main(
int argc,
char *argv[])
492 timeout = getenv(
"PG_TEST_TIMEOUT_DEFAULT");
495 int timeout_s = atoi(timeout);
498 timeout_us = timeout_s * 1000 * 1000;
508 test_register_socket();
510 printf(
"1..%d\n", num_tests);
522 printf(
"1..0 # skip: cassert is not enabled\n");
int PQsocketPoll(int sock, int forRead, int forWrite, pg_usec_time_t end_time)
pg_usec_time_t PQgetCurrentTimeUSec(void)
Assert(PointerIsAligned(start, uint64))
static bool drain_timer_events(struct async_ctx *actx, bool *was_expired)
static bool setup_multiplexer(struct async_ctx *actx)
static int register_socket(CURL *curl, curl_socket_t socket, int what, void *ctx, void *socketp)
static bool set_timer(struct async_ctx *actx, long timeout)
static int timer_expired(struct async_ctx *actx)
static bool comb_multiplexer(struct async_ctx *actx)
static PgChecksumMode mode
void initPQExpBuffer(PQExpBuffer str)
void termPQExpBuffer(PQExpBuffer str)
static int fd(const char *x, int i)
int main(int argc, char *argv[])