diff options
| author | Garrett D'Amore <garrett@damore.org> | 2024-12-30 15:39:50 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2024-12-30 15:47:04 -0800 |
| commit | 7f7a8194a60e9f5883866dd8b8c22d4576fc1abc (patch) | |
| tree | cbd7af87601a5f68e84ca9dcaad890881dec62db /src/platform | |
| parent | a74d853241fa21ef4b6352fd39c25b4d4c6a4ab3 (diff) | |
| download | nng-7f7a8194a60e9f5883866dd8b8c22d4576fc1abc.tar.gz nng-7f7a8194a60e9f5883866dd8b8c22d4576fc1abc.tar.bz2 nng-7f7a8194a60e9f5883866dd8b8c22d4576fc1abc.zip | |
ipc test: add a case for IPC that never connects
This involved test-specific hacks, since connect() for UNIX domain
sockets always completes synchronously one way or the other, even though
it is documented that it might not. This found a bug, with an uninitialized
poll FD as well!
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/ipc_stream_test.c | 32 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipc.h | 3 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipcdial.c | 42 |
3 files changed, 72 insertions, 5 deletions
diff --git a/src/platform/ipc_stream_test.c b/src/platform/ipc_stream_test.c index 7e5e7701..fb3bc493 100644 --- a/src/platform/ipc_stream_test.c +++ b/src/platform/ipc_stream_test.c @@ -108,6 +108,37 @@ test_ipc_stream(void) } void +test_ipc_no_connect(void) +{ +#ifdef NNG_PLATFORM_POSIX + nng_stream_dialer *d = NULL; + nng_stream_listener *l = NULL; + char *url; + nng_aio *daio = NULL; + + NUTS_ADDR(url, "ipc"); + NUTS_PASS(nng_aio_alloc(&daio, NULL, NULL)); + + NUTS_PASS(nng_stream_listener_alloc(&l, url)); + NUTS_PASS(nng_stream_listener_listen(l)); + nng_aio_set_timeout(daio, 100); + + NUTS_PASS(nng_stream_dialer_alloc(&d, url)); + NUTS_PASS(nng_stream_dialer_set_bool(d, "test-no-connect", true)); + nng_stream_dialer_dial(d, daio); + + nng_aio_wait(daio); + NUTS_FAIL(nng_aio_result(daio), NNG_ETIMEDOUT); + + nng_aio_free(daio); + nng_stream_dialer_free(d); + nng_stream_listener_free(l); +#else + NUTS_SKIP("Not POSIX"); +#endif +} + +void test_ipc_listen_activation(void) { #if defined(NNG_PLATFORM_POSIX) @@ -290,6 +321,7 @@ test_ipc_listen_activation_bad_arg(void) NUTS_TESTS = { { "ipc stream", test_ipc_stream }, + { "ipc no connect", test_ipc_no_connect }, { "ipc socket activation", test_ipc_listen_activation }, { "ipc socket activation busy", test_ipc_listen_activation_busy }, { "ipc socket activation closed", test_ipc_listen_activation_closed }, diff --git a/src/platform/posix/posix_ipc.h b/src/platform/posix/posix_ipc.h index e4bdfd97..09cae865 100644 --- a/src/platform/posix/posix_ipc.h +++ b/src/platform/posix/posix_ipc.h @@ -40,6 +40,9 @@ struct nni_ipc_dialer { nni_mtx mtx; nng_sockaddr sa; nni_refcnt ref; +#ifdef NNG_TEST_LIB + bool no_connect; // don't actually connect, for testing cancellation, +#endif }; extern int nni_posix_ipc_alloc( diff --git a/src/platform/posix/posix_ipcdial.c b/src/platform/posix/posix_ipcdial.c index 2b6d547a..e106cfc9 100644 --- a/src/platform/posix/posix_ipcdial.c +++ b/src/platform/posix/posix_ipcdial.c @@ -161,7 +161,6 @@ ipc_dialer_dial(void *arg, nni_aio *aio) { ipc_dialer *d = arg; nni_ipc_conn *c; - nni_posix_pfd *pfd = NULL; struct sockaddr_storage ss; size_t len; int fd; @@ -201,7 +200,19 @@ ipc_dialer_dial(void *arg, nni_aio *aio) goto error; } c->dial_aio = aio; - if (connect(fd, (void *) &ss, len) != 0) { +#ifdef NNG_TEST_LIB + // this stanza exists for testing, because IPC doesn't normally + // exhibit a delayed connection. But it could, and we need to try + // to test it as much as possible. + if (d->no_connect) { + errno = EINPROGRESS; + } + if (d->no_connect || (connect(fd, (void *) &ss, len) != 0)) +#else + if (connect(fd, (void *) &ss, len) != 0) +#endif + + { if (errno != EINPROGRESS && errno != EAGAIN) { if (errno == ENOENT) { // No socket present means nobody listening. @@ -212,7 +223,7 @@ ipc_dialer_dial(void *arg, nni_aio *aio) goto error; } // Asynchronous connect. - if ((rv = nni_posix_pfd_arm(pfd, NNI_POLL_OUT)) != 0) { + if ((rv = nni_posix_pfd_arm(&c->pfd, NNI_POLL_OUT)) != 0) { goto error; } c->dial_aio = NULL; @@ -221,8 +232,7 @@ ipc_dialer_dial(void *arg, nni_aio *aio) nni_mtx_unlock(&d->mtx); return; } - // Immediate connect, cool! This probably only happens - // on loop back, and probably not on every platform. + // Immediate connect, cool! For IPC this is typical. c->dial_aio = NULL; nni_aio_set_prov_data(aio, NULL); nni_mtx_unlock(&d->mtx); @@ -247,11 +257,33 @@ ipc_dialer_get_remaddr(void *arg, void *buf, size_t *szp, nni_type t) return (nni_copyout_sockaddr(&d->sa, buf, szp, t)); } +#ifdef NNG_TEST_LIB +static int +ipc_dialer_set_test_no_connect( + void *arg, const void *buf, size_t sz, nni_type t) +{ + ipc_dialer *d = arg; + bool no_connect = false; + + (void) nni_copyin_bool(&no_connect, buf, sz, t); + nni_mtx_lock(&d->mtx); + d->no_connect = no_connect; + nni_mtx_unlock(&d->mtx); + return (0); +} +#endif + static const nni_option ipc_dialer_options[] = { { .o_name = NNG_OPT_REMADDR, .o_get = ipc_dialer_get_remaddr, }, +#ifdef NNG_TEST_LIB + { + .o_name = "test-no-connect", + .o_set = ipc_dialer_set_test_no_connect, + }, +#endif { .o_name = NULL, }, |
