0
0
mirror of https://github.com/zeromq/libzmq.git synced 2025-01-02 03:08:04 +08:00

Merge pull request #2990 from sigiesec/migrate-to-unity

Problem: test assertion failures do not clean up properly
This commit is contained in:
Luca Boccassi 2018-03-14 13:25:02 +00:00 committed by GitHub
commit 59516ed51a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 170 additions and 88 deletions

View File

@ -18,6 +18,27 @@ On many slower environments, like embedded systems, VMs or CI systems, tests mig
fail because it takes time for sockets to settle after a connect. If you need
to add a sleep, please be consistent with all the other tests and use:
msleep (SETTLE_TIME);
# Ensure proper cleanup
If a test program uses unity, it will execute test cases individually, and will continue to run further test cases if an assertion in one test case fails. However, the test case that had an assertion failure will be aborted.
To ensure that the resources of the test case are properly cleaned up, use appropriate setUp and tearDown functions. These are run by unity before each test case starts resp. after it ended (whether successfully or not).
The same setUp and tearDown function is used for all test cases in a test program.
For many test cases, the following setUp and tearDown functions will be appropriate:
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
Within the tests, do not use zmq_socket and zmq_close then but test_context_socket and test_context_socket_close instead. These functions will register/unregister sockets with the test_context.
All sockets not closed when tearDown is executed, with forcibly be closed with linger=0 before terminating the context. Note that it is a misuse not to close sockets during successful test execution,
and a warning will be output.
# Building tests in Windows

View File

@ -34,10 +34,12 @@
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
const int MAX_SENDS = 10000;
@ -50,19 +52,12 @@ enum TestType
void test_defaults ()
{
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
// Set up bind socket
void *bind_socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (bind_socket);
void *bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
// Set up connect socket
void *connect_socket = zmq_socket (ctx, ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (connect_socket);
void *connect_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
// Send until we block
@ -81,9 +76,8 @@ void test_defaults ()
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Clean up
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
// Default values are 1000 on send and 1000 one receive, so 2000 total
TEST_ASSERT_EQUAL_INT (2000, send_count);
@ -91,36 +85,29 @@ void test_defaults ()
int count_msg (int send_hwm, int recv_hwm, TestType testType)
{
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *bind_socket;
void *connect_socket;
if (testType == BIND_FIRST) {
// Set up bind socket
bind_socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (bind_socket);
bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
// Set up connect socket
connect_socket = zmq_socket (ctx, ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (connect_socket);
connect_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
connect_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
} else {
// Set up connect socket
connect_socket = zmq_socket (ctx, ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (connect_socket);
connect_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
connect_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
// Set up bind socket
bind_socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (bind_socket);
bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
@ -146,9 +133,8 @@ int count_msg (int send_hwm, int recv_hwm, TestType testType)
recv_string_expect_success (bind_socket, NULL, 0);
// Clean up
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
return send_count;
}
@ -165,12 +151,8 @@ int test_inproc_connect_first (int send_hwm, int recv_hwm)
int test_inproc_connect_and_close_first (int send_hwm, int recv_hwm)
{
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
// Set up connect socket
void *connect_socket = zmq_socket (ctx, ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (connect_socket);
void *connect_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (connect_socket, ZMQ_SNDHWM,
&send_hwm, sizeof (send_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
@ -182,11 +164,10 @@ int test_inproc_connect_and_close_first (int send_hwm, int recv_hwm)
++send_count;
// Close connect
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
test_context_socket_close (connect_socket);
// Set up bind socket
void *bind_socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (bind_socket);
void *bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
@ -199,8 +180,7 @@ int test_inproc_connect_and_close_first (int send_hwm, int recv_hwm)
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Clean up
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (bind_socket);
return send_count;
}

View File

@ -34,10 +34,12 @@
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
#ifdef ZMQ_BUILD_DRAFT_API
@ -59,10 +61,7 @@ bool send_msg_to_peer_if_ready (void *router, const char *peer_routing_id)
void test_get_peer_state ()
{
#ifdef ZMQ_BUILD_DRAFT_API
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *router = zmq_socket (ctx, ZMQ_ROUTER);
TEST_ASSERT_NOT_NULL (router);
void *router = test_context_socket (ZMQ_ROUTER);
int mandatory = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY,
@ -71,11 +70,8 @@ void test_get_peer_state ()
const char *my_endpoint = "inproc://test_get_peer_state";
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, my_endpoint));
void *dealer1 = zmq_socket (ctx, ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (dealer1);
void *dealer2 = zmq_socket (ctx, ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (dealer2);
void *dealer1 = test_context_socket (ZMQ_DEALER);
void *dealer2 = test_context_socket (ZMQ_DEALER);
// Lower HWMs to allow doing the test with fewer messages
const int hwm = 100;
@ -156,10 +152,9 @@ void test_get_peer_state ()
TEST_ASSERT_TRUE (dealer2_blocked);
zmq_poller_destroy (&poller);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (router));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (dealer1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (dealer2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (router);
test_context_socket_close (dealer1);
test_context_socket_close (dealer2);
#endif
}
@ -174,12 +169,8 @@ void test_get_peer_state_corner_cases ()
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno);
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *dealer = zmq_socket (ctx, ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (dealer);
void *router = zmq_socket (ctx, ZMQ_ROUTER);
TEST_ASSERT_NOT_NULL (router);
void *dealer = test_context_socket (ZMQ_DEALER);
void *router = test_context_socket (ZMQ_ROUTER);
// call get_peer_state with a non-ROUTER socket
rc = zmq_socket_get_peer_state (dealer, peer_routing_id,
@ -193,9 +184,8 @@ void test_get_peer_state_corner_cases ()
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EHOSTUNREACH, errno);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (router));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (dealer));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (router);
test_context_socket_close (dealer);
#endif
}
@ -203,10 +193,7 @@ void test_basic ()
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *router = zmq_socket (ctx, ZMQ_ROUTER);
TEST_ASSERT_NOT_NULL (router);
void *router = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, "tcp://127.0.0.1:*"));
TEST_ASSERT_SUCCESS_ERRNO (
@ -227,8 +214,7 @@ void test_basic ()
TEST_ASSERT_EQUAL_INT (EHOSTUNREACH, errno);
// Create dealer called "X" and connect it to our router
void *dealer = zmq_socket (ctx, ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (dealer);
void *dealer = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (dealer, ZMQ_ROUTING_ID, "X", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));
@ -241,9 +227,8 @@ void test_basic ()
send_string_expect_success (router, "X", ZMQ_SNDMORE);
send_string_expect_success (router, "Hello", 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (router));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (dealer));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main (void)

View File

@ -28,26 +28,28 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void setUp ()
{
}
void tearDown ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
const int MAX_SENDS = 10000;
void test_change_before_connected ()
{
int rc;
void *ctx = zmq_ctx_new ();
void *bind_socket = zmq_socket (ctx, ZMQ_PUSH);
void *connect_socket = zmq_socket (ctx, ZMQ_PULL);
void *bind_socket = test_context_socket (ZMQ_PUSH);
void *connect_socket = test_context_socket (ZMQ_PULL);
int val = 2;
rc = zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &val, sizeof (val));
@ -71,18 +73,16 @@ void test_change_before_connected ()
TEST_ASSERT_EQUAL_INT (4, send_count);
zmq_close (bind_socket);
zmq_close (connect_socket);
zmq_ctx_term (ctx);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}
void test_change_after_connected ()
{
int rc;
void *ctx = zmq_ctx_new ();
void *bind_socket = zmq_socket (ctx, ZMQ_PUSH);
void *connect_socket = zmq_socket (ctx, ZMQ_PULL);
void *bind_socket = test_context_socket (ZMQ_PUSH);
void *connect_socket = test_context_socket (ZMQ_PULL);
int val = 1;
rc = zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &val, sizeof (val));
@ -110,9 +110,8 @@ void test_change_after_connected ()
TEST_ASSERT_EQUAL_INT (6, send_count);
zmq_close (bind_socket);
zmq_close (connect_socket);
zmq_ctx_term (ctx);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}
int send_until_wouldblock (void *socket)
@ -138,10 +137,9 @@ int test_fill_up_to_hwm (void *socket, int sndhwm)
void test_decrease_when_full ()
{
int rc;
void *ctx = zmq_ctx_new ();
void *bind_socket = zmq_socket (ctx, ZMQ_PUSH);
void *connect_socket = zmq_socket (ctx, ZMQ_PULL);
void *bind_socket = test_context_socket (ZMQ_PUSH);
void *connect_socket = test_context_socket (ZMQ_PULL);
int val = 1;
rc = zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &val, sizeof (val));
@ -190,9 +188,8 @@ void test_decrease_when_full ()
// Fill up to new hwm
test_fill_up_to_hwm (bind_socket, sndhwm);
zmq_close (bind_socket);
zmq_close (connect_socket);
zmq_ctx_term (ctx);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}

View File

@ -85,3 +85,102 @@ void recv_string_expect_success (void *socket, const char *str, int flags)
if (str)
TEST_ASSERT_EQUAL_STRING_LEN (str, buffer, len);
}
// do not call from tests directly, use setup_test_context, get_test_context and teardown_test_context only
void *internal_manage_test_context (bool init, bool clear)
{
static void *test_context = NULL;
if (clear) {
TEST_ASSERT_NOT_NULL (test_context);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (test_context));
test_context = NULL;
} else {
if (init) {
TEST_ASSERT_NULL (test_context);
test_context = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (test_context);
}
}
return test_context;
}
#define MAX_TEST_SOCKETS 128
void internal_manage_test_sockets (void *socket, bool add)
{
static void *test_sockets[MAX_TEST_SOCKETS];
static size_t test_socket_count = 0;
if (!socket) {
assert (!add);
// force-close all sockets
if (test_socket_count) {
for (size_t i = 0; i < test_socket_count; ++i) {
close_zero_linger (test_sockets[i]);
}
fprintf (stderr,
"WARNING: Forced closure of %i sockets, this is an "
"implementation error unless the test case failed\n",
(int) test_socket_count);
test_socket_count = 0;
}
} else {
if (add) {
++test_socket_count;
TEST_ASSERT_LESS_THAN_MESSAGE (MAX_TEST_SOCKETS, test_socket_count,
"MAX_TEST_SOCKETS must be "
"increased, or you cannot use the "
"test context");
test_sockets[test_socket_count - 1] = socket;
} else {
bool found = false;
for (size_t i = 0; i < test_socket_count; ++i) {
if (test_sockets[i] == socket) {
found = true;
}
if (found) {
if (i < test_socket_count)
test_sockets[i] = test_sockets[i + 1];
}
}
TEST_ASSERT_TRUE (found);
--test_socket_count;
}
}
}
void setup_test_context ()
{
internal_manage_test_context (true, false);
}
void *get_test_context ()
{
return internal_manage_test_context (false, false);
}
void teardown_test_context ()
{
// this condition allows an explicit call to teardown_test_context from a
// test. if this is never used, it should probably be removed, to detect
// misuses
if (get_test_context ()) {
internal_manage_test_sockets (NULL, false);
internal_manage_test_context (false, true);
}
}
void *test_context_socket (int type)
{
void *const socket = zmq_socket (get_test_context (), type);
TEST_ASSERT_NOT_NULL (socket);
internal_manage_test_sockets (socket, true);
return socket;
}
void *test_context_socket_close (void *socket)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
internal_manage_test_sockets (socket, false);
return socket;
}