aboutsummaryrefslogtreecommitdiff
path: root/tests/sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sock.c')
-rw-r--r--tests/sock.c1139
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 },
+};