aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-05-25 19:35:52 -0700
committerGarrett D'Amore <garrett@damore.org>2018-05-29 16:05:23 -0700
commit33dc5d611f578ace9833a80dc006a34b09da18af (patch)
tree2351fd7d197530493dbd27034ae9e1546c2e299c /tests
parentfe5336ec1f9f27045f2c27ac253285c8447aa653 (diff)
downloadnng-33dc5d611f578ace9833a80dc006a34b09da18af.tar.gz
nng-33dc5d611f578ace9833a80dc006a34b09da18af.tar.bz2
nng-33dc5d611f578ace9833a80dc006a34b09da18af.zip
fixes #484 crashes in websocket transport
fixes #490 posix_epdesc use-after-free bug fixes #489 Sanitizer based testing would help fixes #492 Numerous memory leaks found with sanitizer This introduces support for compiler-based sanitizers when using clang or gcc (and not on Windows). See NNG_SANITIZER for possible settings such as "thread" or "address". Furthermore, we have fixed the issues we found with both the thread and address sanitizers. We believe that the thread issues pointed to a low frequency use-after-free responsible for rare crashes in some of the tests. The tests generally have their timeouts doubled when running under a sanitizer, to account for the extra long times that the sanitizer can cause these to take. While here, we also changed the compat_ws test to avoid a particularly painful and time consuming DNS lookup, and we made the nngcat_unlimited test a bit more robust by waiting before sending traffic.
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt36
-rw-r--r--tests/aio.c3
-rw-r--r--tests/compat_ws.c2
-rw-r--r--tests/platform.c64
-rw-r--r--tests/survey.c2
-rw-r--r--tests/synch.c57
-rw-r--r--tests/tcp6.c66
7 files changed, 115 insertions, 115 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9ba25882..4139c046 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -38,11 +38,17 @@ include_directories(AFTER SYSTEM ${PROJECT_SOURCE_DIR}/src)
if (NNG_TESTS)
+ if (NOT NNG_SANITIZER STREQUAL "none")
+ set(TIMEOUT_FACTOR 2)
+ else()
+ set (TIMEOUT_FACTOR 1)
+ endif()
set (NNG_TEST_PORT 13000)
macro (add_nng_test NAME TIMEOUT)
add_executable (${NAME} ${NAME}.c convey.c)
target_link_libraries (${NAME} ${PROJECT_NAME} Threads::Threads)
add_test (NAME ${NAME} COMMAND ${NAME} -v -p TEST_PORT=${NNG_TEST_PORT})
+ math (EXPR TIMEOUT ${TIMEOUT}*${TIMEOUT_FACTOR})
set_tests_properties (${NAME} PROPERTIES TIMEOUT ${TIMEOUT})
math (EXPR NNG_TEST_PORT "${NNG_TEST_PORT}+20")
endmacro (add_nng_test)
@@ -181,21 +187,21 @@ add_nng_test2(surveypoll 5 NNG_PROTO_SURVEYOR0 NNG_PROTO_RESPONDENT0)
# is because we don't want to make modifications to partially enable some
# of these tests. Folks minimizing the library probably don't care too
# much about these anyway.
-add_nng_compat_test(compat_block 5)
-add_nng_compat_test(compat_bug777 5)
-add_nng_compat_test(compat_bus 5)
-add_nng_compat_test(compat_cmsg 5)
-add_nng_compat_test(compat_msg 5)
-add_nng_compat_test(compat_iovec 5)
-add_nng_compat_test(compat_device 5)
-add_nng_compat_test(compat_pair 5)
-add_nng_compat_test(compat_pipeline 5)
-add_nng_compat_test(compat_poll 5)
-add_nng_compat_test(compat_reqrep 5)
-add_nng_compat_test(compat_survey 5)
-add_nng_compat_test(compat_reqttl 5)
-add_nng_compat_test(compat_shutdown 5)
-add_nng_compat_test(compat_surveyttl 5)
+add_nng_compat_test(compat_block 10)
+add_nng_compat_test(compat_bug777 10)
+add_nng_compat_test(compat_bus 10)
+add_nng_compat_test(compat_cmsg 10)
+add_nng_compat_test(compat_msg 10)
+add_nng_compat_test(compat_iovec 10)
+add_nng_compat_test(compat_device 10)
+add_nng_compat_test(compat_pair 10)
+add_nng_compat_test(compat_pipeline 10)
+add_nng_compat_test(compat_poll 10)
+add_nng_compat_test(compat_reqrep 10)
+add_nng_compat_test(compat_survey 10)
+add_nng_compat_test(compat_reqttl 10)
+add_nng_compat_test(compat_shutdown 10)
+add_nng_compat_test(compat_surveyttl 10)
add_nng_compat_test(compat_tcp 60)
add_nng_compat_test(compat_ws 60)
diff --git a/tests/aio.c b/tests/aio.c
index 2aa96de5..bd5c5097 100644
--- a/tests/aio.c
+++ b/tests/aio.c
@@ -36,7 +36,6 @@ sleepdone(void *arg)
}
Main({
-
Test("AIO operations", {
const char *addr = "inproc://aio";
@@ -170,7 +169,6 @@ Main({
So(done == 1);
So(nng_aio_result(a) == NNG_ECANCELED);
})
-
});
Convey("We cannot set insane IOVs", {
@@ -179,6 +177,7 @@ Main({
So(nng_aio_alloc(&aio, NULL, NULL) == 0);
So(nng_aio_set_iov(aio, 1024, &iov) == NNG_EINVAL);
+ nng_aio_free(aio);
});
});
diff --git a/tests/compat_ws.c b/tests/compat_ws.c
index 6d019364..2c302712 100644
--- a/tests/compat_ws.c
+++ b/tests/compat_ws.c
@@ -156,7 +156,7 @@ int main (int argc, const char *argv[])
rc = nn_connect (sc, "ws://:5555");
nn_assert (rc < 0);
errno_assert (nn_errno () == EINVAL);
- rc = nn_connect (sc, "ws://-hostname:5555");
+ rc = nn_connect (sc, "ws://-hostname.:5555");
nn_assert (rc < 0);
errno_assert (nn_errno () == EINVAL);
rc = nn_connect (sc, "ws://abc.123.---.#:5555");
diff --git a/tests/platform.c b/tests/platform.c
index 168f7879..51dc41fc 100644
--- a/tests/platform.c
+++ b/tests/platform.c
@@ -15,35 +15,24 @@
#include "stubs.h"
-// Add is for testing threads.
-void
-add(void *arg)
-{
- *(int *) arg += 1;
-}
-
-// Notify tests for verifying condvars.
-struct notifyarg {
- int did;
- nng_duration when;
- nng_mtx * mx;
- nng_cv * cv;
+struct addarg {
+ int cnt;
+ nng_mtx *mx;
+ nng_cv * cv;
};
void
-notifyafter(void *arg)
+add(void *arg)
{
- struct notifyarg *na = arg;
+ struct addarg *aa = arg;
- nng_msleep(na->when);
- nng_mtx_lock(na->mx);
- na->did = 1;
- nng_cv_wake(na->cv);
- nng_mtx_unlock(na->mx);
+ nng_mtx_lock(aa->mx);
+ aa->cnt++;
+ nng_cv_wake(aa->cv);
+ nng_mtx_unlock(aa->mx);
}
TestMain("Platform Operations", {
-
// This is required for anything else to work
Convey("The clock works", {
uint64_t now = getms();
@@ -79,35 +68,46 @@ TestMain("Platform Operations", {
So(nng_mtx_alloc(&mx) == 0);
Reset({ nng_mtx_free(mx); });
- Convey("We can lock a mutex", {
+ Convey("We can lock and unlock mutex", {
nng_mtx_lock(mx);
So(1);
- Convey("And we can unlock it", {
+ nng_mtx_unlock(mx);
+ So(1);
+ Convey("And then lock it again", {
+ nng_mtx_lock(mx);
+ So(1);
nng_mtx_unlock(mx);
So(1);
- Convey("And then lock it again", {
- nng_mtx_lock(mx);
- So(1);
- nng_mtx_unlock(mx);
- So(1);
- });
});
});
});
Convey("Threads work", {
static nng_thread *thr;
- int val = 0;
int rv;
+ struct addarg aa;
+
+ So(nng_mtx_alloc(&aa.mx) == 0);
+ So(nng_cv_alloc(&aa.cv, aa.mx) == 0);
+ Reset({
+ nng_mtx_free(aa.mx);
+ nng_cv_free(aa.cv);
+ });
+ aa.cnt = 0;
Convey("We can create threads", {
- rv = nng_thread_create(&thr, add, &val);
+ rv = nng_thread_create(&thr, add, &aa);
So(rv == 0);
Reset({ nng_thread_destroy(thr); });
Convey("It ran", {
- nng_msleep(50); // for context switch
+ int val;
+ nng_mtx_lock(aa.mx);
+ while ((val = aa.cnt) == 0) {
+ nng_cv_wait(aa.cv);
+ }
+ nng_mtx_unlock(aa.mx);
So(val == 1);
});
});
diff --git a/tests/survey.c b/tests/survey.c
index d6d35c1b..5f3001e7 100644
--- a/tests/survey.c
+++ b/tests/survey.c
@@ -131,6 +131,7 @@ TestMain("SURVEY pattern", {
So(nng_sendmsg(surv, msg, 0) == 0);
nng_aio_wait(aio);
So(nng_aio_result(aio) == NNG_ECANCELED);
+ nng_aio_free(aio);
});
Convey("Sending a NULL message does not panic", {
@@ -331,5 +332,4 @@ TestMain("SURVEY pattern", {
So(nng_sendmsg(resp, msg, 0) == 0);
So(nng_recvmsg(surv, &msg, 0) == NNG_ETIMEDOUT);
});
-
})
diff --git a/tests/synch.c b/tests/synch.c
index e767cad8..cf75e20c 100644
--- a/tests/synch.c
+++ b/tests/synch.c
@@ -45,42 +45,39 @@ test_sync(void)
So(nng_mtx_alloc(&mx) == 0);
Reset({ nng_mtx_free(mx); });
- Convey("We can lock a mutex", {
+ Convey("We can lock and unlock a mutex", {
nng_mtx_lock(mx);
So(1);
- Convey("And we can unlock it", {
+ nng_mtx_unlock(mx);
+ So(1);
+ Convey("And then lock it again", {
+ nng_mtx_lock(mx);
+ So(1);
nng_mtx_unlock(mx);
So(1);
- Convey("And then lock it again", {
- nng_mtx_lock(mx);
- So(1);
- nng_mtx_unlock(mx);
- So(1);
- });
});
- Convey("Things block properly", {
- So(nng_mtx_alloc(&arg.mx) == 0);
- So(nng_cv_alloc(&arg.cv, arg.mx) == 0);
- arg.did = 0;
- arg.when = 0;
- nng_mtx_lock(arg.mx);
- So(nng_thread_create(
- &thr, notifyafter, &arg) == 0);
- nng_msleep(10);
- So(arg.did == 0);
- nng_mtx_unlock(arg.mx);
- nng_msleep(10);
- nng_mtx_lock(arg.mx);
- while (!arg.did) {
- nng_cv_wait(arg.cv);
- }
- So(arg.did != 0);
- nng_mtx_unlock(arg.mx);
- nng_thread_destroy(thr);
- nng_cv_free(arg.cv);
- nng_mtx_free(arg.mx);
- })
});
+ Convey("Things block properly", {
+ So(nng_mtx_alloc(&arg.mx) == 0);
+ So(nng_cv_alloc(&arg.cv, arg.mx) == 0);
+ arg.did = 0;
+ arg.when = 0;
+ nng_mtx_lock(arg.mx);
+ So(nng_thread_create(&thr, notifyafter, &arg) == 0);
+ nng_msleep(10);
+ So(arg.did == 0);
+ nng_mtx_unlock(arg.mx);
+ nng_msleep(10);
+ nng_mtx_lock(arg.mx);
+ while (!arg.did) {
+ nng_cv_wait(arg.cv);
+ }
+ So(arg.did != 0);
+ nng_mtx_unlock(arg.mx);
+ nng_thread_destroy(thr);
+ nng_cv_free(arg.cv);
+ nng_mtx_free(arg.mx);
+ })
});
Convey("Condition variables work", {
diff --git a/tests/tcp6.c b/tests/tcp6.c
index c023997f..86898b46 100644
--- a/tests/tcp6.c
+++ b/tests/tcp6.c
@@ -45,46 +45,34 @@ check_props_v6(nng_msg *msg)
memset(loopback, 0, sizeof(loopback));
loopback[15] = 1;
- Convey("IPv6 Local address property works", {
- nng_sockaddr la;
- z = sizeof(nng_sockaddr);
- p = nng_msg_get_pipe(msg);
- So(nng_pipe_id(p) > 0);
- So(nng_pipe_getopt(p, NNG_OPT_LOCADDR, &la, &z) == 0);
- So(z == sizeof(la));
- So(la.s_family == NNG_AF_INET6);
- // So(la.s_in.sa_port == (trantest_port - 1));
- So(la.s_in6.sa_port != 0);
- So(memcmp(la.s_in6.sa_addr, loopback, 16) == 0);
- });
-
- Convey("IPv6 Remote address property works", {
- nng_sockaddr ra;
- z = sizeof(nng_sockaddr);
- p = nng_msg_get_pipe(msg);
- So(nng_pipe_id(p) > 0);
- So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0);
- So(z == sizeof(ra));
- So(ra.s_family == NNG_AF_INET6);
- So(ra.s_in6.sa_port != 0);
- So(memcmp(ra.s_in6.sa_addr, loopback, 16) == 0);
- });
-
- Convey("Malformed TCPv6 addresses do not panic", {
- nng_socket s1;
- So(nng_pair_open(&s1) == 0);
- Reset({ nng_close(s1); });
- So(nng_dial(s1, "tcp://::1", NULL, 0) == NNG_EADDRINVAL);
- So(nng_dial(s1, "tcp://::1:5055", NULL, 0) == NNG_EADDRINVAL);
- So(nng_dial(s1, "tcp://[::1]", NULL, 0) == NNG_EADDRINVAL);
- });
+ // IPv6 Local address property works
+ nng_sockaddr la;
+ z = sizeof(nng_sockaddr);
+ p = nng_msg_get_pipe(msg);
+ So(nng_pipe_id(p) > 0);
+ So(nng_pipe_getopt(p, NNG_OPT_LOCADDR, &la, &z) == 0);
+ So(z == sizeof(la));
+ So(la.s_family == NNG_AF_INET6);
+ // So(la.s_in.sa_port == (trantest_port - 1));
+ So(la.s_in6.sa_port != 0);
+ So(memcmp(la.s_in6.sa_addr, loopback, 16) == 0);
+
+ // IPv6 Remote address property works
+ nng_sockaddr ra;
+ z = sizeof(nng_sockaddr);
+ p = nng_msg_get_pipe(msg);
+ So(nng_pipe_id(p) > 0);
+ So(nng_pipe_getopt(p, NNG_OPT_REMADDR, &ra, &z) == 0);
+ So(z == sizeof(ra));
+ So(ra.s_family == NNG_AF_INET6);
+ So(ra.s_in6.sa_port != 0);
+ So(memcmp(ra.s_in6.sa_addr, loopback, 16) == 0);
return (0);
}
TestMain("TCP (IPv6) Transport", {
-
nni_init();
if (has_v6()) {
@@ -93,5 +81,15 @@ TestMain("TCP (IPv6) Transport", {
SkipSo("IPv6 not available");
}
+ Convey("Malformed TCPv6 addresses do not panic", {
+ nng_socket s1;
+
+ So(nng_pair_open(&s1) == 0);
+ Reset({ nng_close(s1); });
+ So(nng_dial(s1, "tcp://::1", NULL, 0) == NNG_EADDRINVAL);
+ So(nng_dial(s1, "tcp://::1:5055", NULL, 0) == NNG_EADDRINVAL);
+ So(nng_dial(s1, "tcp://[::1]", NULL, 0) == NNG_EADDRINVAL);
+ });
+
nng_fini();
})