diff options
Diffstat (limited to 'tests/sock.c')
| -rw-r--r-- | tests/sock.c | 1139 |
1 files changed, 611 insertions, 528 deletions
diff --git a/tests/sock.c b/tests/sock.c index 02cd0d43..cf3cc705 100644 --- a/tests/sock.c +++ b/tests/sock.c @@ -1,5 +1,5 @@ // -// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -12,532 +12,615 @@ #include <nng/nng.h> #include <nng/protocol/pair1/pair.h> -#include <nng/protocol/pubsub0/sub.h> #include <nng/supplemental/util/platform.h> -#include "convey.h" -#include "stubs.h" -#include "trantest.h" - -#define SECONDS(x) ((x) *1000) - -TestMain("Socket Operations", { - atexit(nng_fini); - // Reset({ nng_fini(); }); - Reset({ nng_closeall(); }); - - Convey("We are able to open a PAIR socket", { - int rv; - nng_socket s1; - - So(nng_pair_open(&s1) == 0); - - Reset({ nng_close(s1); }); - - Convey("Recv with no pipes times out correctly", { - nng_msg * msg = NULL; - nng_duration to = 100; - uint64_t now; - - now = getms(); - So(now > 0); - So(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, to) == 0); - So(nng_recvmsg(s1, &msg, 0) == NNG_ETIMEDOUT); - So(msg == NULL); - So(getms() >= (now + to)); - So(getms() < (now + (to * 2))); - }); - - Convey("Recv nonblock with no pipes gives EAGAIN", { - nng_msg *msg = NULL; - So(nng_recvmsg(s1, &msg, NNG_FLAG_NONBLOCK) == - NNG_EAGAIN); - So(msg == NULL); - }); - - Convey("Send with no pipes times out correctly", { - nng_msg * msg = NULL; - nng_duration to = 100; - uint64_t now; - - // We cheat to get access to the core's clock. - So(nng_msg_alloc(&msg, 0) == 0); - So(msg != NULL); - now = getms(); - - So(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, to) == 0); - So(nng_sendmsg(s1, msg, 0) == NNG_ETIMEDOUT); - So(getms() >= (now + to)); - So(getms() < (now + (to * 2))); - nng_msg_free(msg); - }); - - Convey("We can set and get options", { - nng_duration to = 1234; - - So(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, to) == 0); - - Convey("Read only options handled properly", { - So(nng_setopt_int(s1, NNG_OPT_RECVFD, 0) == - NNG_EREADONLY); - So(nng_setopt_int(s1, NNG_OPT_SENDFD, 0) == - NNG_EREADONLY); - So(nng_setopt(s1, NNG_OPT_LOCADDR, "a", 1) == - NNG_EREADONLY); - }); - - Convey("Sockname option works", { - char name[128]; // 64 is max - char * allocd; - size_t sz; - sz = sizeof(name); - So(nng_getopt( - s1, NNG_OPT_SOCKNAME, name, &sz) == 0); - So(sz > 0 && sz < 64); - So(sz == strlen(name) + 1); - So(atoi(name) == (int) s1.id); - - So(nng_setopt( - s1, NNG_OPT_SOCKNAME, "hello", 6) == 0); - sz = sizeof(name); - So(nng_getopt( - s1, NNG_OPT_SOCKNAME, name, &sz) == 0); - So(sz == 6); - So(strcmp(name, "hello") == 0); - - memset(name, 'A', 64); - name[64] = '\0'; - - // strings must be NULL terminated - So(nng_setopt(s1, NNG_OPT_SOCKNAME, name, 5) == - NNG_EINVAL); - - So(nng_getopt_string( - s1, NNG_OPT_SOCKNAME, &allocd) == 0); - So(strlen(allocd) == 5); - So(strcmp(allocd, "hello") == 0); - nng_strfree(allocd); - }); - - Convey("Oversize sockname handled right", { - char name[256]; // 64 is max - size_t sz = sizeof(name); - memset(name, 'A', sz); - So(nng_setopt(s1, NNG_OPT_SOCKNAME, name, - sz) == NNG_EINVAL); - name[sz - 1] = '\0'; - So(nng_setopt(s1, NNG_OPT_SOCKNAME, name, - sz) == NNG_EINVAL); - - strcpy(name, "hello"); - So(nng_setopt( - s1, NNG_OPT_SOCKNAME, name, sz) == 0); - sz = sizeof(name); - memset(name, 'B', sz); - So(nng_getopt( - s1, NNG_OPT_SOCKNAME, name, &sz) == 0); - So(sz == 6); - So(strcmp(name, "hello") == 0); - }); - - Convey("RAW option works", { - bool raw; - So(nng_getopt_bool(s1, NNG_OPT_RAW, &raw) == - 0); - So(raw == false); - }); - - Convey("URL option works", { - char url[NNG_MAXADDRLEN]; - nng_listener l; - nng_dialer d; - size_t sz; - - So(nng_listener_create( - &l, s1, "inproc://url1") == 0); - So(nng_dialer_create( - &d, s1, "inproc://url2") == 0); - memset(url, 0, sizeof(url)); - sz = sizeof(url); - So(nng_listener_getopt( - l, NNG_OPT_URL, url, &sz) == 0); - So(strcmp(url, "inproc://url1") == 0); - So(nng_listener_setopt(l, NNG_OPT_URL, url, - sz) == NNG_EREADONLY); - sz = sizeof(url); - So(nng_dialer_getopt( - d, NNG_OPT_URL, url, &sz) == 0); - So(strcmp(url, "inproc://url2") == 0); - - So(nng_dialer_setopt(d, NNG_OPT_URL, url, - sz) == NNG_EREADONLY); - Reset({ - nng_dialer_close(d); - nng_listener_close(l); - }); - }); - - Convey("We can apply options before endpoint", { - nng_listener l; - char addr[NNG_MAXADDRLEN]; - size_t sz; - - trantest_next_address( - addr, "ipc:///tmp/lopt_%u"); - - So(nng_setopt_size( - s1, NNG_OPT_RECVMAXSZ, 543) == 0); - So(nng_listener_create(&l, s1, addr) == 0); - So(nng_listener_getopt_size( - l, NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 543); - - Convey("Endpoint option can be overridden", { - So(nng_listener_setopt_size(l, - NNG_OPT_RECVMAXSZ, 678) == 0); - So(nng_listener_getopt_size(l, - NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 678); - So(nng_getopt_size(s1, - NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 543); - }); - - Convey("And socket overrides again", { - So(nng_setopt_size(s1, - NNG_OPT_RECVMAXSZ, 911) == 0); - So(nng_listener_getopt_size(l, - NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 911); - }); - }); - Convey("Short size is not copied", { - size_t sz = 0; - to = 0; - So(nng_getopt(s1, NNG_OPT_SENDTIMEO, &to, - &sz) == NNG_EINVAL); - So(sz == sizeof(to)); - So(to == 0); - sz = 0; - So(nng_getopt(s1, NNG_OPT_RECONNMINT, &to, - &sz) == NNG_EINVAL); - - So(to == 0); - sz = 0; - So(nng_getopt(s1, NNG_OPT_RECONNMAXT, &to, - &sz) == NNG_EINVAL); - So(to == 0); - }); - - Convey("Correct size is copied", { - size_t sz = sizeof(to); - So(nng_getopt( - s1, NNG_OPT_SENDTIMEO, &to, &sz) == 0); - So(sz == sizeof(to)); - So(to == 1234); - }); - - Convey("Short size buf is not copied", { - int l = 5; - size_t sz = 0; - So(nng_getopt(s1, NNG_OPT_RECVBUF, &l, &sz) == - NNG_EINVAL); - So(sz == sizeof(l)); - So(l == 5); - }); - - Convey("Insane buffer size fails", { - So(nng_setopt_int(s1, NNG_OPT_RECVBUF, - 0x100000) == NNG_EINVAL); - So(nng_setopt_int(s1, NNG_OPT_RECVBUF, -200) == - NNG_EINVAL); - }); - - Convey("Negative timeout fails", { - So(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, -5) == - NNG_EINVAL); - }); - - Convey("Short timeout fails", { - size_t sz = sizeof(to) - 1; - to = 0; - So(nng_setopt(s1, NNG_OPT_RECVTIMEO, &to, - sz) == NNG_EINVAL); - So(nng_setopt(s1, NNG_OPT_RECONNMINT, &to, - sz) == NNG_EINVAL); - }); - - Convey("Cannot set raw", { - So(nng_setopt_bool(s1, NNG_OPT_RAW, true) == - NNG_EREADONLY); - }); - - Convey("Unsupported options fail", { - char *crap = "crap"; - So(nng_setopt(s1, NNG_OPT_SUB_SUBSCRIBE, crap, - strlen(crap)) == NNG_ENOTSUP); - }); - - Convey("Bogus sizes fail", { - size_t v; - int i; - - So(nng_setopt_size( - s1, NNG_OPT_RECVMAXSZ, 6550) == 0); - So(nng_getopt_size( - s1, NNG_OPT_RECVMAXSZ, &v) == 0); - So(v == 6550); - - v = 102400; - So(nng_setopt(s1, NNG_OPT_RECVMAXSZ, &v, 1) == - NNG_EINVAL); - So(nng_getopt_size( - s1, NNG_OPT_RECVMAXSZ, &v) == 0); - So(v == 6550); - - i = 42; - So(nng_setopt(s1, NNG_OPT_RECVBUF, &i, 1) == - NNG_EINVAL); - - if (sizeof(size_t) == 8) { - v = 0x10000; - v <<= 30; - So(nng_setopt_size(s1, - NNG_OPT_RECVMAXSZ, - v) == NNG_EINVAL); - So(nng_getopt_size(s1, - NNG_OPT_RECVMAXSZ, &v) == 0); - So(v == 6550); - } - }); - }); - - Convey("Bogus URLs not supported", { - Convey("Dialing fails properly", { - rv = nng_dial(s1, "bogus://1", NULL, 0); - So(rv == NNG_ENOTSUP); - }); - Convey("Listening fails properly", { - rv = nng_listen(s1, "bogus://2", NULL, 0); - So(rv == NNG_ENOTSUP); - }); - }); - - Convey("Dialing synch can get refused", { - rv = nng_dial(s1, "inproc://no", NULL, 0); - So(rv == NNG_ECONNREFUSED); - }); - - Convey("Dialing asynch does not get refused", { - char * buf; - size_t sz; - nng_socket s2; - char * a = "inproc://asy"; - So(nng_setopt_ms(s1, NNG_OPT_RECONNMINT, 10) == 0); - So(nng_setopt_ms(s1, NNG_OPT_RECONNMAXT, 10) == 0); - So(nng_dial(s1, a, NULL, NNG_FLAG_NONBLOCK) == 0); - Convey("And connects late", { - So(nng_pair_open(&s2) == 0); - Reset({ nng_close(s2); }); - So(nng_listen(s2, a, NULL, 0) == 0); - nng_msleep(100); - So(nng_send(s1, "abc", 4, 0) == 0); - So(nng_recv(s2, &buf, &sz, NNG_FLAG_ALLOC) == - 0); - So(sz == 4); - So(memcmp(buf, "abc", 4) == 0); - nng_free(buf, sz); - }); - }); - - Convey("Listening works", { - char * a = "inproc://here"; - nng_listener l = NNG_LISTENER_INITIALIZER; - - So(nng_listener_id(l) < 0); - rv = nng_listen(s1, a, &l, 0); - So(rv == 0); - So(nng_listener_id(l) > 0); - - Convey("Second listen fails ADDRINUSE", { - rv = nng_listen(s1, a, NULL, 0); - So(rv == NNG_EADDRINUSE); - }); - - Convey("We cannot try to start a listener again", - { So(nng_listener_start(l, 0) == NNG_ESTATE); }); - - Convey("We can connect to it", { - nng_socket s2 = NNG_SOCKET_INITIALIZER; - So(nng_socket_id(s2) < 0); - So(nng_pair_open(&s2) == 0); - Reset({ nng_close(s2); }); - So(nng_dial(s2, a, NULL, 0) == 0); - nng_close(s2); - }); - }); - - Convey("Dialer creation ok", { - nng_dialer ep = NNG_DIALER_INITIALIZER; - char * a = "tcp://127.0.0.1:2929"; - - So(nng_dialer_id(ep) < 0); - So(nng_dialer_create(&ep, s1, a) == 0); - So(nng_dialer_id(ep) > 0); - - Convey("Options work", { - size_t sz; - So(nng_dialer_setopt_size( - ep, NNG_OPT_RECVMAXSZ, 4321) == 0); - So(nng_dialer_getopt_size( - ep, NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 4321); - }); - - Convey("Cannot access as listener", { - bool b; - nng_listener l; - l.id = ep.id; - So(nng_listener_getopt_bool( - l, NNG_OPT_RAW, &b) == NNG_ENOENT); - So(nng_listener_close(l) == NNG_ENOENT); - }); - - Convey("Socket opts not for dialer", { - // Not appropriate for dialer. - So(nng_dialer_setopt_bool( - ep, NNG_OPT_RAW, true) == NNG_ENOTSUP); - So(nng_dialer_setopt_ms(ep, NNG_OPT_SENDTIMEO, - 1) == NNG_ENOTSUP); - So(nng_dialer_setopt_string(ep, - NNG_OPT_SOCKNAME, - "bogus") == NNG_ENOTSUP); - }); - - Convey("URL is readonly", { - So(nng_dialer_setopt_string(ep, NNG_OPT_URL, - "tcp://somewhere.else.com:8888") == - NNG_EREADONLY); - }); - Convey("Bad size checks", { - So(nng_dialer_setopt(ep, NNG_OPT_RECVMAXSZ, - "a", 1) == NNG_EINVAL); - }); - }); - - Convey("Listener creation ok", { - nng_listener ep; - char * a = "tcp://127.0.0.1:2929"; - So(nng_listener_create(&ep, s1, a) == 0); - Convey("Options work", { - size_t sz; - So(nng_listener_setopt_size( - ep, NNG_OPT_RECVMAXSZ, 4321) == 0); - So(nng_listener_getopt_size( - ep, NNG_OPT_RECVMAXSZ, &sz) == 0); - So(sz == 4321); - }); - Convey("Cannot access as dialer", { - bool b; - nng_dialer d; - d.id = ep.id; - So(nng_dialer_getopt_bool( - d, NNG_OPT_RAW, &b) == NNG_ENOENT); - So(nng_dialer_close(d) == NNG_ENOENT); - }); - - Convey("Socket opts not for listener", { - // Not appropriate for dialer. - So(nng_listener_setopt_bool( - ep, NNG_OPT_RAW, true) == NNG_ENOTSUP); - So(nng_listener_setopt_ms(ep, - NNG_OPT_RECONNMINT, 1) == NNG_ENOTSUP); - So(nng_listener_setopt_string(ep, - NNG_OPT_SOCKNAME, - "bogus") == NNG_ENOTSUP); - }); - - Convey("URL is readonly", { - So(nng_listener_setopt_string(ep, NNG_OPT_URL, - "tcp://somewhere.else.com:8888") == - NNG_EREADONLY); - }); - - Convey("Bad size checks", { - So(nng_listener_setopt(ep, NNG_OPT_RECVMAXSZ, - "a", 1) == NNG_EINVAL); - }); - }); - - Convey("Cannot access absent ep options", { - size_t s; - int i; - nng_duration t; - bool b; - nng_dialer d; - nng_listener l; - d.id = 1999; - l.id = 1999; - - So(nng_dialer_setopt_size(d, NNG_OPT_RECVMAXSZ, 10) == - NNG_ENOENT); - So(nng_listener_setopt_size( - l, NNG_OPT_RECVMAXSZ, 10) == NNG_ENOENT); - - s = 1; - So(nng_dialer_getopt_bool(d, NNG_OPT_RAW, &b) == - NNG_ENOENT); - So(nng_listener_getopt_bool(l, NNG_OPT_RAW, &b) == - NNG_ENOENT); - - So(nng_dialer_getopt_size(d, NNG_OPT_RECVMAXSZ, &s) == - NNG_ENOENT); - So(nng_listener_getopt_size( - l, NNG_OPT_RECVMAXSZ, &s) == NNG_ENOENT); - - So(nng_dialer_getopt_int(d, NNG_OPT_RAW, &i) == - NNG_ENOENT); - So(nng_listener_getopt_int(l, NNG_OPT_RAW, &i) == - NNG_ENOENT); - - So(nng_dialer_getopt_ms(d, NNG_OPT_RECVTIMEO, &t) == - NNG_ENOENT); - So(nng_listener_getopt_ms(l, NNG_OPT_SENDTIMEO, &t) == - NNG_ENOENT); - }); - - Convey("We can send and receive messages", { - nng_socket s2; - int len; - size_t sz; - nng_duration to = SECONDS(3); - char * buf; - char * a = "inproc://t1"; - - So(nng_pair_open(&s2) == 0); - Reset({ nng_close(s2); }); - - So(nng_setopt_int(s1, NNG_OPT_RECVBUF, 1) == 0); - So(nng_getopt_int(s1, NNG_OPT_RECVBUF, &len) == 0); - So(len == 1); - - So(nng_setopt_int(s1, NNG_OPT_SENDBUF, 1) == 0); - So(nng_setopt_int(s2, NNG_OPT_SENDBUF, 1) == 0); - - So(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, to) == 0); - So(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, to) == 0); - So(nng_setopt_ms(s2, NNG_OPT_SENDTIMEO, to) == 0); - So(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, to) == 0); - - So(nng_listen(s1, a, NULL, 0) == 0); - So(nng_dial(s2, a, NULL, 0) == 0); - - So(nng_send(s1, "abc", 4, 0) == 0); - So(nng_recv(s2, &buf, &sz, NNG_FLAG_ALLOC) == 0); - So(buf != NULL); - So(sz == 4); - So(memcmp(buf, "abc", 4) == 0); - nng_free(buf, sz); - }); - }); -}) +#include "acutest.h" +#include "testutil.h" + +void +test_recv_timeout(void) +{ + nng_socket s1; + uint64_t now; + nng_msg * msg = NULL; + + TEST_CHECK(nng_pair_open(&s1) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, 10) == 0); + now = testutil_clock(); + TEST_CHECK(nng_recvmsg(s1, &msg, 0) == NNG_ETIMEDOUT); + TEST_CHECK(msg == NULL); + TEST_CHECK(testutil_clock() >= (now + 9)); + TEST_CHECK(testutil_clock() < (now + 500)); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_recv_nonblock(void) +{ + nng_socket s1; + uint64_t now; + nng_msg * msg = NULL; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, 10) == 0); + now = testutil_clock(); + TEST_CHECK(nng_recvmsg(s1, &msg, NNG_FLAG_NONBLOCK) == NNG_EAGAIN); + TEST_CHECK(msg == NULL); + TEST_CHECK(testutil_clock() < (now + 500)); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_send_timeout(void) +{ + nng_socket s1; + uint64_t now; + nng_msg * msg; + + TEST_CHECK(nng_msg_alloc(&msg, 0) == 0); + TEST_CHECK(nng_pair_open(&s1) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, 100) == 0); + now = testutil_clock(); + TEST_CHECK(nng_sendmsg(s1, msg, 0) == NNG_ETIMEDOUT); + TEST_CHECK(testutil_clock() >= (now + 9)); + TEST_CHECK(testutil_clock() < (now + 500)); + nng_msg_free(msg); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_send_nonblock(void) +{ + nng_socket s1; + uint64_t now; + nng_msg * msg; + + TEST_CHECK(nng_msg_alloc(&msg, 0) == 0); + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, 500) == 0); + now = testutil_clock(); + TEST_CHECK(nng_sendmsg(s1, msg, NNG_FLAG_NONBLOCK) == NNG_EAGAIN); + TEST_CHECK(testutil_clock() < (now + 100)); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_readonly_options(void) +{ + nng_socket s1; + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_setopt_int(s1, NNG_OPT_RECVFD, 0) == NNG_EREADONLY); + TEST_CHECK(nng_setopt_int(s1, NNG_OPT_SENDFD, 0) == NNG_EREADONLY); + TEST_CHECK(nng_setopt(s1, NNG_OPT_LOCADDR, "a", 1) == NNG_EREADONLY); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_socket_base(void) +{ + nng_socket s1 = NNG_SOCKET_INITIALIZER; + + TEST_CHECK(nng_socket_id(s1) < 0); + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_socket_id(s1) > 0); + + // Cannot set bogus options + TEST_CHECK(nng_setopt_bool(s1, "BAD_OPT", false) == NNG_ENOTSUP); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_socket_name(void) +{ + nng_socket s1; + char name[128]; // 64 is max + char * str; + long id; + char * end; + size_t sz; + + sz = sizeof(name); + TEST_CHECK(nng_pair_open(&s1) == 0); + TEST_CHECK(nng_getopt(s1, NNG_OPT_SOCKNAME, name, &sz) == 0); + TEST_CHECK(sz > 0 && sz < 64); + TEST_CHECK(sz == strlen(name) + 1); + id = strtol(name, &end, 10); + TEST_CHECK(id == (long) s1.id); + TEST_CHECK(end != NULL && *end == '\0'); + + TEST_CHECK(nng_setopt(s1, NNG_OPT_SOCKNAME, "hello", 6) == 0); + sz = sizeof(name); + TEST_CHECK(nng_getopt(s1, NNG_OPT_SOCKNAME, name, &sz) == 0); + TEST_CHECK(sz == 6); + TEST_CHECK(strcmp(name, "hello") == 0); + + memset(name, 'A', 64); + name[64] = '\0'; + + // strings must be NULL terminated + TEST_CHECK(nng_setopt(s1, NNG_OPT_SOCKNAME, name, 5) == NNG_EINVAL); + + TEST_CHECK(nng_getopt_string(s1, NNG_OPT_SOCKNAME, &str) == 0); + TEST_ASSERT(str != NULL); + TEST_CHECK(strlen(str) == 5); + TEST_CHECK(strcmp(str, "hello") == 0); + nng_strfree(str); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_socket_name_oversize(void) +{ + nng_socket s1; + char name[256]; // 64 is max + size_t sz = sizeof(name); + + memset(name, 'A', sz); + TEST_CHECK(nng_pair_open(&s1) == 0); + + TEST_CHECK(nng_setopt(s1, NNG_OPT_SOCKNAME, name, sz) == NNG_EINVAL); + name[sz - 1] = '\0'; + TEST_CHECK(nng_setopt(s1, NNG_OPT_SOCKNAME, name, sz) == NNG_EINVAL); + + strcpy(name, "hello"); + TEST_CHECK(nng_setopt(s1, NNG_OPT_SOCKNAME, name, sz) == 0); + sz = sizeof(name); + memset(name, 'B', sz); + TEST_CHECK(nng_getopt(s1, NNG_OPT_SOCKNAME, name, &sz) == 0); + TEST_CHECK(sz == 6); + TEST_CHECK(strcmp(name, "hello") == 0); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_send_recv(void) +{ + nng_socket s1; + nng_socket s2; + int len; + size_t sz; + nng_duration to = 3000; // 3 seconds + char * buf; + char * a = "inproc://t1"; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_pair1_open(&s2) == 0); + + TEST_CHECK(nng_setopt_int(s1, NNG_OPT_RECVBUF, 1) == 0); + TEST_CHECK(nng_getopt_int(s1, NNG_OPT_RECVBUF, &len) == 0); + TEST_CHECK(len == 1); + + TEST_CHECK(nng_setopt_int(s1, NNG_OPT_SENDBUF, 1) == 0); + TEST_CHECK(nng_setopt_int(s2, NNG_OPT_SENDBUF, 1) == 0); + + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_SENDTIMEO, to) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_RECVTIMEO, to) == 0); + TEST_CHECK(nng_setopt_ms(s2, NNG_OPT_SENDTIMEO, to) == 0); + TEST_CHECK(nng_setopt_ms(s2, NNG_OPT_RECVTIMEO, to) == 0); + + TEST_CHECK(nng_listen(s1, a, NULL, 0) == 0); + TEST_CHECK(nng_dial(s2, a, NULL, 0) == 0); + + TEST_CHECK(nng_send(s1, "abc", 4, 0) == 0); + TEST_CHECK(nng_recv(s2, &buf, &sz, NNG_FLAG_ALLOC) == 0); + TEST_CHECK(buf != NULL); + TEST_CHECK(sz == 4); + TEST_CHECK(memcmp(buf, "abc", 4) == 0); + nng_free(buf, sz); + + TEST_CHECK(nng_close(s1) == 0); + TEST_CHECK(nng_close(s2) == 0); +} + +void +test_connection_refused(void) +{ + nng_socket s1; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_dial(s1, "inproc://no", NULL, 0) == NNG_ECONNREFUSED); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_late_connection(void) +{ + char * buf; + size_t sz; + nng_socket s1; + nng_socket s2; + char * a = "inproc://asy"; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_pair1_open(&s2) == 0); + + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_RECONNMINT, 10) == 0); + TEST_CHECK(nng_setopt_ms(s1, NNG_OPT_RECONNMAXT, 10) == 0); + + TEST_CHECK(nng_dial(s1, a, NULL, NNG_FLAG_NONBLOCK) == 0); + TEST_CHECK(nng_listen(s2, a, NULL, 0) == 0); + nng_msleep(100); + TEST_CHECK(nng_send(s1, "abc", 4, 0) == 0); + TEST_CHECK(nng_recv(s2, &buf, &sz, NNG_FLAG_ALLOC) == 0); + TEST_CHECK(sz == 4); + TEST_CHECK(memcmp(buf, "abc", 4) == 0); + nng_free(buf, sz); + + TEST_CHECK(nng_close(s1) == 0); + TEST_CHECK(nng_close(s2) == 0); +} + +void +test_address_busy(void) +{ + char * a = "inproc://eaddrinuse"; + nng_listener l = NNG_LISTENER_INITIALIZER; + nng_dialer d = NNG_DIALER_INITIALIZER; + nng_socket s1; + nng_socket s2; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_pair1_open(&s2) == 0); + + TEST_CHECK(nng_listener_id(l) < 0); + TEST_CHECK(nng_listen(s1, a, &l, 0) == 0); + TEST_CHECK(nng_listener_id(l) > 0); + + // Cannot start another one. + TEST_CHECK(nng_listen(s1, a, NULL, 0) == NNG_EADDRINUSE); + + // We can't restart it -- it's already running + TEST_CHECK(nng_listener_start(l, 0) == NNG_ESTATE); + + // We can connect to it. + TEST_CHECK(nng_dialer_id(d) < 0); + TEST_CHECK(nng_dial(s2, a, &d, 0) == 0); + TEST_CHECK(nng_dialer_id(d) > 0); + + TEST_CHECK(nng_close(s1) == 0); + TEST_CHECK(nng_close(s2) == 0); +} + +void +test_endpoint_types(void) +{ + nng_socket s1; + nng_dialer d = NNG_DIALER_INITIALIZER; + nng_listener l = NNG_LISTENER_INITIALIZER; + nng_dialer d2; + nng_listener l2; + char * a = "inproc://mumble..."; + bool b; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + + TEST_CHECK(nng_dialer_id(d) < 0); + TEST_CHECK(nng_dialer_create(&d, s1, a) == 0); + TEST_CHECK(nng_dialer_id(d) > 0); + + // Forge a listener + l2.id = nng_dialer_id(d); + TEST_CHECK( + nng_listener_getopt_bool(l2, NNG_OPT_RAW, &b) == NNG_ENOENT); + TEST_CHECK(nng_listener_close(l2) == NNG_ENOENT); + TEST_CHECK(nng_dialer_close(d) == 0); + + TEST_CHECK(nng_listener_id(l) < 0); + TEST_CHECK(nng_listener_create(&l, s1, a) == 0); + TEST_CHECK(nng_listener_id(l) > 0); + + // Forge a dialer + d2.id = nng_listener_id(l); + TEST_CHECK(nng_dialer_getopt_bool(d2, NNG_OPT_RAW, &b) == NNG_ENOENT); + TEST_CHECK(nng_dialer_close(d2) == NNG_ENOENT); + TEST_CHECK(nng_listener_close(l) == 0); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_bad_url(void) +{ + nng_socket s1; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + TEST_CHECK(nng_dial(s1, "bogus://1", NULL, 0) == NNG_ENOTSUP); + TEST_CHECK(nng_listen(s1, "bogus://2", NULL, 0) == NNG_ENOTSUP); + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_url_option(void) +{ + nng_socket s1; + char url[NNG_MAXADDRLEN]; + nng_listener l; + nng_dialer d; + size_t sz; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + + // Listener + TEST_CHECK(nng_listener_create(&l, s1, "inproc://url1") == 0); + memset(url, 0, sizeof(url)); + sz = sizeof(url); + TEST_CHECK(nng_listener_getopt(l, NNG_OPT_URL, url, &sz) == 0); + TEST_CHECK(strcmp(url, "inproc://url1") == 0); + TEST_CHECK( + nng_listener_setopt(l, NNG_OPT_URL, url, sz) == NNG_EREADONLY); + sz = sizeof(url); + + // Dialer + TEST_CHECK(nng_dialer_create(&d, s1, "inproc://url2") == 0); + TEST_CHECK(nng_dialer_getopt(d, NNG_OPT_URL, url, &sz) == 0); + TEST_CHECK(strcmp(url, "inproc://url2") == 0); + TEST_CHECK( + nng_dialer_setopt(d, NNG_OPT_URL, url, sz) == NNG_EREADONLY); + + nng_close(s1); +} + +void +test_listener_options(void) +{ + nng_socket s1; + nng_listener l; + size_t sz; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + + // Create a listener with the specified options + TEST_CHECK(nng_setopt_size(s1, NNG_OPT_RECVMAXSZ, 543) == 0); + TEST_CHECK(nng_listener_create(&l, s1, "inproc://listener_opts") == 0); + TEST_CHECK(nng_listener_getopt_size(l, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 543); + + // Verify endpoint overrides + TEST_CHECK(nng_listener_setopt_size(l, NNG_OPT_RECVMAXSZ, 678) == 0); + TEST_CHECK(nng_listener_getopt_size(l, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 678); + TEST_CHECK(nng_getopt_size(s1, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 543); + + // And socket overrides again + TEST_CHECK(nng_setopt_size(s1, NNG_OPT_RECVMAXSZ, 911) == 0); + TEST_CHECK(nng_listener_getopt_size(l, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 911); + + // Cannot set invalid options + TEST_CHECK(nng_listener_setopt_size(l, "BAD_OPT", 1) == NNG_ENOTSUP); + TEST_CHECK(nng_listener_setopt_bool(l, NNG_OPT_RECVMAXSZ, true) == + NNG_EBADTYPE); + TEST_CHECK( + nng_listener_setopt(l, NNG_OPT_RECVMAXSZ, &sz, 1) == NNG_EINVAL); + + // Cannot set inappropriate options + TEST_CHECK(nng_listener_setopt_string(l, NNG_OPT_SOCKNAME, "1") == + NNG_ENOTSUP); + TEST_CHECK( + nng_listener_setopt_bool(l, NNG_OPT_RAW, true) == NNG_ENOTSUP); + TEST_CHECK( + nng_listener_setopt_ms(l, NNG_OPT_RECONNMINT, 1) == NNG_ENOTSUP); + TEST_CHECK(nng_listener_setopt_string(l, NNG_OPT_SOCKNAME, "bogus") == + NNG_ENOTSUP); + + // Read only options + TEST_CHECK(nng_listener_setopt_string( + l, NNG_OPT_URL, "inproc://junk") == NNG_EREADONLY); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_dialer_options(void) +{ + nng_socket s1; + nng_dialer d; + size_t sz; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + + // Create a listener with the specified options + TEST_CHECK(nng_setopt_size(s1, NNG_OPT_RECVMAXSZ, 543) == 0); + TEST_CHECK(nng_dialer_create(&d, s1, "inproc://dialer_opts") == 0); + TEST_CHECK(nng_dialer_getopt_size(d, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 543); + + // Verify endpoint overrides + TEST_CHECK(nng_dialer_setopt_size(d, NNG_OPT_RECVMAXSZ, 678) == 0); + TEST_CHECK(nng_dialer_getopt_size(d, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 678); + TEST_CHECK(nng_getopt_size(s1, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 543); + + // And socket overrides again + TEST_CHECK(nng_setopt_size(s1, NNG_OPT_RECVMAXSZ, 911) == 0); + TEST_CHECK(nng_dialer_getopt_size(d, NNG_OPT_RECVMAXSZ, &sz) == 0); + TEST_CHECK(sz == 911); + + // Cannot set invalid options + TEST_CHECK(nng_dialer_setopt_size(d, "BAD_OPT", 1) == NNG_ENOTSUP); + TEST_CHECK(nng_dialer_setopt_bool(d, NNG_OPT_RECVMAXSZ, true) == + NNG_EBADTYPE); + TEST_CHECK( + nng_dialer_setopt(d, NNG_OPT_RECVMAXSZ, &sz, 1) == NNG_EINVAL); + + // Cannot set inappropriate options + TEST_CHECK( + nng_dialer_setopt_string(d, NNG_OPT_SOCKNAME, "1") == NNG_ENOTSUP); + TEST_CHECK( + nng_dialer_setopt_bool(d, NNG_OPT_RAW, true) == NNG_ENOTSUP); + TEST_CHECK( + nng_dialer_setopt_ms(d, NNG_OPT_SENDTIMEO, 1) == NNG_ENOTSUP); + TEST_CHECK(nng_dialer_setopt_string(d, NNG_OPT_SOCKNAME, "bogus") == + NNG_ENOTSUP); + + // Read only options + TEST_CHECK(nng_dialer_setopt_string(d, NNG_OPT_URL, "inproc://junk") == + NNG_EREADONLY); + + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_endpoint_absent_options(void) +{ + size_t s; + int i; + nng_duration t; + bool b; + nng_dialer d; + nng_listener l; + d.id = 1999; + l.id = 1999; + + TEST_CHECK( + nng_dialer_setopt_size(d, NNG_OPT_RECVMAXSZ, 10) == NNG_ENOENT); + TEST_CHECK( + nng_listener_setopt_size(l, NNG_OPT_RECVMAXSZ, 10) == NNG_ENOENT); + + TEST_CHECK(nng_dialer_getopt_bool(d, NNG_OPT_RAW, &b) == NNG_ENOENT); + TEST_CHECK(nng_listener_getopt_bool(l, NNG_OPT_RAW, &b) == NNG_ENOENT); + + TEST_CHECK( + nng_dialer_getopt_size(d, NNG_OPT_RECVMAXSZ, &s) == NNG_ENOENT); + TEST_CHECK( + nng_listener_getopt_size(l, NNG_OPT_RECVMAXSZ, &s) == NNG_ENOENT); + + TEST_CHECK(nng_dialer_getopt_int(d, NNG_OPT_RAW, &i) == NNG_ENOENT); + TEST_CHECK(nng_listener_getopt_int(l, NNG_OPT_RAW, &i) == NNG_ENOENT); + + TEST_CHECK( + nng_dialer_getopt_ms(d, NNG_OPT_RECVTIMEO, &t) == NNG_ENOENT); + TEST_CHECK( + nng_listener_getopt_ms(l, NNG_OPT_SENDTIMEO, &t) == NNG_ENOENT); +} + +void +test_timeout_options(void) +{ + nng_socket s1; + nng_duration to; + size_t sz; + + char *cases[] = { + NNG_OPT_RECVTIMEO, + NNG_OPT_SENDTIMEO, + NNG_OPT_RECONNMAXT, + NNG_OPT_RECONNMINT, + NULL, + }; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + for (int i = 0; cases[i] != NULL; i++) { + bool b; + TEST_CASE(cases[i]); + + // Can't receive a duration into zero bytes. + sz = 0; + TEST_CHECK(nng_getopt(s1, cases[i], &to, &sz) == NNG_EINVAL); + + // Type mismatches + TEST_CHECK(nng_getopt_bool(s1, cases[i], &b) == NNG_EBADTYPE); + sz = 1; + TEST_CHECK(nng_getopt(s1, cases[i], &b, &sz) == NNG_EINVAL); + + // Can set a valid duration + TEST_CHECK(nng_setopt_ms(s1, cases[i], 1234) == 0); + TEST_CHECK(nng_getopt_ms(s1, cases[i], &to) == 0); + TEST_CHECK(to == 1234); + + to = 0; + sz = sizeof(to); + TEST_CHECK(nng_getopt(s1, cases[i], &to, &sz) == 0); + TEST_CHECK(to == 1234); + TEST_CHECK(sz == sizeof(to)); + + // Can't set a negative duration + TEST_CHECK(nng_setopt_ms(s1, cases[i], -5) == NNG_EINVAL); + + // Can't pass a buf too small for duration + sz = sizeof(to) - 1; + to = 1; + TEST_CHECK(nng_setopt(s1, cases[i], &to, sz) == NNG_EINVAL); + } + TEST_CHECK(nng_close(s1) == 0); +} + +void +test_size_options(void) +{ + nng_socket s1; + size_t val; + size_t sz; + char * opt; + + char *cases[] = { + NNG_OPT_RECVMAXSZ, + NULL, + }; + + TEST_CHECK(nng_pair1_open(&s1) == 0); + for (int i = 0; (opt = cases[i]) != NULL; i++) { + TEST_CASE(opt); + + // Can't receive a size into zero bytes. + sz = 0; + TEST_CHECK(nng_getopt(s1, opt, &val, &sz) == NNG_EINVAL); + + // Can set a valid duration + TEST_CHECK(nng_setopt_size(s1, opt, 1234) == 0); + TEST_CHECK(nng_getopt_size(s1, opt, &val) == 0); + TEST_CHECK(val == 1234); + + val = 0; + sz = sizeof(val); + TEST_CHECK(nng_getopt(s1, opt, &val, &sz) == 0); + TEST_CHECK(val == 1234); + TEST_CHECK(sz == sizeof(val)); + + // Can't pass a buf too small for size + sz = sizeof(val) - 1; + val = 1; + TEST_CHECK(nng_setopt(s1, opt, &val, sz) == NNG_EINVAL); + + // We limit the limit to 4GB. Clear it if you want to + // ship more than 4GB at a time. +#if defined(_WIN64) || defined(_LP64) + val = 0x10000u; + val <<= 30u; + TEST_CHECK(nng_setopt_size(s1, opt, val) == NNG_EINVAL); + TEST_CHECK(nng_getopt_size(s1, opt, &val) == 0); + TEST_CHECK(val == 1234); +#endif + } + TEST_CHECK(nng_close(s1) == 0); +} + +TEST_LIST = { + { "recv timeout", test_recv_timeout }, + { "recv non-block", test_recv_nonblock }, + { "send timeout", test_send_timeout }, + { "send non-block", test_send_nonblock }, + { "read only options", test_readonly_options }, + { "socket base", test_socket_base }, + { "socket name", test_socket_name }, + { "socket name oversize", test_socket_name_oversize }, + { "send recv", test_send_recv }, + { "connection refused", test_connection_refused }, + { "late connection", test_late_connection }, + { "address busy", test_address_busy }, + { "bad url", test_bad_url }, + { "url option", test_url_option }, + { "listener options", test_listener_options }, + { "dialer options", test_dialer_options }, + { "timeout options", test_timeout_options }, + { "size options", test_size_options }, + { "endpoint absent options", test_endpoint_absent_options }, + { "endpoint types", test_endpoint_types }, + + { NULL, NULL }, +}; |
