diff options
| author | Garrett D'Amore <garrett@damore.org> | 2018-05-25 19:35:52 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2018-05-29 16:05:23 -0700 |
| commit | 33dc5d611f578ace9833a80dc006a34b09da18af (patch) | |
| tree | 2351fd7d197530493dbd27034ae9e1546c2e299c /tests | |
| parent | fe5336ec1f9f27045f2c27ac253285c8447aa653 (diff) | |
| download | nng-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.txt | 36 | ||||
| -rw-r--r-- | tests/aio.c | 3 | ||||
| -rw-r--r-- | tests/compat_ws.c | 2 | ||||
| -rw-r--r-- | tests/platform.c | 64 | ||||
| -rw-r--r-- | tests/survey.c | 2 | ||||
| -rw-r--r-- | tests/synch.c | 57 | ||||
| -rw-r--r-- | tests/tcp6.c | 66 |
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(); }) |
