1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-08-03 14:41:48 +02:00

Initial ZMQ bindings.

This commit is contained in:
Sandu Liviu Catalin
2021-02-02 19:07:02 +02:00
parent 82b7f75b80
commit fc9419677f
1092 changed files with 147348 additions and 92 deletions

308
vendor/ZMQ/tests/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,308 @@
# CMake build script for ZeroMQ tests
cmake_minimum_required(VERSION "2.8.1")
# On Windows: solution file will be called tests.sln
project(tests)
set(tests
test_ancillaries
test_system
test_pair_inproc
test_pair_tcp
test_reqrep_inproc
test_reqrep_tcp
test_hwm
test_hwm_pubsub
test_reqrep_device
test_sub_forward
test_invalid_rep
test_msg_flags
test_msg_ffn
test_connect_resolve
test_immediate
test_last_endpoint
test_term_endpoint
test_router_mandatory
test_probe_router
test_stream
test_stream_empty
test_stream_disconnect
test_disconnect_inproc
test_unbind_wildcard
test_ctx_options
test_ctx_destroy
test_security_no_zap_handler
test_security_null
test_security_plain
test_security_zap
test_iov
test_spec_req
test_spec_rep
test_spec_dealer
test_spec_router
test_spec_pushpull
test_req_correlate
test_req_relaxed
test_conflate
test_inproc_connect
test_issue_566
test_shutdown_stress
test_timeo
test_many_sockets
test_diffserv
test_connect_rid
test_xpub_nodrop
test_pub_invert_matching
test_setsockopt
test_sockopt_hwm
test_heartbeats
test_atomics
test_bind_src_address
test_capabilities
test_metadata
test_router_handover
test_srcfd
test_stream_timeout
test_xpub_manual
test_xpub_welcome_msg
test_xpub_verbose
test_base85
test_bind_after_connect_tcp
test_sodium
test_monitor
test_socket_null
test_reconnect_ivl
test_reconnect_options
test_tcp_accept_filter
test_mock_pub_sub)
if(NOT WIN32)
list(APPEND tests test_security_gssapi test_socks test_connect_null_fuzzer test_bind_null_fuzzer test_connect_fuzzer test_bind_fuzzer)
endif()
if(ZMQ_HAVE_CURVE)
list(APPEND tests test_security_curve)
if(NOT WIN32)
list(APPEND tests test_connect_curve_fuzzer test_bind_curve_fuzzer test_z85_decode_fuzzer)
endif()
endif()
option(ENABLE_CAPSH "Run tests that require sudo and capsh (for cap_net_admin)" OFF)
if(ENABLE_CAPSH)
find_program(CAPSH_PROGRAM NAMES capsh)
if(CAPSH_PROGRAM)
list(APPEND tests test_pair_tcp_cap_net_admin)
else()
message(STATUS "capsh not found, skipping tests that require CAP_NET_ADMIN")
endif()
endif()
if(ZMQ_HAVE_IPC)
list(APPEND tests test_ipc_wildcard test_pair_ipc test_reqrep_ipc test_rebind_ipc)
endif()
if(NOT WIN32)
list(
APPEND
tests
test_proxy
test_proxy_hwm
test_proxy_single_socket
test_proxy_terminate
test_getsockopt_memset
test_filter_ipc
test_stream_exceeds_buffer
test_router_mandatory_hwm
test_use_fd
test_zmq_poll_fd)
if(HAVE_FORK)
list(APPEND tests test_fork)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
list(APPEND tests test_abstract_ipc)
if(ZMQ_HAVE_TIPC)
list(
APPEND
tests
test_address_tipc
test_pair_tipc
test_reqrep_device_tipc
test_reqrep_tipc
test_router_mandatory_tipc
test_sub_forward_tipc
test_connect_delay_tipc
test_shutdown_stress_tipc
test_term_endpoint_tipc)
endif()
endif()
endif()
if(WITH_VMCI)
list(APPEND tests test_pair_vmci test_reqrep_vmci)
endif()
if(ENABLE_DRAFTS)
list(
APPEND
tests
test_poller
test_thread_safe
test_client_server
test_timers
test_radio_dish
test_scatter_gather
test_dgram
test_app_meta
test_router_notify
test_xpub_manual_last_value
test_peer
test_msg_init
test_channel
test_hello_msg
test_disconnect_msg
)
endif()
if(ZMQ_HAVE_WS)
list(APPEND tests test_ws_transport)
if(ZMQ_HAVE_WSS)
list(APPEND tests test_wss_transport)
endif()
endif()
# add location of platform.hpp for Windows builds
if(WIN32)
add_definitions(-DZMQ_CUSTOM_PLATFORM_HPP)
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
# Same name on 64bit systems
link_libraries(ws2_32.lib)
endif()
add_library(
unity STATIC
"${CMAKE_CURRENT_LIST_DIR}/../external/unity/unity.c" "${CMAKE_CURRENT_LIST_DIR}/../external/unity/unity.h"
"${CMAKE_CURRENT_LIST_DIR}/../external/unity/unity_internals.h")
set_target_properties(unity PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_LIST_DIR}/../external/unity/unity.h")
target_compile_definitions(unity PUBLIC "UNITY_USE_COMMAND_LINE_ARGS" "UNITY_EXCLUDE_FLOAT")
target_include_directories(unity PUBLIC "${CMAKE_CURRENT_LIST_DIR}/../external/unity")
set(TESTUTIL_SOURCES
testutil.cpp
testutil.hpp
testutil_monitoring.cpp
testutil_monitoring.hpp
testutil_security.cpp
testutil_security.hpp
testutil_unity.cpp
testutil_unity.hpp)
if(BUILD_STATIC)
add_library(testutil-static STATIC ${TESTUTIL_SOURCES})
target_link_libraries(testutil-static libzmq-static ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} unity)
endif()
if(BUILD_SHARED)
add_library(testutil STATIC ${TESTUTIL_SOURCES})
target_link_libraries(testutil libzmq ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} unity)
endif()
if(BUILD_STATIC AND NOT BUILD_SHARED)
# use testutil-static for both tests and unit tests
set(TESTUTIL_LIB testutil-static)
else()
# use testutil for tests and testutil-static for unit tests
set(TESTUTIL_LIB testutil)
endif()
if(MSVC_VERSION LESS 1700)
set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/../external/unity/unity.c" PROPERTIES LANGUAGE CXX)
endif()
if(MSVC_VERSION LESS 1600)
target_compile_definitions(unity PUBLIC "UNITY_EXCLUDE_STDINT_H")
endif()
# add include dirs for all targets
include_directories("${ZeroMQ_SOURCE_DIR}/../include" "${ZeroMQ_BINARY_DIR}")
if(WIN32)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
endif()
# Does not work, times out every time
if(WIN32)
list(REMOVE_ITEM tests test_many_sockets)
endif()
foreach(test ${tests})
# target_sources not supported before CMake 3.1
if(ZMQ_HAVE_CURVE AND ${test} MATCHES test_security_curve)
add_executable(${test} ${test}.cpp "../src/tweetnacl.c" "../src/err.cpp" "../src/random.cpp" "../src/clock.cpp")
else()
add_executable(${test} ${test}.cpp)
endif()
target_link_libraries(${test} ${TESTUTIL_LIB})
if(WIN32)
# This is the output for Debug dynamic builds on Visual Studio 6.0 You should provide the correct directory, don't
# know how to do it automatically
find_path(LIBZMQ_PATH "libzmq.lib" PATHS "../bin/Win32/Debug/v120/dynamic")
if(NOT ${LIBZMQ_PATH} STREQUAL "LIBZMQ_PATH-NOTFOUND")
set_target_properties(${test} PROPERTIES LINK_FLAGS "/LIBPATH:${LIBZMQ_PATH}")
endif()
else()
# per-test directories not generated on OS X / Darwin
if(NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang.*")
link_directories(${test} PRIVATE "${ZeroMQ_SOURCE_DIR}/../lib")
endif()
endif()
if(RT_LIBRARY)
target_link_libraries(${test} ${RT_LIBRARY})
endif()
if(CMAKE_SYSTEM_NAME MATCHES "QNX")
target_link_libraries(${test} socket)
target_link_libraries(${test} m)
endif()
if(WIN32)
add_test(
NAME ${test}
WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}
COMMAND ${test})
else()
if(${test} MATCHES "_cap_net_admin")
add_test(NAME ${test} COMMAND sh -c "sudo ${CAPSH_PROGRAM} --caps=cap_net_admin+eip -- -c $<TARGET_FILE:${test}>")
else()
add_test(NAME ${test} COMMAND ${test})
endif()
endif()
set_tests_properties(${test} PROPERTIES TIMEOUT 10)
set_tests_properties(${test} PROPERTIES SKIP_RETURN_CODE 77)
endforeach()
# override timeout for these tests
if(ZMQ_HAVE_CURVE)
set_tests_properties(test_security_curve PROPERTIES TIMEOUT 60)
endif()
set_tests_properties(test_heartbeats PROPERTIES TIMEOUT 60)
if(WIN32 AND ENABLE_DRAFTS)
set_tests_properties(test_radio_dish PROPERTIES TIMEOUT 30)
endif()
# add additional required flags ZMQ_USE_TWEETNACL will already be defined when not using sodium
if(ZMQ_HAVE_CURVE AND NOT ZMQ_USE_TWEETNACL)
target_compile_definitions(test_security_curve PRIVATE "-DZMQ_USE_TWEETNACL")
endif()
set_tests_properties(test_security_zap PROPERTIES TIMEOUT 60)
set_tests_properties(test_reconnect_ivl PROPERTIES TIMEOUT 15)
# Check whether all tests in the current folder are present
file(READ "${CMAKE_CURRENT_LIST_FILE}" CURRENT_LIST_FILE_CONTENT)
file(GLOB ALL_TEST_SOURCES "test_*.cpp")
foreach(TEST_SOURCE ${ALL_TEST_SOURCES})
get_filename_component(TESTNAME "${TEST_SOURCE}" NAME_WE)
string(REGEX MATCH "${TESTNAME}" MATCH_TESTNAME "${CURRENT_LIST_FILE_CONTENT}")
if(NOT MATCH_TESTNAME)
message(AUTHOR_WARNING "Test '${TESTNAME}' is not known to CTest.")
endif()
endforeach()

45
vendor/ZMQ/tests/README.md vendored Normal file
View File

@@ -0,0 +1,45 @@
# Guidelines for tests
Write your test case as if you were writing clean application code. It should be safe to compile on all platforms.
Normally, you should only include the header files from the tests directory, e.g. `testutil.hpp`. Do not include files from src. Do not use the internal libzmq API. Tests for these should be placed in unittests instead.
If you must write non-portable code, wrap it in #ifdefs to ensure it will compile and run on all systems.
Note that testutil.hpp includes platform.h. Do not include it yourself as it changes location depending on the build system and OS.
All sources must contain the correct copyright header. Please copy from test_system.cpp if you're not certain.
Write new tests using the unity test framework. For an example, see test_sockopt_hwm.
Please use only ANSI C99 in test cases, no C++. This is to make the code more reusable.
On many slower environments, like embedded systems, VMs or CI systems, tests might
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
The tests are only built via cmake, not when using the checked-in Visual Studio .sln files.

76
vendor/ZMQ/tests/test_abstract_ipc.cpp vendored Normal file
View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
static const char test_endpoint[] = "ipc://@tmp-tester";
static const char test_endpoint_empty[] = "ipc://@";
void test_roundtrip ()
{
void *sb = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, test_endpoint));
char endpoint[MAX_SOCKET_STRING];
size_t size = sizeof (endpoint);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &size));
TEST_ASSERT_EQUAL_INT (0, strncmp (endpoint, test_endpoint, size));
void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, test_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_empty_abstract_name ()
{
void *sb = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_bind (sb, test_endpoint_empty));
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
RUN_TEST (test_empty_abstract_name);
return UNITY_END ();
}

107
vendor/ZMQ/tests/test_address_tipc.cpp vendored Normal file
View File

@@ -0,0 +1,107 @@
/*
Copyright (c) 2007-2018 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_tipc_port_name_and_domain ()
{
// test Port Name addressing
void *sb = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "tipc://{5560,0,0}"));
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "tipc://{5560,0}@0.0.0"));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_tipc_port_identity ()
{
char endpoint[256];
unsigned int z, c, n, ref;
void *sb = test_context_socket (ZMQ_REP);
void *sc = test_context_socket (ZMQ_REQ);
// Test binding to random Port Identity and
// test resolving assigned address, should return a properly formatted string
bind_loopback_tipc (sb, endpoint, sizeof endpoint);
int rc = sscanf (&endpoint[0], "tipc://<%u.%u.%u:%u>", &z, &c, &n, &ref);
TEST_ASSERT_EQUAL_INT (4, rc);
TEST_ASSERT_NOT_EQUAL_MESSAGE (
0, ref, "tipc port number must not be 0 after random assignment");
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_tipc_bad_addresses ()
{
// Test Port Name addressing
void *sb = test_context_socket (ZMQ_REP);
// Test binding to a fixed address, should fail
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_bind (sb, "tipc://<1.2.3:123123>"));
// Test connecting to random identity, should fail
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_connect (sb, "tipc://<*>"));
// Clean up
test_context_socket_close (sb);
}
int main ()
{
setup_test_environment ();
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_tipc_port_name_and_domain);
RUN_TEST (test_tipc_port_identity);
RUN_TEST (test_tipc_bad_addresses);
return UNITY_END ();
}

71
vendor/ZMQ/tests/test_ancillaries.cpp vendored Normal file
View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* File for adding tests for ancillary API methods and other miscellaenous
* API internals. Please ensure that when adding such tests into this file,
* that they are short-lived so they do not trigger timeouts in the
* CI build environments.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
}
void tearDown ()
{
}
void test_version ()
{
int major, minor, patch;
zmq_version (&major, &minor, &patch);
TEST_ASSERT_EQUAL_INT (ZMQ_VERSION_MAJOR, major);
TEST_ASSERT_EQUAL_INT (ZMQ_VERSION_MINOR, minor);
TEST_ASSERT_EQUAL_INT (ZMQ_VERSION_PATCH, patch);
}
void test_strerrror ()
{
TEST_ASSERT_NOT_NULL (zmq_strerror (EINVAL));
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_version);
RUN_TEST (test_strerrror);
return UNITY_END ();
}

169
vendor/ZMQ/tests/test_app_meta.cpp vendored Normal file
View File

@@ -0,0 +1,169 @@
/*
Copyright (c) 2007-2018 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
#include <string.h>
void setUp ()
{
}
void tearDown ()
{
}
void test_app_meta_reqrep ()
{
void *ctx;
zmq_msg_t msg;
void *rep_sock, *req_sock;
char connect_address[MAX_SOCKET_STRING];
const char *req_hello = "X-hello:hello";
const char *req_connection = "X-connection:primary";
const char *req_z85 = "X-bin:009c6";
const char *rep_hello = "X-hello:world";
const char *rep_connection = "X-connection:backup";
const char *bad_strings[] = {
":",
"key:",
":value",
"keyvalue",
"",
"X-"
"KeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKe"
"yTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyT"
"ooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyTooLongKeyToo"
"LongKeyTooLongKeyTooLongKeyTooLongKeyTooLong:value"};
ctx = zmq_ctx_new ();
rep_sock = zmq_socket (ctx, ZMQ_REP);
TEST_ASSERT_NOT_NULL (rep_sock);
req_sock = zmq_socket (ctx, ZMQ_REQ);
TEST_ASSERT_NOT_NULL (req_sock);
int rc =
zmq_setsockopt (rep_sock, ZMQ_METADATA, rep_hello, strlen (rep_hello));
TEST_ASSERT_EQUAL_INT (0, rc);
int l = 0;
rc = zmq_setsockopt (rep_sock, ZMQ_LINGER, &l, sizeof (l));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (rep_sock, ZMQ_METADATA, rep_connection,
strlen (rep_connection));
TEST_ASSERT_EQUAL_INT (0, rc);
for (int i = 0; i < 6; i++) {
rc = zmq_setsockopt (rep_sock, ZMQ_METADATA, bad_strings[i],
strlen (bad_strings[i]));
TEST_ASSERT_EQUAL_INT (-1, rc);
}
bind_loopback_ipv4 (rep_sock, connect_address, sizeof connect_address);
l = 0;
rc = zmq_setsockopt (req_sock, ZMQ_LINGER, &l, sizeof (l));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (req_sock, ZMQ_METADATA, req_hello, strlen (req_hello));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (req_sock, ZMQ_METADATA, req_connection,
strlen (req_connection));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (req_sock, ZMQ_METADATA, req_z85, strlen (req_z85));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_connect (req_sock, connect_address);
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_msg_init_size (&msg, 1);
TEST_ASSERT_EQUAL_INT (0, rc);
char *data = static_cast<char *> (zmq_msg_data (&msg));
data[0] = 1;
rc = zmq_msg_send (&msg, req_sock, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
rc = zmq_msg_init (&msg);
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_msg_recv (&msg, rep_sock, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
TEST_ASSERT_EQUAL_STRING ("hello", zmq_msg_gets (&msg, "X-hello"));
TEST_ASSERT_EQUAL_STRING ("primary", zmq_msg_gets (&msg, "X-connection"));
const char *const bindata = zmq_msg_gets (&msg, "X-bin");
TEST_ASSERT_NOT_NULL (bindata);
uint8_t rawdata[4];
const uint8_t *const ret = zmq_z85_decode (rawdata, bindata);
TEST_ASSERT_NOT_NULL (ret);
TEST_ASSERT_EQUAL_UINT8 (0, rawdata[0]);
TEST_ASSERT_EQUAL_UINT8 (1, rawdata[1]);
TEST_ASSERT_EQUAL_UINT8 (2, rawdata[2]);
TEST_ASSERT_EQUAL_UINT8 (3, rawdata[3]);
TEST_ASSERT_NULL (zmq_msg_gets (&msg, "X-foobar"));
TEST_ASSERT_NULL (zmq_msg_gets (&msg, "foobar"));
rc = zmq_msg_send (&msg, rep_sock, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
rc = zmq_msg_recv (&msg, req_sock, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
TEST_ASSERT_EQUAL_STRING ("world", zmq_msg_gets (&msg, "X-hello"));
TEST_ASSERT_EQUAL_STRING ("backup", zmq_msg_gets (&msg, "X-connection"));
rc = zmq_msg_close (&msg);
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_close (req_sock);
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_close (rep_sock);
TEST_ASSERT_EQUAL_INT (0, rc);
zmq_ctx_term (ctx);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_app_meta_reqrep);
return UNITY_END ();
}

65
vendor/ZMQ/tests/test_atomics.cpp vendored Normal file
View File

@@ -0,0 +1,65 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void setUp ()
{
}
void tearDown ()
{
}
void test ()
{
void *counter = zmq_atomic_counter_new ();
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_value (counter));
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_inc (counter));
TEST_ASSERT_EQUAL_INT (1, zmq_atomic_counter_inc (counter));
TEST_ASSERT_EQUAL_INT (2, zmq_atomic_counter_inc (counter));
TEST_ASSERT_EQUAL_INT (3, zmq_atomic_counter_value (counter));
TEST_ASSERT_EQUAL_INT (1, zmq_atomic_counter_dec (counter));
TEST_ASSERT_EQUAL_INT (1, zmq_atomic_counter_dec (counter));
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_dec (counter));
zmq_atomic_counter_set (counter, 2);
TEST_ASSERT_EQUAL_INT (1, zmq_atomic_counter_dec (counter));
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_dec (counter));
zmq_atomic_counter_destroy (&counter);
}
int main ()
{
UNITY_BEGIN ();
RUN_TEST (test);
return UNITY_END ();
}

204
vendor/ZMQ/tests/test_base85.cpp vendored Normal file
View File

@@ -0,0 +1,204 @@
/*
Copyright (c) 2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
}
void tearDown ()
{
}
// Test vector: rfc.zeromq.org/spec:32/Z85
void test__zmq_z85_encode__valid__success ()
{
static const size_t size = 8;
static const size_t length = size * 5 / 4;
static const uint8_t decoded[size] = {0x86, 0x4F, 0xD2, 0x6F,
0xB5, 0x59, 0xF7, 0x5B};
static const char expected[length + 1] = "HelloWorld";
char out_encoded[length + 1] = {0};
errno = 0;
TEST_ASSERT_NOT_NULL (zmq_z85_encode (out_encoded, decoded, size));
TEST_ASSERT_EQUAL_STRING (expected, out_encoded);
TEST_ASSERT_EQUAL_INT (0, zmq_errno ());
}
// Buffer length must be evenly divisible by 4 or must fail with EINVAL.
void test__zmq_z85_encode__invalid__failure (size_t size_)
{
errno = 0;
TEST_ASSERT_NULL (zmq_z85_encode (NULL, NULL, size_));
TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ());
}
// Test vector: rfc.zeromq.org/spec:32/Z85
void test__zmq_z85_decode__valid__success ()
{
static const size_t size = 10 * 4 / 5;
static const uint8_t expected[size] = {0x86, 0x4F, 0xD2, 0x6F,
0xB5, 0x59, 0xF7, 0x5B};
static const char *encoded = "HelloWorld";
uint8_t out_decoded[size] = {0};
errno = 0;
TEST_ASSERT_NOT_NULL (zmq_z85_decode (out_decoded, encoded));
TEST_ASSERT_EQUAL_INT (0, zmq_errno ());
TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, out_decoded, size);
}
// Invalid input data must fail with EINVAL.
template <size_t SIZE>
void test__zmq_z85_decode__invalid__failure (const char (&encoded_)[SIZE])
{
uint8_t decoded[SIZE * 4 / 5 + 1];
errno = 0;
TEST_ASSERT_NULL (zmq_z85_decode (decoded, encoded_));
TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ());
}
// call zmq_z85_encode, then zmq_z85_decode, and compare the results with the original
template <size_t SIZE>
void test__zmq_z85_encode__zmq_z85_decode__roundtrip (
const uint8_t (&test_data_)[SIZE])
{
char test_data_z85[SIZE * 5 / 4 + 1];
const char *const res1 = zmq_z85_encode (test_data_z85, test_data_, SIZE);
TEST_ASSERT_NOT_NULL (res1);
uint8_t test_data_decoded[SIZE];
const uint8_t *const res2 =
zmq_z85_decode (test_data_decoded, test_data_z85);
TEST_ASSERT_NOT_NULL (res2);
TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_decoded, SIZE);
}
// call zmq_z85_encode, then zmq_z85_decode, and compare the results with the original
template <size_t SIZE>
void test__zmq_z85_decode__zmq_z85_encode__roundtrip (
const char (&test_data_)[SIZE])
{
const size_t decoded_size = (SIZE - 1) * 4 / 5;
uint8_t test_data_decoded[decoded_size];
const uint8_t *const res1 = zmq_z85_decode (test_data_decoded, test_data_);
TEST_ASSERT_NOT_NULL (res1);
char test_data_z85[SIZE];
const char *const res2 =
zmq_z85_encode (test_data_z85, test_data_decoded, decoded_size);
TEST_ASSERT_NOT_NULL (res2);
TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_z85, SIZE);
}
#define def_test__zmq_z85_basename(basename, name, param) \
void test__zmq_z85_##basename##_##name () \
{ \
test__zmq_z85_##basename (param); \
}
#define def_test__zmq_z85_encode__invalid__failure(name, param) \
def_test__zmq_z85_basename (encode__invalid__failure, name, param)
def_test__zmq_z85_encode__invalid__failure (1, 1)
def_test__zmq_z85_encode__invalid__failure (42, 42)
#define def_test__zmq_z85_decode__invalid__failure(name, param) \
def_test__zmq_z85_basename (decode__invalid__failure, name, param)
// String length must be evenly divisible by 5 or must fail with EINVAL.
def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_multiple_chars,
"01234567")
def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_one_char, "0")
// decode invalid data with the maximum representable value
def_test__zmq_z85_decode__invalid__failure (max, "#####")
// decode invalid data with the minimum value beyond the limit
// "%nSc0" is 0xffffffff
def_test__zmq_z85_decode__invalid__failure (above_limit, "%nSc1")
// decode invalid data with an invalid character in the range of valid
// characters
def_test__zmq_z85_decode__invalid__failure (char_within, "####\0047")
// decode invalid data with an invalid character just below the range of valid
// characters
def_test__zmq_z85_decode__invalid__failure (char_adjacent_below, "####\0200")
// decode invalid data with an invalid character just above the range of valid
// characters
def_test__zmq_z85_decode__invalid__failure (char_adjacent_above, "####\0037")
#define def_test__encode__zmq_z85_decode__roundtrip(name, param) \
def_test__zmq_z85_basename (encode__zmq_z85_decode__roundtrip, name, param)
const uint8_t test_data_min[] = {0x00, 0x00, 0x00, 0x00};
const uint8_t test_data_max[] = {0xff, 0xff, 0xff, 0xff};
def_test__encode__zmq_z85_decode__roundtrip (min, test_data_min)
def_test__encode__zmq_z85_decode__roundtrip (max, test_data_max)
#define def_test__decode__zmq_z85_encode__roundtrip(name, param) \
def_test__zmq_z85_basename (decode__zmq_z85_encode__roundtrip, name, param)
const char test_data_regular[] = "r^/rM9M=rMToK)63O8dCvd9D<PY<7iGlC+{BiSnG";
def_test__decode__zmq_z85_encode__roundtrip (regular, test_data_regular)
int main ()
{
UNITY_BEGIN ();
RUN_TEST (test__zmq_z85_encode__valid__success);
RUN_TEST (test__zmq_z85_encode__invalid__failure_1);
RUN_TEST (test__zmq_z85_encode__invalid__failure_42);
RUN_TEST (test__zmq_z85_decode__valid__success);
RUN_TEST (
test__zmq_z85_decode__invalid__failure_indivisble_by_5_multiple_chars);
RUN_TEST (test__zmq_z85_decode__invalid__failure_indivisble_by_5_one_char);
RUN_TEST (test__zmq_z85_decode__invalid__failure_max);
RUN_TEST (test__zmq_z85_decode__invalid__failure_above_limit);
RUN_TEST (test__zmq_z85_decode__invalid__failure_char_within);
RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_below);
RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_above);
RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_min);
RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_max);
RUN_TEST (test__zmq_z85_decode__zmq_z85_encode__roundtrip_regular);
return UNITY_END ();
}

View File

@@ -0,0 +1,63 @@
/*
Copyright (c) 2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_x ()
{
void *sb = test_context_socket (ZMQ_DEALER);
void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, ENDPOINT_3));
send_string_expect_success (sc, "foobar", 0);
send_string_expect_success (sc, "baz", 0);
send_string_expect_success (sc, "buzz", 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, ENDPOINT_3));
recv_string_expect_success (sb, "foobar", 0);
recv_string_expect_success (sb, "baz", 0);
recv_string_expect_success (sb, "buzz", 0);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_x);
return UNITY_END ();
}

View File

@@ -0,0 +1,150 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include <string.h>
#include "testutil.hpp"
#include "testutil_security.hpp"
// Test that the ZMTP engine handles invalid handshake when binding
// https://rfc.zeromq.org/spec/37/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
const char *fixed_client_public =
"{{k*81)yMWEF{/BxdMd[5RL^qRFxBgoL<8m.D^KD";
const char *fixed_client_secret =
"N?Gmik8R[2ACw{b7*[-$S6[4}aO#?DB?#=<OQPc7";
const char *fixed_server_public =
"3.9-xXwy{g*w72TP*3iB9IJJRxlBH<ufTAvPd2>C";
const char *fixed_server_secret =
"T}t5GLq%&Qm1)y3ywu-}pY3KEA//{^Ut!M1ut+B4";
void *handler;
void *zap_thread;
void *server;
void *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
setup_test_context ();
memcpy (valid_client_public, fixed_client_public, 41);
setup_context_and_server_side (
&handler, &zap_thread, &server, &server_mon, my_endpoint, &zap_handler,
&socket_config_curve_server, (void *) fixed_server_secret);
fd_t client = connect_socket (my_endpoint);
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[512];
if (size >= 64) {
send (client, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (client, buf, 64, 0);
// Then send HELLO and expect WELCOME if there's enough data
if (size >= 202) {
send (client, (void *) data, 202, MSG_NOSIGNAL);
data += 202;
size -= 202;
recv (client, buf, 170, MSG_DONTWAIT);
}
// Then send READY and expect INITIATE if there's enough data
if (size >= 301) {
send (client, (void *) data, 301, MSG_NOSIGNAL);
data += 301;
size -= 301;
recv (client, buf, 512, MSG_DONTWAIT);
}
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
// Drain the queue, if any
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
// A well-behaved client should work while the malformed data from the other
// is being received
curve_client_data_t curve_client_data = {
fixed_server_public, fixed_client_public, fixed_client_secret};
void *client_mon;
void *client_good = create_and_connect_client (
my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
bounce (server, client_good);
close (client);
test_context_socket_close_zero_linger (client_good);
test_context_socket_close_zero_linger (client_mon);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_bind_curve_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_bind_curve_fuzzer_seed_corpus", &data,
&len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_curve_fuzzer);
return UNITY_END ();
}
#endif

96
vendor/ZMQ/tests/test_bind_fuzzer.cpp vendored Normal file
View File

@@ -0,0 +1,96 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include <string>
#include "testutil.hpp"
#include "testutil_unity.hpp"
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
// Test that zmq_bind can handle malformed strings
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
// This test might create socket files, so move to /tmp to avoid clobbering
// the working directory with random filenames
char *pwd = (char *) malloc (PATH_MAX + 1);
TEST_ASSERT_NOT_NULL (pwd);
TEST_ASSERT_NOT_NULL (getcwd (pwd, PATH_MAX + 1));
TEST_ASSERT_SUCCESS_ERRNO (chdir ("/tmp"));
setup_test_context ();
std::string my_endpoint (reinterpret_cast<const char *> (data), size);
void *socket = test_context_socket (ZMQ_PUB);
zmq_bind (socket, my_endpoint.c_str ());
test_context_socket_close_zero_linger (socket);
teardown_test_context ();
TEST_ASSERT_SUCCESS_ERRNO (chdir (pwd));
free (pwd);
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_bind_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_bind_fuzzer_seed_corpus", &data, &len,
&num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP engine handles invalid handshake when binding
// https://rfc.zeromq.org/spec/37/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
void *server = test_context_socket (ZMQ_PUB);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
fd_t client = connect_socket (my_endpoint);
void *client_good = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client_good, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_good, my_endpoint));
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[64];
if (size >= 64) {
send (client, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (client, buf, 64, 0);
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
TEST_ASSERT_EQUAL_INT (6, zmq_send_const (server, "HELLO", 6, 0));
TEST_ASSERT_EQUAL_INT (6, zmq_recv (client_good, buf, 6, 0));
close (client);
test_context_socket_close_zero_linger (client_good);
test_context_socket_close_zero_linger (server);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_bind_null_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_bind_null_fuzzer_seed_corpus", &data,
&len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_null_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,56 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_x ()
{
void *sock = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (sock, "tcp://127.0.0.1:0;localhost:1234"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (sock, "tcp://localhost:5555;localhost:1235"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (sock, "tcp://lo:5555;localhost:1235"));
test_context_socket_close (sock);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_x);
return UNITY_END ();
}

View File

@@ -0,0 +1,132 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP engine handles invalid handshake when binding
// https://rfc.zeromq.org/spec/37/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
void *server = test_context_socket (ZMQ_STREAM);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
fd_t client = connect_socket (my_endpoint);
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[64];
if (size >= 64) {
send (client, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (client, buf, 64, MSG_DONTWAIT);
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
void *client_good = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_good, my_endpoint));
TEST_ASSERT_EQUAL_INT (6, zmq_send_const (client_good, "HELLO", 6, 0));
zmq_msg_t routing_id;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&routing_id));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, server, 0));
TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));
char const *peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
zmq_msg_close (&routing_id);
TEST_ASSERT_NOT_NULL (peer_address);
TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);
TEST_ASSERT_EQUAL_INT (
0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (server, buf, 64, 0)));
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
close (client);
test_context_socket_close_zero_linger (client_good);
test_context_socket_close_zero_linger (server);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_bind_stream_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_bind_stream_fuzzer_seed_corpus",
&data, &len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_stream_fuzzer);
return UNITY_END ();
}
#endif

125
vendor/ZMQ/tests/test_bind_ws_fuzzer.cpp vendored Normal file
View File

@@ -0,0 +1,125 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP WebSocket engine handles invalid handshake when connecting
// https://rfc.zeromq.org/spec/45/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
size_t my_endpoint_size = sizeof (my_endpoint);
void *server = test_context_socket (ZMQ_DEALER);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (server, "ws://127.0.0.1:*"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (server, ZMQ_LAST_ENDPOINT,
my_endpoint, &my_endpoint_size));
// Remove trailing /
my_endpoint[my_endpoint_size - 2] = '\0';
fd_t client = connect_socket (my_endpoint, AF_INET, IPPROTO_WS);
void *client_good = test_context_socket (ZMQ_DEALER);
my_endpoint[my_endpoint_size - 2] = '/';
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_good, my_endpoint));
// If there is not enough data for a full handshake, just send what we can
// Otherwise send websocket handshake first, as expected by the protocol
uint8_t buf[256];
if (size >= 192) {
send (client, (void *) data, 192, MSG_NOSIGNAL);
data += 192;
size -= 192;
}
recv (client, buf, 256, MSG_DONTWAIT);
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (client, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
recv (client, buf, 256, MSG_DONTWAIT);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, server, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
send_string_expect_success (client_good, "abc", 0);
recv_string_expect_success (server, "abc", 0);
close (client);
test_context_socket_close_zero_linger (client_good);
test_context_socket_close_zero_linger (server);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_bind_ws_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_bind_ws_fuzzer_seed_corpus", &data,
&len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_ws_fuzzer);
return UNITY_END ();
}
#endif

99
vendor/ZMQ/tests/test_capabilities.cpp vendored Normal file
View File

@@ -0,0 +1,99 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
}
void tearDown ()
{
}
void test_capabilities ()
{
#if defined(ZMQ_HAVE_IPC)
TEST_ASSERT_TRUE (zmq_has ("ipc"));
#else
TEST_ASSERT_TRUE (!zmq_has ("ipc"));
#endif
#if defined(ZMQ_HAVE_OPENPGM)
TEST_ASSERT_TRUE (zmq_has ("pgm"));
#else
TEST_ASSERT_TRUE (!zmq_has ("pgm"));
#endif
#if defined(ZMQ_HAVE_TIPC)
TEST_ASSERT_TRUE (zmq_has ("tipc"));
#else
TEST_ASSERT_TRUE (!zmq_has ("tipc"));
#endif
#if defined(ZMQ_HAVE_NORM)
TEST_ASSERT_TRUE (zmq_has ("norm"));
#else
TEST_ASSERT_TRUE (!zmq_has ("norm"));
#endif
#if defined(ZMQ_HAVE_CURVE)
TEST_ASSERT_TRUE (zmq_has ("curve"));
#else
TEST_ASSERT_TRUE (!zmq_has ("curve"));
#endif
#if defined(HAVE_LIBGSSAPI_KRB5)
TEST_ASSERT_TRUE (zmq_has ("gssapi"));
#else
TEST_ASSERT_TRUE (!zmq_has ("gssapi"));
#endif
#if defined(ZMQ_HAVE_VMCI)
TEST_ASSERT_TRUE (zmq_has ("vmci"));
#else
TEST_ASSERT_TRUE (!zmq_has ("vmci"));
#endif
#if defined(ZMQ_BUILD_DRAFT_API)
TEST_ASSERT_TRUE (zmq_has ("draft"));
#else
TEST_ASSERT_TRUE (!zmq_has ("draft"));
#endif
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_capabilities);
return UNITY_END ();
}

81
vendor/ZMQ/tests/test_channel.cpp vendored Normal file
View File

@@ -0,0 +1,81 @@
/*
Copyright (c) 2007-2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void *sb;
void *sc;
void setUp ()
{
setup_test_context ();
sb = test_context_socket (ZMQ_CHANNEL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
sc = test_context_socket (ZMQ_CHANNEL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
}
void tearDown ()
{
test_context_socket_close (sc);
test_context_socket_close (sb);
teardown_test_context ();
}
void test_roundtrip ()
{
send_string_expect_success (sb, "HELLO", 0);
recv_string_expect_success (sc, "HELLO", 0);
send_string_expect_success (sc, "WORLD", 0);
recv_string_expect_success (sb, "WORLD", 0);
}
void test_sndmore_fails ()
{
int rc = zmq_send (sc, "X", 1, ZMQ_SNDMORE);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EINVAL, errno);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
RUN_TEST (test_sndmore_fails);
return UNITY_END ();
}

135
vendor/ZMQ/tests/test_client_server.cpp vendored Normal file
View File

@@ -0,0 +1,135 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void create_inproc_client_server_pair (void **server_, void **client_)
{
*server_ = test_context_socket (ZMQ_SERVER);
*client_ = test_context_socket (ZMQ_CLIENT);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (*server_, "inproc://test-client-server"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (*client_, "inproc://test-client-server"));
}
void send_sndmore_expect_failure (void *socket_)
{
int rc = zmq_send (socket_, "X", 1, ZMQ_SNDMORE);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EINVAL, errno);
}
void test_client_sndmore_fails ()
{
void *server, *client;
create_inproc_client_server_pair (&server, &client);
send_sndmore_expect_failure (client);
test_context_socket_close (server);
test_context_socket_close (client);
}
void test_server_sndmore_fails ()
{
void *server, *client;
create_inproc_client_server_pair (&server, &client);
send_sndmore_expect_failure (server);
test_context_socket_close (server);
test_context_socket_close (client);
}
void test_routing_id ()
{
void *server, *client;
create_inproc_client_server_pair (&server, &client);
send_string_expect_success (client, "X", 0);
uint32_t routing_id;
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
int rc = TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, server, 0));
TEST_ASSERT_EQUAL_INT (1, rc);
routing_id = zmq_msg_routing_id (&msg);
TEST_ASSERT_NOT_EQUAL (0, routing_id);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 1));
char *data = static_cast<char *> (zmq_msg_data (&msg));
data[0] = 2;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_set_routing_id (&msg, routing_id));
int rc = zmq_msg_send (&msg, server, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
}
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
int rc = zmq_msg_recv (&msg, client, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
routing_id = zmq_msg_routing_id (&msg);
TEST_ASSERT_EQUAL_UINT32 (0, routing_id);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
test_context_socket_close (server);
test_context_socket_close (client);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_client_sndmore_fails);
RUN_TEST (test_server_sndmore_fails);
RUN_TEST (test_routing_id);
return UNITY_END ();
}

76
vendor/ZMQ/tests/test_conflate.cpp vendored Normal file
View File

@@ -0,0 +1,76 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_conflate ()
{
char my_endpoint[MAX_SOCKET_STRING];
int rc;
void *s_in = test_context_socket (ZMQ_PULL);
int conflate = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (s_in, ZMQ_CONFLATE, &conflate, sizeof (conflate)));
bind_loopback_ipv4 (s_in, my_endpoint, sizeof my_endpoint);
void *s_out = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (s_out, my_endpoint));
int message_count = 20;
for (int j = 0; j < message_count; ++j) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_send (s_out, (void *) &j, sizeof (int), 0));
}
msleep (SETTLE_TIME);
int payload_recved = 0;
rc = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (s_in, (void *) &payload_recved, sizeof (int), 0));
TEST_ASSERT_GREATER_THAN_INT (0, rc);
TEST_ASSERT_EQUAL_INT (message_count - 1, payload_recved);
test_context_socket_close (s_in);
test_context_socket_close (s_out);
}
int main (int, char *[])
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_conflate);
return UNITY_END ();
}

View File

@@ -0,0 +1,139 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_security.hpp"
// Test that the ZMTP engine handles invalid handshake when connecting
// https://rfc.zeromq.org/spec/37/
// https://rfc.zeromq.org/spec/26/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
const char *fixed_client_public =
"{{k*81)yMWEF{/BxdMd[5RL^qRFxBgoL<8m.D^KD";
const char *fixed_client_secret =
"N?Gmik8R[2ACw{b7*[-$S6[4}aO#?DB?#=<OQPc7";
const char *fixed_server_public =
"3.9-xXwy{g*w72TP*3iB9IJJRxlBH<ufTAvPd2>C";
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
curve_client_data_t curve_client_data = {
fixed_server_public, fixed_client_public, fixed_client_secret};
void *client_mon;
void *client = create_and_connect_client (
my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
fd_t server_accept =
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[512];
if (size >= 64) {
send (server_accept, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (server_accept, buf, 64, 0);
// Then expect HELLO and send WELCOME if there's enough data
if (size >= 170) {
recv (server_accept, buf, 202, 0);
send (server_accept, (void *) data, 170, MSG_NOSIGNAL);
data += 170;
size -= 170;
}
// Then expect INITIATE and send READY if there's enough data
if (size >= 72) {
recv (server_accept, buf, 512, 0);
send (server_accept, (void *) data, 72, MSG_NOSIGNAL);
data += 72;
size -= 72;
}
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
recv (server_accept, buf, 512, MSG_DONTWAIT);
msleep (250);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, client, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
close (server_accept);
close (server);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (client_mon);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_connect_curve_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_connect_curve_fuzzer_seed_corpus",
&data, &len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_curve_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,246 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include "testutil_security.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_send_one_connected_one_unconnected ()
{
int val;
// TEST 1.
// First we're going to attempt to send messages to two
// pipes, one connected, the other not. We should see
// the PUSH load balancing to both pipes, and hence half
// of the messages getting queued, as connect() creates a
// pipe immediately.
void *to = test_context_socket (ZMQ_PULL);
int timeout = 5000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &timeout, sizeof (timeout)));
// Bind the one valid receiver
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof (val)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (to, "tipc://{6555,0,0}"));
// Create a socket pushing to two endpoints - only 1 message should arrive.
void *from = test_context_socket (ZMQ_PUSH);
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &timeout, sizeof (timeout)));
// This pipe will not connect
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{5556,0}@0.0.0"));
// This pipe will
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{6555,0}@0.0.0"));
// We send 10 messages, 5 should just get stuck in the queue
// for the not-yet-connected pipe
const int send_count = 10;
for (int i = 0; i < send_count; ++i) {
send_string_expect_success (from, "Hello", 0);
}
// We now consume from the connected pipe
// - we should see just 5
timeout = SETTLE_TIME;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
int seen = 0;
while (true) {
char buffer[16];
int rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
if (rc == -1) {
TEST_ASSERT_EQUAL_INT (EAGAIN, zmq_errno ());
break; // Break when we didn't get a message
}
seen++;
}
TEST_ASSERT_EQUAL_INT (send_count / 2, seen);
test_context_socket_close (from);
test_context_socket_close (to);
}
void test_send_one_connected_one_unconnected_with_delay ()
{
int val;
// TEST 2
// This time we will do the same thing, connect two pipes,
// one of which will succeed in connecting to a bound
// receiver, the other of which will fail. However, we will
// also set the delay attach on connect flag, which should
// cause the pipe attachment to be delayed until the connection
// succeeds.
// Bind the valid socket
void *to = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (to, "tipc://{5560,0,0}"));
int timeout = 5000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &timeout, sizeof (timeout)));
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof (val)));
// Create a socket pushing to two endpoints - all messages should arrive.
void *from = test_context_socket (ZMQ_PUSH);
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &timeout, sizeof (timeout)));
// Set the key flag
val = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_DELAY_ATTACH_ON_CONNECT, &val, sizeof (val)));
// Connect to the invalid socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{5561,0}@0.0.0"));
// Connect to the valid socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{5560,0}@0.0.0"));
// Send 10 messages, all should be routed to the connected pipe
const int send_count = 10;
for (int i = 0; i < send_count; ++i) {
send_string_expect_success (from, "Hello", 0);
}
timeout = SETTLE_TIME;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
int seen = 0;
while (true) {
char buffer[16];
int rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
if (rc == -1) {
TEST_ASSERT_EQUAL_INT (EAGAIN, zmq_errno ());
break; // Break when we didn't get a message
}
seen++;
}
TEST_ASSERT_EQUAL_INT (send_count, seen);
test_context_socket_close (from);
test_context_socket_close (to);
}
void test_send_disconnected_with_delay ()
{
// TEST 3
// This time we want to validate that the same blocking behaviour
// occurs with an existing connection that is broken. We will send
// messages to a connected pipe, disconnect and verify the messages
// block. Then we reconnect and verify messages flow again.
void *backend = test_context_socket (ZMQ_DEALER);
void *frontend = test_context_socket (ZMQ_DEALER);
void *monitor = test_context_socket (ZMQ_PAIR);
int rc;
int zero = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (frontend, "inproc://monitor",
ZMQ_EVENT_DISCONNECTED));
int timeout = 5000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &timeout, sizeof (timeout)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_LINGER, &timeout, sizeof (timeout)));
// Frontend connects to backend using DELAY_ATTACH_ON_CONNECT
int on = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_DELAY_ATTACH_ON_CONNECT, &on, sizeof (on)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (backend, "tipc://{5560,0,0}"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (monitor, "inproc://monitor"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (frontend, "tipc://{5560,0}@0.0.0"));
// Ping backend to frontend so we know when the connection is up
send_string_expect_success (backend, "Hello", 0);
recv_string_expect_success (frontend, "Hello", 0);
// Send message from frontend to backend
send_string_expect_success (frontend, "Hello", ZMQ_DONTWAIT);
test_context_socket_close (backend);
// Wait for disconnect to happen
expect_monitor_event (monitor, ZMQ_EVENT_DISCONNECTED);
// Send a message, might succeed depending on scheduling of the I/O thread
do {
rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
TEST_ASSERT_TRUE (rc == 5 || (rc == -1 && zmq_errno () == EAGAIN));
} while (rc == 5);
// Recreate backend socket
backend = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (backend, "tipc://{5560,0,0}"));
// Ping backend to frontend so we know when the connection is up
send_string_expect_success (backend, "Hello", 0);
recv_string_expect_success (frontend, "Hello", 0);
// After the reconnect, should succeed
send_string_expect_success (frontend, "Hello", ZMQ_DONTWAIT);
test_context_socket_close (monitor);
test_context_socket_close (backend);
test_context_socket_close (frontend);
}
int main (void)
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_send_one_connected_one_unconnected);
RUN_TEST (test_send_one_connected_one_unconnected_with_delay);
RUN_TEST (test_send_disconnected_with_delay);
return UNITY_END ();
}

View File

@@ -0,0 +1,83 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include <string>
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that zmq_connect can handle malformed strings
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
std::string my_endpoint (reinterpret_cast<const char *> (data), size);
void *socket = test_context_socket (ZMQ_PUB);
zmq_connect (socket, my_endpoint.c_str ());
test_context_socket_close_zero_linger (socket);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_connect_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_connect_fuzzer_seed_corpus", &data,
&len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,118 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP engine handles invalid handshake when connecting
// https://rfc.zeromq.org/spec/37/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
void *client = test_context_socket (ZMQ_SUB);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
fd_t server_accept =
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[64];
if (size >= 64) {
send (server_accept, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (server_accept, buf, 64, 0);
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, client, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
close (server_accept);
close (server);
test_context_socket_close_zero_linger (client);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_connect_null_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_connect_null_fuzzer_seed_corpus",
&data, &len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_null_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,104 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void *sock;
void setUp ()
{
setup_test_context ();
sock = test_context_socket (ZMQ_PUB);
}
void tearDown ()
{
test_context_socket_close (sock);
sock = NULL;
teardown_test_context ();
}
void test_hostname_ipv4 ()
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sock, "tcp://localhost:1234"));
}
void test_loopback_ipv6 ()
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sock, "tcp://[::1]:1234"));
}
void test_invalid_service_fails ()
{
int rc = zmq_connect (sock, "tcp://localhost:invalid");
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_hostname_with_spaces_fails ()
{
int rc = zmq_connect (sock, "tcp://in val id:1234");
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_no_hostname_fails ()
{
int rc = zmq_connect (sock, "tcp://");
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_x ()
{
int rc = zmq_connect (sock, "tcp://192.168.0.200:*");
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_invalid_proto_fails ()
{
int rc = zmq_connect (sock, "invalid://localhost:1234");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EPROTONOSUPPORT, errno);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_hostname_ipv4);
RUN_TEST (test_loopback_ipv6);
RUN_TEST (test_hostname_with_spaces_fails);
RUN_TEST (test_no_hostname_fails);
RUN_TEST (test_invalid_service_fails);
RUN_TEST (test_invalid_proto_fails);
return UNITY_END ();
}

252
vendor/ZMQ/tests/test_connect_rid.cpp vendored Normal file
View File

@@ -0,0 +1,252 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
const char *rconn1routing_id = "conn1";
const char *x_routing_id = "X";
const char *y_routing_id = "Y";
const char *z_routing_id = "Z";
void test_stream_2_stream ()
{
char buff[256];
const char msg[] = "hi 1";
const int disabled = 0;
const int zero = 0;
char my_endpoint[MAX_SOCKET_STRING];
// Set up listener STREAM.
void *rbind = test_context_socket (ZMQ_STREAM);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rbind, ZMQ_STREAM_NOTIFY, &disabled, sizeof (disabled)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rbind, ZMQ_LINGER, &zero, sizeof zero));
bind_loopback_ipv4 (rbind, my_endpoint, sizeof my_endpoint);
// Set up connection stream.
void *rconn1 = test_context_socket (ZMQ_STREAM);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rconn1, ZMQ_LINGER, &zero, sizeof zero));
// Do the connection.
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID,
rconn1routing_id,
strlen (rconn1routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, my_endpoint));
/* Uncomment to test assert on duplicate routing id.
// Test duplicate connect attempt.
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, rconn1routing_id, strlen(rconn1routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, bindip));
*/
// Send data to the bound stream.
send_string_expect_success (rconn1, rconn1routing_id, ZMQ_SNDMORE);
send_string_expect_success (rconn1, msg, 0);
// Accept data on the bound stream.
TEST_ASSERT_GREATER_THAN (
0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (rbind, buff, 256, 0)));
TEST_ASSERT_EQUAL (0, buff[0]); // an auto-generated routing id
recv_string_expect_success (rbind, msg, 0);
// Handle close of the socket.
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (rbind, my_endpoint));
test_context_socket_close (rbind);
test_context_socket_close (rconn1);
}
void test_router_2_router (bool named_)
{
char buff[256];
const char msg[] = "hi 1";
const int zero = 0;
char my_endpoint[MAX_SOCKET_STRING];
// Create bind socket.
void *rbind = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rbind, ZMQ_LINGER, &zero, sizeof (zero)));
bind_loopback_ipv4 (rbind, my_endpoint, sizeof my_endpoint);
// Create connection socket.
void *rconn1 = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rconn1, ZMQ_LINGER, &zero, sizeof (zero)));
// If we're in named mode, set some identities.
if (named_) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rbind, ZMQ_ROUTING_ID, x_routing_id, 1));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (rconn1, ZMQ_ROUTING_ID, y_routing_id, 1));
}
// Make call to connect using a connect_routing_id.
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID,
rconn1routing_id,
strlen (rconn1routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, my_endpoint));
/* Uncomment to test assert on duplicate routing id
// Test duplicate connect attempt.
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, rconn1routing_id, strlen (rconn1routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, bindip));
*/
// Send some data.
send_string_expect_success (rconn1, rconn1routing_id, ZMQ_SNDMORE);
send_string_expect_success (rconn1, msg, 0);
// Receive the name.
const int routing_id_len = zmq_recv (rbind, buff, 256, 0);
if (named_) {
TEST_ASSERT_EQUAL_INT (strlen (y_routing_id), routing_id_len);
TEST_ASSERT_EQUAL_STRING_LEN (y_routing_id, buff, routing_id_len);
} else {
TEST_ASSERT_TRUE (routing_id_len && 0 == buff[0]);
}
// Receive the data.
recv_string_expect_success (rbind, msg, 0);
// Send some data back.
const int ret = zmq_send (rbind, buff, routing_id_len, ZMQ_SNDMORE);
TEST_ASSERT_EQUAL_INT (routing_id_len, ret);
send_string_expect_success (rbind, "ok", 0);
// If bound socket identity naming a problem, we'll likely see something funky here.
recv_string_expect_success (rconn1, rconn1routing_id, 0);
recv_string_expect_success (rconn1, "ok", 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (rbind, my_endpoint));
test_context_socket_close (rbind);
test_context_socket_close (rconn1);
}
void test_router_2_router_while_receiving ()
{
char buff[256];
const char msg[] = "hi 1";
const int zero = 0;
char x_endpoint[MAX_SOCKET_STRING];
char z_endpoint[MAX_SOCKET_STRING];
// Create xbind socket.
void *xbind = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (xbind, ZMQ_LINGER, &zero, sizeof (zero)));
bind_loopback_ipv4 (xbind, x_endpoint, sizeof x_endpoint);
// Create zbind socket.
void *zbind = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (zbind, ZMQ_LINGER, &zero, sizeof (zero)));
bind_loopback_ipv4 (zbind, z_endpoint, sizeof z_endpoint);
// Create connection socket.
void *yconn = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (yconn, ZMQ_LINGER, &zero, sizeof (zero)));
// set identities for each socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
xbind, ZMQ_ROUTING_ID, x_routing_id, strlen (x_routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (yconn, ZMQ_ROUTING_ID, y_routing_id, 2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
zbind, ZMQ_ROUTING_ID, z_routing_id, strlen (z_routing_id)));
// Connect Y to X using a routing id
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
yconn, ZMQ_CONNECT_ROUTING_ID, x_routing_id, strlen (x_routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (yconn, x_endpoint));
// Send some data from Y to X.
send_string_expect_success (yconn, x_routing_id, ZMQ_SNDMORE);
send_string_expect_success (yconn, msg, 0);
// wait for the Y->X message to be received
msleep (SETTLE_TIME);
// Now X tries to connect to Z and send a message
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
xbind, ZMQ_CONNECT_ROUTING_ID, z_routing_id, strlen (z_routing_id)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (xbind, z_endpoint));
// Try to send some data from X to Z.
send_string_expect_success (xbind, z_routing_id, ZMQ_SNDMORE);
send_string_expect_success (xbind, msg, 0);
// wait for the X->Z message to be received (so that our non-blocking check will actually
// fail if the message is routed to Y)
msleep (SETTLE_TIME);
// nothing should have been received on the Y socket
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_recv (yconn, buff, 256, ZMQ_DONTWAIT));
// the message should have been received on the Z socket
recv_string_expect_success (zbind, x_routing_id, 0);
recv_string_expect_success (zbind, msg, 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (xbind, x_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (zbind, z_endpoint));
test_context_socket_close (yconn);
test_context_socket_close (xbind);
test_context_socket_close (zbind);
}
void test_router_2_router_unnamed ()
{
test_router_2_router (false);
}
void test_router_2_router_named ()
{
test_router_2_router (true);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_stream_2_stream);
RUN_TEST (test_router_2_router_unnamed);
RUN_TEST (test_router_2_router_named);
RUN_TEST (test_router_2_router_while_receiving);
return UNITY_END ();
}

View File

@@ -0,0 +1,117 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP engine handles invalid handshake when connecting
// https://rfc.zeromq.org/spec/37/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint);
void *client = test_context_socket (ZMQ_STREAM);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
fd_t server_accept =
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
// If there is not enough data for a full greeting, just send what we can
// Otherwise send greeting first, as expected by the protocol
uint8_t buf[64];
if (size >= 64) {
send (server_accept, (void *) data, 64, MSG_NOSIGNAL);
data += 64;
size -= 64;
}
recv (server_accept, buf, 64, MSG_DONTWAIT);
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, client, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
close (server_accept);
close (server);
test_context_socket_close_zero_linger (client);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_connect_null_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_connect_null_fuzzer_seed_corpus",
&data, &len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_null_fuzzer);
return UNITY_END ();
}
#endif

View File

@@ -0,0 +1,125 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
// Test that the ZMTP WebSocket engine handles invalid handshake when connecting
// https://rfc.zeromq.org/spec/45/
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
fd_t server = bind_socket_resolve_port ("127.0.0.1", "0", my_endpoint,
AF_INET, IPPROTO_WS);
void *client = test_context_socket (ZMQ_PULL);
// As per API by default there's no limit to the size of a message,
// but the sanitizer allocator will barf over a gig or so
int64_t max_msg_size = 64 * 1024 * 1024;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_MAXMSGSIZE, &max_msg_size, sizeof (int64_t)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
fd_t server_accept =
TEST_ASSERT_SUCCESS_RAW_ERRNO (accept (server, NULL, NULL));
// If there is not enough data for a full handshake, just send what we can
// Otherwise send websocket handshake first, as expected by the protocol
uint8_t buf[256];
recv (server_accept, buf, 256, 0);
if (size >= 166) {
send (server_accept, (void *) data, 166, MSG_NOSIGNAL);
data += 166;
size -= 166;
}
recv (server_accept, buf, 256, MSG_DONTWAIT);
// Then send the READY command
if (size >= 29) {
send (server_accept, (void *) data, 29, MSG_NOSIGNAL);
data += 29;
size -= 29;
}
msleep (250);
for (ssize_t sent = 0; size > 0 && (sent != -1 || errno == EINTR);
size -= sent > 0 ? sent : 0, data += sent > 0 ? sent : 0)
sent = send (server_accept, (const char *) data, size, MSG_NOSIGNAL);
msleep (250);
zmq_msg_t msg;
zmq_msg_init (&msg);
while (-1 != zmq_msg_recv (&msg, client, ZMQ_DONTWAIT)) {
zmq_msg_close (&msg);
zmq_msg_init (&msg);
}
close (server_accept);
close (server);
test_context_socket_close_zero_linger (client);
teardown_test_context ();
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_connect_ws_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_connect_ws_fuzzer_seed_corpus", &data,
&len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_ws_fuzzer);
return UNITY_END ();
}
#endif

255
vendor/ZMQ/tests/test_ctx_destroy.cpp vendored Normal file
View File

@@ -0,0 +1,255 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void setUp ()
{
}
void tearDown ()
{
}
static void receiver (void *socket_)
{
char buffer[16];
int rc = zmq_recv (socket_, &buffer, sizeof (buffer), 0);
// TODO which error is expected here? use TEST_ASSERT_FAILURE_ERRNO instead
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_ctx_destroy ()
{
// Set up our context and sockets
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (socket);
// Close the socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
// Destroy the context
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
}
void test_ctx_shutdown ()
{
// Set up our context and sockets
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (socket);
// Spawn a thread to receive on socket
void *receiver_thread = zmq_threadstart (&receiver, socket);
// Wait for thread to start up and block
msleep (SETTLE_TIME);
// Shutdown context, if we used destroy here we would deadlock.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_shutdown (ctx));
// Wait for thread to finish
zmq_threadclose (receiver_thread);
// Close the socket.
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
// Destroy the context, will now not hang as we have closed the socket.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
}
void test_ctx_shutdown_socket_opened_after ()
{
// Set up our context.
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
// Open a socket to start context, and close it immediately again.
void *socket = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL (socket);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
// Shutdown context.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_shutdown (ctx));
// Opening socket should now fail.
TEST_ASSERT_NULL (zmq_socket (ctx, ZMQ_PULL));
TEST_ASSERT_FAILURE_ERRNO (ETERM, -1);
// Destroy the context.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
}
void test_ctx_shutdown_only_socket_opened_after ()
{
// Set up our context.
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
// Shutdown context.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_shutdown (ctx));
// Opening socket should now fail.
TEST_ASSERT_NULL (zmq_socket (ctx, ZMQ_PULL));
TEST_ASSERT_FAILURE_ERRNO (ETERM, -1);
// Destroy the context.
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (ctx));
}
void test_zmq_ctx_term_null_fails ()
{
int rc = zmq_ctx_term (NULL);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EFAULT, errno);
}
void test_zmq_term_null_fails ()
{
int rc = zmq_term (NULL);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EFAULT, errno);
}
void test_zmq_ctx_shutdown_null_fails ()
{
int rc = zmq_ctx_shutdown (NULL);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EFAULT, errno);
}
#ifdef ZMQ_HAVE_POLLER
struct poller_test_data_t
{
int socket_type;
void *ctx;
void *counter;
};
void run_poller (void *data_)
{
const poller_test_data_t *const poller_test_data =
static_cast<const poller_test_data_t *> (data_);
void *socket =
zmq_socket (poller_test_data->ctx, poller_test_data->socket_type);
TEST_ASSERT_NOT_NULL (socket);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN));
zmq_atomic_counter_set (poller_test_data->counter, 1);
zmq_poller_event_t event;
TEST_ASSERT_FAILURE_ERRNO (ETERM, zmq_poller_wait (poller, &event, -1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
// Close the socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
}
#endif
void test_poller_exists_with_socket_on_zmq_ctx_term (const int socket_type_)
{
#ifdef ZMQ_HAVE_POLLER
struct poller_test_data_t poller_test_data;
poller_test_data.socket_type = socket_type_;
// Set up our context and sockets
poller_test_data.ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (poller_test_data.ctx);
poller_test_data.counter = zmq_atomic_counter_new ();
TEST_ASSERT_NOT_NULL (poller_test_data.counter);
void *thread = zmq_threadstart (run_poller, &poller_test_data);
TEST_ASSERT_NOT_NULL (thread);
while (zmq_atomic_counter_value (poller_test_data.counter) == 0) {
msleep (10);
}
// Destroy the context
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_destroy (poller_test_data.ctx));
zmq_threadclose (thread);
zmq_atomic_counter_destroy (&poller_test_data.counter);
#else
TEST_IGNORE_MESSAGE ("libzmq without zmq_poller_* support, ignoring test");
#endif
}
void test_poller_exists_with_socket_on_zmq_ctx_term_thread_safe_socket ()
{
#ifdef ZMQ_BUILD_DRAFT_API
test_poller_exists_with_socket_on_zmq_ctx_term (ZMQ_CLIENT);
#else
TEST_IGNORE_MESSAGE ("libzmq without DRAFT support, ignoring test");
#endif
}
void test_poller_exists_with_socket_on_zmq_ctx_term_non_thread_safe_socket ()
{
test_poller_exists_with_socket_on_zmq_ctx_term (ZMQ_DEALER);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_ctx_destroy);
RUN_TEST (test_ctx_shutdown);
RUN_TEST (test_ctx_shutdown_socket_opened_after);
RUN_TEST (test_ctx_shutdown_only_socket_opened_after);
RUN_TEST (test_zmq_ctx_term_null_fails);
RUN_TEST (test_zmq_term_null_fails);
RUN_TEST (test_zmq_ctx_shutdown_null_fails);
RUN_TEST (
test_poller_exists_with_socket_on_zmq_ctx_term_non_thread_safe_socket);
RUN_TEST (
test_poller_exists_with_socket_on_zmq_ctx_term_thread_safe_socket);
return UNITY_END ();
}

310
vendor/ZMQ/tests/test_ctx_options.cpp vendored Normal file
View File

@@ -0,0 +1,310 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <limits>
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
#define WAIT_FOR_BACKGROUND_THREAD_INSPECTION (0)
#ifdef ZMQ_HAVE_LINUX
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h> // for sleep()
#include <sched.h>
#define TEST_POLICY \
(SCHED_OTHER) // NOTE: SCHED_OTHER is the default Linux scheduler
bool is_allowed_to_raise_priority ()
{
// NOTE1: if setrlimit() fails with EPERM, this means that current user has not enough permissions.
// NOTE2: even for privileged users (e.g., root) getrlimit() would usually return 0 as nice limit; the only way to
// discover if the user is able to increase the nice value is to actually try to change the rlimit:
struct rlimit rlim;
rlim.rlim_cur = 40;
rlim.rlim_max = 40;
if (setrlimit (RLIMIT_NICE, &rlim) == 0) {
// rlim_cur == 40 means that this process is allowed to set a nice value of -20
if (WAIT_FOR_BACKGROUND_THREAD_INSPECTION)
printf ("This process has enough permissions to raise ZMQ "
"background thread priority!\n");
return true;
}
if (WAIT_FOR_BACKGROUND_THREAD_INSPECTION)
printf ("This process has NOT enough permissions to raise ZMQ "
"background thread priority.\n");
return false;
}
#else
#define TEST_POLICY (0)
bool is_allowed_to_raise_priority ()
{
return false;
}
#endif
void test_ctx_thread_opts ()
{
// verify that setting negative values (e.g., default values) fail:
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_ctx_set (get_test_context (), ZMQ_THREAD_SCHED_POLICY,
ZMQ_THREAD_SCHED_POLICY_DFLT));
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_ctx_set (get_test_context (),
ZMQ_THREAD_PRIORITY,
ZMQ_THREAD_PRIORITY_DFLT));
// test scheduling policy:
// set context options that alter the background thread CPU scheduling/affinity settings;
// as of ZMQ 4.2.3 this has an effect only on POSIX systems (nothing happens on Windows, but still it should return success):
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_THREAD_SCHED_POLICY, TEST_POLICY));
TEST_ASSERT_EQUAL_INT (
TEST_POLICY, zmq_ctx_get (get_test_context (), ZMQ_THREAD_SCHED_POLICY));
// test priority:
// in theory SCHED_OTHER supports only the static priority 0 but quoting the docs
// http://man7.org/linux/man-pages/man7/sched.7.html
// "The thread to run is chosen from the static priority 0 list based on
// a dynamic priority that is determined only inside this list. The
// dynamic priority is based on the nice value [...]
// The nice value can be modified using nice(2), setpriority(2), or sched_setattr(2)."
// ZMQ will internally use nice(2) to set the nice value when using SCHED_OTHER.
// However changing the nice value of a process requires appropriate permissions...
// check that the current effective user is able to do that:
if (is_allowed_to_raise_priority ()) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_set (
get_test_context (), ZMQ_THREAD_PRIORITY,
1 /* any positive value different than the default will be ok */));
}
// test affinity:
// this should result in background threads being placed only on the
// first CPU available on this system; try experimenting with other values
// (e.g., 5 to use CPU index 5) and use "top -H" or "taskset -pc" to see the result
int cpus_add[] = {0, 1};
for (unsigned int idx = 0; idx < sizeof (cpus_add) / sizeof (cpus_add[0]);
idx++) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_set (
get_test_context (), ZMQ_THREAD_AFFINITY_CPU_ADD, cpus_add[idx]));
}
// you can also remove CPUs from list of affinities:
int cpus_remove[] = {1};
for (unsigned int idx = 0;
idx < sizeof (cpus_remove) / sizeof (cpus_remove[0]); idx++) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_set (get_test_context (),
ZMQ_THREAD_AFFINITY_CPU_REMOVE,
cpus_remove[idx]));
}
// test INTEGER thread name prefix:
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_THREAD_NAME_PREFIX, 1234));
TEST_ASSERT_EQUAL_INT (
1234, zmq_ctx_get (get_test_context (), ZMQ_THREAD_NAME_PREFIX));
#ifdef ZMQ_BUILD_DRAFT_API
// test STRING thread name prefix:
const char prefix[] = "MyPrefix9012345"; // max len is 16 chars
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set_ext (get_test_context (), ZMQ_THREAD_NAME_PREFIX, prefix,
sizeof (prefix) / sizeof (char)));
char buf[16];
size_t buflen = sizeof (buf) / sizeof (char);
zmq_ctx_get_ext (get_test_context (), ZMQ_THREAD_NAME_PREFIX, buf, &buflen);
TEST_ASSERT_EQUAL_STRING (prefix, buf);
#endif
}
void test_ctx_zero_copy ()
{
#ifdef ZMQ_ZERO_COPY_RECV
int zero_copy;
// Default value is 1.
zero_copy = zmq_ctx_get (get_test_context (), ZMQ_ZERO_COPY_RECV);
TEST_ASSERT_EQUAL_INT (1, zero_copy);
// Test we can set it to 0.
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_ZERO_COPY_RECV, 0));
zero_copy = zmq_ctx_get (get_test_context (), ZMQ_ZERO_COPY_RECV);
TEST_ASSERT_EQUAL_INT (0, zero_copy);
// Create a TCP socket pair using the context and test that messages can be
// received. Note that inproc sockets cannot be used for this test.
void *pull = zmq_socket (get_test_context (), ZMQ_PULL);
char endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (pull, endpoint, sizeof endpoint);
void *push = zmq_socket (get_test_context (), ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (push, endpoint));
const char *small_str = "abcd";
const char *large_str =
"01234567890123456789012345678901234567890123456789";
send_string_expect_success (push, small_str, 0);
send_string_expect_success (push, large_str, 0);
recv_string_expect_success (pull, small_str, 0);
recv_string_expect_success (pull, large_str, 0);
// Clean up.
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (push));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (pull));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_ZERO_COPY_RECV, 1));
TEST_ASSERT_EQUAL_INT (
1, zmq_ctx_get (get_test_context (), ZMQ_ZERO_COPY_RECV));
#endif
}
void test_ctx_option_max_sockets ()
{
TEST_ASSERT_EQUAL_INT (ZMQ_MAX_SOCKETS_DFLT,
zmq_ctx_get (get_test_context (), ZMQ_MAX_SOCKETS));
}
void test_ctx_option_socket_limit ()
{
#if defined(ZMQ_USE_SELECT)
TEST_ASSERT_EQUAL_INT (FD_SETSIZE - 1, zmq_ctx_get (ctx, ZMQ_SOCKET_LIMIT));
#elif defined(ZMQ_USE_POLL) || defined(ZMQ_USE_EPOLL) \
|| defined(ZMQ_USE_DEVPOLL) || defined(ZMQ_USE_KQUEUE)
TEST_ASSERT_EQUAL_INT (65535, zmq_ctx_get (ctx, ZMQ_SOCKET_LIMIT));
#endif
}
void test_ctx_option_io_threads ()
{
TEST_ASSERT_EQUAL_INT (ZMQ_IO_THREADS_DFLT,
zmq_ctx_get (get_test_context (), ZMQ_IO_THREADS));
}
void test_ctx_option_ipv6 ()
{
TEST_ASSERT_EQUAL_INT (0, zmq_ctx_get (get_test_context (), ZMQ_IPV6));
}
void test_ctx_option_msg_t_size ()
{
#if defined(ZMQ_MSG_T_SIZE)
TEST_ASSERT_EQUAL_INT (sizeof (zmq_msg_t),
zmq_ctx_get (get_test_context (), ZMQ_MSG_T_SIZE));
#endif
}
void test_ctx_option_ipv6_set ()
{
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_IPV6, true));
TEST_ASSERT_EQUAL_INT (1, zmq_ctx_get (get_test_context (), ZMQ_IPV6));
}
void test_ctx_option_blocky ()
{
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_IPV6, true));
void *router = test_context_socket (ZMQ_ROUTER);
int value;
size_t optsize = sizeof (int);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_IPV6, &value, &optsize));
TEST_ASSERT_EQUAL_INT (1, value);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_LINGER, &value, &optsize));
TEST_ASSERT_EQUAL_INT (-1, value);
test_context_socket_close (router);
#if WAIT_FOR_BACKGROUND_THREAD_INSPECTION
// this is useful when you want to use an external tool (like top or taskset) to view
// properties of the background threads
printf ("Sleeping for 100sec. You can now use 'top -H -p $(pgrep -f "
"test_ctx_options)' and 'taskset -pc <ZMQ background thread PID>' "
"to view ZMQ background thread properties.\n");
sleep (100);
#endif
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_BLOCKY, false));
TEST_ASSERT_EQUAL_INT (0, TEST_ASSERT_SUCCESS_ERRNO ((zmq_ctx_get (
get_test_context (), ZMQ_BLOCKY))));
router = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_LINGER, &value, &optsize));
TEST_ASSERT_EQUAL_INT (0, value);
test_context_socket_close (router);
}
void test_ctx_option_invalid ()
{
TEST_ASSERT_EQUAL_INT (-1, zmq_ctx_set (get_test_context (), -1, 0));
TEST_ASSERT_EQUAL_INT (EINVAL, errno);
TEST_ASSERT_EQUAL_INT (-1, zmq_ctx_get (get_test_context (), -1));
TEST_ASSERT_EQUAL_INT (EINVAL, errno);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_ctx_option_max_sockets);
RUN_TEST (test_ctx_option_socket_limit);
RUN_TEST (test_ctx_option_io_threads);
RUN_TEST (test_ctx_option_ipv6);
RUN_TEST (test_ctx_option_msg_t_size);
RUN_TEST (test_ctx_option_ipv6_set);
RUN_TEST (test_ctx_thread_opts);
RUN_TEST (test_ctx_zero_copy);
RUN_TEST (test_ctx_option_blocky);
RUN_TEST (test_ctx_option_invalid);
return UNITY_END ();
}

107
vendor/ZMQ/tests/test_dgram.cpp vendored Normal file
View File

@@ -0,0 +1,107 @@
/*
Copyright (c) 2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void str_send_to (void *s_, const char *content_, const char *address_)
{
send_string_expect_success (s_, address_, ZMQ_SNDMORE);
send_string_expect_success (s_, content_, 0);
}
void str_recv_from (void *s_, char **ptr_content_, char **ptr_address_)
{
*ptr_address_ = s_recv (s_);
TEST_ASSERT_NOT_NULL (ptr_address_);
*ptr_content_ = s_recv (s_);
TEST_ASSERT_NOT_NULL (ptr_content_);
}
static const char test_question[] = "Is someone there ?";
static const char test_answer[] = "Yes, there is !";
void test_connect_fails ()
{
void *socket = test_context_socket (ZMQ_DGRAM);
// Connecting dgram should fail
TEST_ASSERT_FAILURE_ERRNO (ENOCOMPATPROTO,
zmq_connect (socket, ENDPOINT_4));
test_context_socket_close (socket);
}
void test_roundtrip ()
{
char *message_string;
char *address;
void *sender = test_context_socket (ZMQ_DGRAM);
void *listener = test_context_socket (ZMQ_DGRAM);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (listener, ENDPOINT_4));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sender, ENDPOINT_5));
str_send_to (sender, test_question, strrchr (ENDPOINT_4, '/') + 1);
str_recv_from (listener, &message_string, &address);
TEST_ASSERT_EQUAL_STRING (test_question, message_string);
TEST_ASSERT_EQUAL_STRING (strrchr (ENDPOINT_5, '/') + 1, address);
free (message_string);
str_send_to (listener, test_answer, address);
free (address);
str_recv_from (sender, &message_string, &address);
TEST_ASSERT_EQUAL_STRING (test_answer, message_string);
TEST_ASSERT_EQUAL_STRING (strrchr (ENDPOINT_4, '/') + 1, address);
free (message_string);
free (address);
test_context_socket_close (sender);
test_context_socket_close (listener);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_connect_fails);
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

72
vendor/ZMQ/tests/test_diffserv.cpp vendored Normal file
View File

@@ -0,0 +1,72 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_diffserv ()
{
int tos = 0x28;
int o_tos;
size_t tos_size = sizeof (tos);
char my_endpoint[MAX_SOCKET_STRING];
void *sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sb, ZMQ_TOS, &tos, tos_size));
bind_loopback_ipv4 (sb, my_endpoint, sizeof (my_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (sb, ZMQ_TOS, &o_tos, &tos_size));
TEST_ASSERT_EQUAL (tos, o_tos);
void *sc = test_context_socket (ZMQ_PAIR);
tos = 0x58;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sc, ZMQ_TOS, &tos, tos_size));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (sc, ZMQ_TOS, &o_tos, &tos_size));
TEST_ASSERT_EQUAL (tos, o_tos);
// Wireshark can be used to verify that the server socket is
// using DSCP 0x28 in packets to the client while the client
// is using 0x58 in packets to the server.
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_diffserv);
return UNITY_END ();
}

View File

@@ -0,0 +1,137 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
/// Initialize a zeromq message with a given null-terminated string
#define ZMQ_PREPARE_STRING(msg, data, size) \
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg)); \
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, size + 1)); \
memcpy (zmq_msg_data (&msg), data, size + 1);
static int publicationsReceived = 0;
static bool isSubscribed = false;
void test_disconnect_inproc ()
{
void *pub_socket = test_context_socket (ZMQ_XPUB);
void *sub_socket = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, "foo", 3));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (pub_socket, "inproc://someInProcDescriptor"));
int more;
size_t more_size = sizeof (more);
for (int iteration = 0;; ++iteration) {
zmq_pollitem_t items[] = {
{sub_socket, 0, ZMQ_POLLIN, 0}, // read publications
{pub_socket, 0, ZMQ_POLLIN, 0}, // read subscriptions
};
int rc = zmq_poll (items, 2, 100);
if (items[1].revents & ZMQ_POLLIN) {
for (more = 1; more;) {
zmq_msg_t msg;
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, pub_socket, 0));
const char *const buffer =
static_cast<const char *> (zmq_msg_data (&msg));
if (buffer[0] == 0) {
TEST_ASSERT_TRUE (isSubscribed);
isSubscribed = false;
} else {
TEST_ASSERT_FALSE (isSubscribed);
isSubscribed = true;
}
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (pub_socket, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
}
if (items[0].revents & ZMQ_POLLIN) {
more = 1;
for (more = 1; more;) {
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sub_socket, 0));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (sub_socket, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
publicationsReceived++;
}
if (iteration == 1) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (sub_socket, "inproc://someInProcDescriptor"));
msleep (SETTLE_TIME);
}
if (iteration == 4) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_disconnect (sub_socket, "inproc://someInProcDescriptor"));
}
if (iteration > 4 && rc == 0)
break;
zmq_msg_t channel_envlp;
ZMQ_PREPARE_STRING (channel_envlp, "foo", 3);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&channel_envlp, pub_socket, ZMQ_SNDMORE));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&channel_envlp));
zmq_msg_t message;
ZMQ_PREPARE_STRING (message, "this is foo!", 12);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&message, pub_socket, 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&message));
}
TEST_ASSERT_EQUAL_INT (3, publicationsReceived);
TEST_ASSERT_FALSE (isSubscribed);
test_context_socket_close (pub_socket);
test_context_socket_close (sub_socket);
}
int main (int, char **)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_disconnect_inproc);
return UNITY_END ();
}

118
vendor/ZMQ/tests/test_disconnect_msg.cpp vendored Normal file
View File

@@ -0,0 +1,118 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test (const char *address)
{
// Create a server
void *server = test_context_socket (ZMQ_SERVER);
// set server socket options
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_DISCONNECT_MSG, "D", 1));
// bind server
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (server, address));
// Create a client
void *client = test_context_socket (ZMQ_CLIENT);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_HELLO_MSG, "H", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, address));
// Receive the hello message from client
recv_string_expect_success (server, "H", 0);
// Kill the client
test_context_socket_close (client);
// Receive the disconnect message
recv_string_expect_success (server, "D", 0);
// Clean up.
test_context_socket_close (server);
}
void test_tcp ()
{
test ("tcp://127.0.0.1:5569");
}
void test_inproc ()
{
test ("inproc://disconnect-msg");
}
void test_inproc_disconnect ()
{
const char *address = "inproc://disconnect-msg";
// Create a server
void *server = test_context_socket (ZMQ_SERVER);
// set server socket options
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_DISCONNECT_MSG, "D", 1));
// bind server
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (server, address));
// Create a client
void *client = test_context_socket (ZMQ_CLIENT);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_HELLO_MSG, "H", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, address));
// Receive the hello message from client
recv_string_expect_success (server, "H", 0);
// disconnect the client
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (client, address));
// Receive the disconnect message
recv_string_expect_success (server, "D", 0);
// Clean up.
test_context_socket_close (client);
test_context_socket_close (server);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_tcp);
RUN_TEST (test_inproc);
RUN_TEST (test_inproc_disconnect);
return UNITY_END ();
}

220
vendor/ZMQ/tests/test_filter_ipc.cpp vendored Normal file
View File

@@ -0,0 +1,220 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unistd.h>
#include <grp.h>
SETUP_TEARDOWN_TESTCONTEXT
static void bounce_fail (void *server_, void *client_)
{
const char *content = "12345678ABCDEFGH12345678abcdefgh";
char buffer[32];
// Send message from client to server
send_string_expect_success (client_, content, ZMQ_SNDMORE);
send_string_expect_success (client_, content, 0);
// Receive message at server side (should not succeed)
int timeout = SETTLE_TIME;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (server_, buffer, 32, 0));
// Send message from server to client to test other direction
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_SNDTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_send (server_, content, 32, ZMQ_SNDMORE));
}
template <class T>
static void
run_test (int opt_, T optval_, int expected_error_, int bounce_test_)
{
void *sb = test_context_socket (ZMQ_DEALER);
if (opt_) {
const int rc = zmq_setsockopt (sb, opt_, &optval_, sizeof (optval_));
if (expected_error_) {
TEST_ASSERT_FAILURE_ERRNO (expected_error_, rc);
} else {
TEST_ASSERT_SUCCESS_ERRNO (rc);
}
}
void *sc = test_context_socket (ZMQ_DEALER);
// If a test fails, don't hang for too long
int timeout = 2500;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sb, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sb, ZMQ_SNDTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_SNDTIMEO, &timeout, sizeof (int)));
int interval = -1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_RECONNECT_IVL, &interval, sizeof (int)));
if (bounce_test_) {
const char *endpoint = "ipc://test_filter_ipc.sock";
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint));
if (bounce_test_ > 0)
bounce (sb, sc);
else
bounce_fail (sb, sc);
}
// TODO only use zero linger when bounce_test_ < 0?
test_context_socket_close_zero_linger (sc);
test_context_socket_close_zero_linger (sb);
}
#if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
gid_t group, supgroup, notgroup;
void init_groups ()
{
// Get the group and supplemental groups of the process owner
gid_t groups[100];
int ngroups = getgroups (100, groups);
TEST_ASSERT_NOT_EQUAL (-1, ngroups);
group = getgid ();
supgroup = group;
notgroup = group + 1;
for (int i = 0; i < ngroups; i++) {
if (supgroup == group && group != groups[i]) {
if (getgrgid (groups[i]))
supgroup = groups[i];
}
if (notgroup <= groups[i])
notgroup = groups[i] + 1;
}
}
#endif
void test_no_filters ()
{
run_test<int> (0, 0, 0, 1);
}
#if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
void test_filter_with_process_owner_uid ()
{
run_test<uid_t> (ZMQ_IPC_FILTER_UID, getuid (), 0, 1);
}
void test_filter_with_possibly_nonexistent_uid ()
{
run_test<uid_t> (ZMQ_IPC_FILTER_UID, getuid () + 1, 0, -1);
}
void test_filter_with_process_owner_gid ()
{
run_test<gid_t> (ZMQ_IPC_FILTER_GID, group, 0, 1);
}
void test_filter_with_supplemental_process_owner_gid ()
{
run_test<gid_t> (ZMQ_IPC_FILTER_GID, supgroup, 0, 1);
}
void test_filter_with_possibly_nonexistent_gid ()
{
run_test<gid_t> (ZMQ_IPC_FILTER_GID, notgroup, 0, -1);
}
#if defined ZMQ_HAVE_SO_PEERCRED
void test_filter_with_current_process_pid ()
{
run_test<pid_t> (ZMQ_IPC_FILTER_PID, getpid (), 0, 1);
}
void test_filter_with_possibly_nonexistent_pid ()
{
run_test<pid_t> (ZMQ_IPC_FILTER_PID, getpid () + 1, 0, -1);
}
#else
void test_filter_with_pid_fails ()
{
// Setup of PID filter should fail with operation not supported error
// TODO EINVAL is not ENOTSUP (!)
run_test<pid_t> (ZMQ_IPC_FILTER_PID, getpid (), EINVAL, 0);
}
#endif
#else
void test_filter_with_zero_uid_fails ()
{
run_test<uid_t> (ZMQ_IPC_FILTER_UID, 0, EINVAL, 0);
}
void test_filter_with_zero_gid_fails ()
{
run_test<gid_t> (ZMQ_IPC_FILTER_GID, 0, EINVAL, 0);
}
void test_filter_with_zero_pid_fails ()
{
run_test<pid_t> (ZMQ_IPC_FILTER_PID, 0, EINVAL, 0);
}
#endif // defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
int main (void)
{
#if !defined(ZMQ_HAVE_WINDOWS)
setup_test_environment ();
#if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
init_groups ();
#endif
UNITY_BEGIN ();
RUN_TEST (test_no_filters);
#if defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
RUN_TEST (test_filter_with_process_owner_uid);
RUN_TEST (test_filter_with_possibly_nonexistent_uid);
RUN_TEST (test_filter_with_process_owner_gid);
RUN_TEST (test_filter_with_supplemental_process_owner_gid);
RUN_TEST (test_filter_with_possibly_nonexistent_gid);
#if defined ZMQ_HAVE_SO_PEERCRED
RUN_TEST (test_filter_with_current_process_pid);
RUN_TEST (test_filter_with_possibly_nonexistent_pid);
#else
RUN_TEST (test_filter_with_pid_fails);
#endif
#else
RUN_TEST (test_filter_with_zero_uid_fails);
RUN_TEST (test_filter_with_zero_gid_fails);
RUN_TEST (test_filter_with_zero_pid_fails);
#endif // defined ZMQ_HAVE_SO_PEERCRED || defined ZMQ_HAVE_LOCAL_PEERCRED
return UNITY_END ();
#else
return 0;
#endif
}

103
vendor/ZMQ/tests/test_fork.cpp vendored Normal file
View File

@@ -0,0 +1,103 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
SETUP_TEARDOWN_TESTCONTEXT
char connect_address[MAX_SOCKET_STRING];
#define NUM_MESSAGES 5
void test_fork ()
{
#if !defined(ZMQ_HAVE_WINDOWS)
// Create and bind pull socket to receive messages
void *pull = test_context_socket (ZMQ_PULL);
bind_loopback_ipv4 (pull, connect_address, sizeof connect_address);
int pid = fork ();
if (pid == 0) {
// use regular assertions in the child process
// Child process
// Immediately close parent sockets and context
zmq_close (pull);
zmq_ctx_term (get_test_context ());
// Create new context, socket, connect and send some messages
void *child_ctx = zmq_ctx_new ();
assert (child_ctx);
void *push = zmq_socket (child_ctx, ZMQ_PUSH);
assert (push);
int rc = zmq_connect (push, connect_address);
assert (rc == 0);
int count;
for (count = 0; count < NUM_MESSAGES; count++)
zmq_send (push, "Hello", 5, 0);
zmq_close (push);
zmq_ctx_destroy (child_ctx);
exit (0);
} else {
// Parent process
int count;
for (count = 0; count < NUM_MESSAGES; count++) {
recv_string_expect_success (pull, "Hello", 0);
}
int child_status;
while (true) {
int rc = waitpid (pid, &child_status, 0);
if (rc == -1 && errno == EINTR)
continue;
TEST_ASSERT_GREATER_THAN (0, rc);
// Verify the status code of the child was zero
TEST_ASSERT_EQUAL (0, WEXITSTATUS (child_status));
break;
}
test_context_socket_close (pull);
}
#endif
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_fork);
return UNITY_END ();
}

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_getsockopt_memset ()
{
int64_t more;
size_t more_size = sizeof (more);
void *sb = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
void *sc = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
memset (&more, 0xFF, sizeof (int64_t));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (sc, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_EQUAL_INT (sizeof (int), more_size);
TEST_ASSERT_EQUAL_INT (0, more);
// Cleanup
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_getsockopt_memset);
return UNITY_END ();
}

444
vendor/ZMQ/tests/test_heartbeats.cpp vendored Normal file
View File

@@ -0,0 +1,444 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#if defined(ZMQ_HAVE_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdexcept>
#define close closesocket
typedef SOCKET raw_socket;
#else
#include <arpa/inet.h>
#include <unistd.h>
typedef int raw_socket;
#endif
#include <limits.h>
#include <stdlib.h>
#include <string.h>
// TODO remove this here, either ensure that UINT16_MAX is always properly
// defined or handle this at a more central location
#ifndef UINT16_MAX
#define UINT16_MAX 65535
#endif
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.
static int get_monitor_event (void *monitor_)
{
for (int i = 0; i < 10; i++) {
// First frame in message contains event number and value
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
if (zmq_msg_recv (&msg, monitor_, ZMQ_DONTWAIT) == -1) {
msleep (SETTLE_TIME);
continue; // Interrupted, presumably
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
uint8_t *data = static_cast<uint8_t *> (zmq_msg_data (&msg));
uint16_t event = *reinterpret_cast<uint16_t *> (data);
// Second frame in message contains event address
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
if (zmq_msg_recv (&msg, monitor_, 0) == -1) {
return -1; // Interrupted, presumably
}
TEST_ASSERT_FALSE (zmq_msg_more (&msg));
return event;
}
return -1;
}
static void recv_with_retry (raw_socket fd_, char *buffer_, int bytes_)
{
int received = 0;
while (true) {
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
recv (fd_, buffer_ + received, bytes_ - received, 0));
TEST_ASSERT_GREATER_THAN_INT (0, rc);
received += rc;
TEST_ASSERT_LESS_OR_EQUAL_INT (bytes_, received);
if (received == bytes_)
break;
}
}
static void mock_handshake (raw_socket fd_, int mock_ping_)
{
char buffer[128];
memset (buffer, 0, sizeof (buffer));
memcpy (buffer, zmtp_greeting_null, sizeof (zmtp_greeting_null));
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (fd_, buffer, sizeof (zmtp_greeting_null), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_greeting_null), rc);
recv_with_retry (fd_, buffer, sizeof (zmtp_greeting_null));
memset (buffer, 0, sizeof (buffer));
memcpy (buffer, zmtp_ready_dealer, sizeof (zmtp_ready_dealer));
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (fd_, buffer, sizeof (zmtp_ready_dealer), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_dealer), rc);
// greeting
recv_with_retry (fd_, buffer, sizeof (zmtp_ready_dealer));
if (mock_ping_) {
// test PING context - should be replicated in the PONG
// to avoid timeouts, do a bulk send
const uint8_t zmtp_ping[12] = {4, 10, 4, 'P', 'I', 'N',
'G', 0, 0, 'L', 'O', 'L'};
uint8_t zmtp_pong[10] = {4, 8, 4, 'P', 'O', 'N', 'G', 'L', 'O', 'L'};
memset (buffer, 0, sizeof (buffer));
memcpy (buffer, zmtp_ping, 12);
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 12, 0));
TEST_ASSERT_EQUAL_INT (12, rc);
// test a larger body that won't fit in a small message and should get
// truncated
memset (buffer, 'z', sizeof (buffer));
memcpy (buffer, zmtp_ping, 12);
buffer[1] = 65;
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 67, 0));
TEST_ASSERT_EQUAL_INT (67, rc);
// small pong
recv_with_retry (fd_, buffer, 10);
TEST_ASSERT_EQUAL_INT (0, memcmp (zmtp_pong, buffer, 10));
// large pong
recv_with_retry (fd_, buffer, 23);
uint8_t zmtp_pooong[65] = {4, 21, 4, 'P', 'O', 'N', 'G', 'L', 'O', 'L'};
memset (zmtp_pooong + 10, 'z', 55);
TEST_ASSERT_EQUAL_INT (0, memcmp (zmtp_pooong, buffer, 23));
}
}
static void setup_curve (void *socket_, int is_server_)
{
const char *secret_key;
const char *public_key;
const char *server_key;
if (is_server_) {
secret_key = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6";
public_key = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
server_key = NULL;
} else {
secret_key = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs";
public_key = "Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID";
server_key = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
}
zmq_setsockopt (socket_, ZMQ_CURVE_SECRETKEY, secret_key,
strlen (secret_key));
zmq_setsockopt (socket_, ZMQ_CURVE_PUBLICKEY, public_key,
strlen (public_key));
if (is_server_)
zmq_setsockopt (socket_, ZMQ_CURVE_SERVER, &is_server_,
sizeof (is_server_));
else
zmq_setsockopt (socket_, ZMQ_CURVE_SERVERKEY, server_key,
strlen (server_key));
}
static void prep_server_socket (int set_heartbeats_,
int is_curve_,
void **server_out_,
void **mon_out_,
char *endpoint_,
size_t ep_length_,
int socket_type_)
{
// We'll be using this socket in raw mode
void *server = test_context_socket (socket_type_);
int value = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_LINGER, &value, sizeof (value)));
if (set_heartbeats_) {
value = 50;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_HEARTBEAT_IVL, &value, sizeof (value)));
}
if (is_curve_)
setup_curve (server, 1);
bind_loopback_ipv4 (server, endpoint_, ep_length_);
// Create and connect a socket for collecting monitor events on dealer
void *server_mon = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
server, "inproc://monitor-dealer",
ZMQ_EVENT_CONNECTED | ZMQ_EVENT_DISCONNECTED | ZMQ_EVENT_ACCEPTED));
// Connect to the inproc endpoint so we'll get events
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (server_mon, "inproc://monitor-dealer"));
*server_out_ = server;
*mon_out_ = server_mon;
}
// This checks for a broken TCP connection (or, in this case a stuck one
// where the peer never responds to PINGS). There should be an accepted event
// then a disconnect event.
static void test_heartbeat_timeout (int server_type_, int mock_ping_)
{
int rc;
char my_endpoint[MAX_SOCKET_STRING];
void *server, *server_mon;
prep_server_socket (!mock_ping_, 0, &server, &server_mon, my_endpoint,
MAX_SOCKET_STRING, server_type_);
fd_t s = connect_socket (my_endpoint);
// Mock a ZMTP 3 client so we can forcibly time out a connection
mock_handshake (s, mock_ping_);
// By now everything should report as connected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_ACCEPTED, rc);
if (!mock_ping_) {
// We should have been disconnected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_DISCONNECTED, rc);
}
close (s);
test_context_socket_close (server);
test_context_socket_close (server_mon);
}
// This checks that peers respect the TTL value in ping messages
// We set up a mock ZMTP 3 client and send a ping message with a TLL
// to a server that is not doing any heartbeating. Then we sleep,
// if the server disconnects the client, then we know the TTL did
// its thing correctly.
static void test_heartbeat_ttl (int client_type_, int server_type_)
{
int rc, value;
char my_endpoint[MAX_SOCKET_STRING];
void *server, *server_mon, *client;
prep_server_socket (0, 0, &server, &server_mon, my_endpoint,
MAX_SOCKET_STRING, server_type_);
client = test_context_socket (client_type_);
// Set the heartbeat TTL to 0.1 seconds
value = 100;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_HEARTBEAT_TTL, &value, sizeof (value)));
// Set the heartbeat interval to much longer than the TTL so that
// the socket times out oon the remote side.
value = 250;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_HEARTBEAT_IVL, &value, sizeof (value)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
// By now everything should report as connected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_ACCEPTED, rc);
msleep (SETTLE_TIME);
// We should have been disconnected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_DISCONNECTED, rc);
test_context_socket_close (server);
test_context_socket_close (server_mon);
test_context_socket_close (client);
}
// This checks for normal operation - that is pings and pongs being
// exchanged normally. There should be an accepted event on the server,
// and then no event afterwards.
static void
test_heartbeat_notimeout (int is_curve_, int client_type_, int server_type_)
{
int rc;
char my_endpoint[MAX_SOCKET_STRING];
void *server, *server_mon;
prep_server_socket (1, is_curve_, &server, &server_mon, my_endpoint,
MAX_SOCKET_STRING, server_type_);
void *client = test_context_socket (client_type_);
if (is_curve_)
setup_curve (client, 0);
rc = zmq_connect (client, my_endpoint);
// Give it a sec to connect and handshake
msleep (SETTLE_TIME);
// By now everything should report as connected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_ACCEPTED, rc);
// We should still be connected because pings and pongs are happenin'
TEST_ASSERT_EQUAL_INT (-1, get_monitor_event (server_mon));
test_context_socket_close (client);
test_context_socket_close (server);
test_context_socket_close (server_mon);
}
void test_heartbeat_timeout_router ()
{
test_heartbeat_timeout (ZMQ_ROUTER, 0);
}
void test_heartbeat_timeout_router_mock_ping ()
{
test_heartbeat_timeout (ZMQ_ROUTER, 1);
}
#define DEFINE_TESTS(first, second, first_define, second_define) \
void test_heartbeat_ttl_##first##_##second () \
{ \
test_heartbeat_ttl (first_define, second_define); \
} \
void test_heartbeat_notimeout_##first##_##second () \
{ \
test_heartbeat_notimeout (0, first_define, second_define); \
} \
void test_heartbeat_notimeout_##first##_##second##_with_curve () \
{ \
test_heartbeat_notimeout (1, first_define, second_define); \
}
DEFINE_TESTS (dealer, router, ZMQ_DEALER, ZMQ_ROUTER)
DEFINE_TESTS (req, rep, ZMQ_REQ, ZMQ_REP)
DEFINE_TESTS (pull, push, ZMQ_PULL, ZMQ_PUSH)
DEFINE_TESTS (sub, pub, ZMQ_SUB, ZMQ_PUB)
DEFINE_TESTS (pair, pair, ZMQ_PAIR, ZMQ_PAIR)
#ifdef ZMQ_BUILD_DRAFT_API
DEFINE_TESTS (gather, scatter, ZMQ_GATHER, ZMQ_SCATTER)
DEFINE_TESTS (client, server, ZMQ_CLIENT, ZMQ_SERVER)
#endif
const int deciseconds_per_millisecond = 100;
const int heartbeat_ttl_max =
(UINT16_MAX + 1) * deciseconds_per_millisecond - 1;
void test_setsockopt_heartbeat_success (const int value_)
{
void *const socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_HEARTBEAT_TTL, &value_, sizeof (value_)));
int value_read;
size_t value_read_size = sizeof (value_read);
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (socket, ZMQ_HEARTBEAT_TTL,
&value_read, &value_read_size));
TEST_ASSERT_EQUAL_INT (value_ - value_ % deciseconds_per_millisecond,
value_read);
test_context_socket_close (socket);
}
void test_setsockopt_heartbeat_ttl_max ()
{
test_setsockopt_heartbeat_success (heartbeat_ttl_max);
}
void test_setsockopt_heartbeat_ttl_more_than_max_fails ()
{
void *const socket = test_context_socket (ZMQ_PAIR);
const int value = heartbeat_ttl_max + 1;
TEST_ASSERT_FAILURE_ERRNO (
EINVAL,
zmq_setsockopt (socket, ZMQ_HEARTBEAT_TTL, &value, sizeof (value)));
test_context_socket_close (socket);
}
void test_setsockopt_heartbeat_ttl_near_zero ()
{
test_setsockopt_heartbeat_success (deciseconds_per_millisecond - 1);
}
int main (void)
{
// The test cases are very long-running. The default timeout of 60 seconds
// is not always enough.
setup_test_environment (90);
UNITY_BEGIN ();
RUN_TEST (test_heartbeat_timeout_router);
RUN_TEST (test_heartbeat_timeout_router_mock_ping);
RUN_TEST (test_heartbeat_ttl_dealer_router);
RUN_TEST (test_heartbeat_ttl_req_rep);
RUN_TEST (test_heartbeat_ttl_pull_push);
RUN_TEST (test_heartbeat_ttl_sub_pub);
RUN_TEST (test_heartbeat_ttl_pair_pair);
RUN_TEST (test_setsockopt_heartbeat_ttl_max);
RUN_TEST (test_setsockopt_heartbeat_ttl_more_than_max_fails);
RUN_TEST (test_setsockopt_heartbeat_ttl_near_zero);
RUN_TEST (test_heartbeat_notimeout_dealer_router);
RUN_TEST (test_heartbeat_notimeout_req_rep);
RUN_TEST (test_heartbeat_notimeout_pull_push);
RUN_TEST (test_heartbeat_notimeout_sub_pub);
RUN_TEST (test_heartbeat_notimeout_pair_pair);
RUN_TEST (test_heartbeat_notimeout_dealer_router_with_curve);
RUN_TEST (test_heartbeat_notimeout_req_rep_with_curve);
RUN_TEST (test_heartbeat_notimeout_pull_push_with_curve);
RUN_TEST (test_heartbeat_notimeout_sub_pub_with_curve);
RUN_TEST (test_heartbeat_notimeout_pair_pair_with_curve);
#ifdef ZMQ_BUILD_DRAFT_API
RUN_TEST (test_heartbeat_ttl_client_server);
RUN_TEST (test_heartbeat_ttl_gather_scatter);
RUN_TEST (test_heartbeat_notimeout_client_server);
RUN_TEST (test_heartbeat_notimeout_gather_scatter);
RUN_TEST (test_heartbeat_notimeout_client_server_with_curve);
RUN_TEST (test_heartbeat_notimeout_gather_scatter_with_curve);
#endif
return UNITY_END ();
}

107
vendor/ZMQ/tests/test_hello_msg.cpp vendored Normal file
View File

@@ -0,0 +1,107 @@
/*
Copyright (c) 2007-2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test (const char *address)
{
// Create a router
void *router = test_context_socket (ZMQ_ROUTER);
char my_endpoint[MAX_SOCKET_STRING];
// set router socket options
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_HELLO_MSG, "H", 1));
// bind router
test_bind (router, address, my_endpoint, MAX_SOCKET_STRING);
// Create a dealer
void *dealer = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));
// Receive the hello message
recv_string_expect_success (dealer, "H", 0);
// Clean up.
test_context_socket_close (dealer);
test_context_socket_close (router);
}
void test_tcp ()
{
test ("tcp://127.0.0.1:*");
}
void test_inproc ()
{
test ("inproc://hello-msg");
}
void test_inproc_late_bind ()
{
char address[] = "inproc://late-hello-msg";
// Create a server
void *server = test_context_socket (ZMQ_SERVER);
// set server socket options
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server, ZMQ_HELLO_MSG, "W", 1));
// Create a dealer
void *client = test_context_socket (ZMQ_CLIENT);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_HELLO_MSG, "H", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, address));
// bind server after the dealer
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (server, address));
// Receive the welcome message from server
recv_string_expect_success (client, "W", 0);
// Receive the hello message from client
recv_string_expect_success (server, "H", 0);
// Clean up.
test_context_socket_close (client);
test_context_socket_close (server);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_tcp);
RUN_TEST (test_inproc);
RUN_TEST (test_inproc_late_bind);
return UNITY_END ();
}

306
vendor/ZMQ/tests/test_hwm.cpp vendored Normal file
View File

@@ -0,0 +1,306 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
const int MAX_SENDS = 10000;
enum TestType
{
BIND_FIRST,
CONNECT_FIRST
};
void test_defaults ()
{
// Set up 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 = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
// Send until we block
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
msleep (SETTLE_TIME);
// Now receive all sent messages
int recv_count = 0;
while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++recv_count;
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Clean up
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);
}
int count_msg (int send_hwm_, int recv_hwm_, TestType test_type_)
{
void *bind_socket;
void *connect_socket;
if (test_type_ == BIND_FIRST) {
// Set up 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 = 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"));
// we must wait for the connect to succeed here, unfortunately we don't
// have monitoring events for inproc, so we just hope SETTLE_TIME suffices
msleep (SETTLE_TIME);
} else {
// Set up 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 = 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"));
}
// Send until we block
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
// Now receive all sent messages
int recv_count = 0;
while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++recv_count;
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Now it should be possible to send one more.
send_string_expect_success (connect_socket, NULL, 0);
// Consume the remaining message.
recv_string_expect_success (bind_socket, NULL, 0);
// Clean up
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
return send_count;
}
int test_inproc_bind_first (int send_hwm_, int recv_hwm_)
{
return count_msg (send_hwm_, recv_hwm_, BIND_FIRST);
}
int test_inproc_connect_first (int send_hwm_, int recv_hwm_)
{
return count_msg (send_hwm_, recv_hwm_, CONNECT_FIRST);
}
int test_inproc_connect_and_close_first (int send_hwm_, int recv_hwm_)
{
// Set up 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"));
// Send until we block
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
// Close connect
test_context_socket_close (connect_socket);
// Set up 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"));
// Now receive all sent messages
int recv_count = 0;
while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++recv_count;
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Clean up
test_context_socket_close (bind_socket);
return send_count;
}
int test_inproc_bind_and_close_first (int send_hwm_, int /* recv_hwm */)
{
// Set up bind socket
void *bind_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
// Send until we block
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
// Close bind
test_context_socket_close (bind_socket);
/* TODO Can't currently do connect without then wiring up a bind as things hang, this needs top be fixed.
// Set up connect socket
void *connect_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
// Now receive all sent messages
int recv_count = 0;
while (zmq_recv (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++recv_count;
TEST_ASSERT_EQUAL_INT(send_count, recv_count);
*/
// Clean up
//test_context_socket_close (connect_socket);
return send_count;
}
void test_infinite_both_inproc_bind_first ()
{
int count = test_inproc_bind_first (0, 0);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_infinite_both_inproc_connect_first ()
{
int count = test_inproc_connect_first (0, 0);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_infinite_receive_inproc_bind_first ()
{
int count = test_inproc_bind_first (1, 0);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_infinite_receive_inproc_connect_first ()
{
int count = test_inproc_connect_first (1, 0);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_infinite_send_inproc_bind_first ()
{
int count = test_inproc_bind_first (0, 1);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_infinite_send_inproc_connect_first ()
{
int count = test_inproc_connect_first (0, 1);
TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
}
void test_finite_both_bind_first ()
{
// Send and recv buffers hwm 1, so total that can be queued is 2
int count = test_inproc_bind_first (1, 1);
TEST_ASSERT_EQUAL_INT (2, count);
}
void test_finite_both_connect_first ()
{
// Send and recv buffers hwm 1, so total that can be queued is 2
int count = test_inproc_connect_first (1, 1);
TEST_ASSERT_EQUAL_INT (2, count);
}
void test_infinite_recv_connect_and_close_first ()
{
// Send hwm of 1, send before bind so total that can be queued is 1
int count = test_inproc_connect_and_close_first (1, 0);
TEST_ASSERT_EQUAL_INT (1, count);
}
void test_infinite_recv_bind_and_close_first ()
{
// Send hwm of 1, send from bind side before connect so total that can be queued should be 1,
// however currently all messages get thrown away before the connect. BUG?
/*int count = */ test_inproc_bind_and_close_first (1, 0);
// TEST_ASSERT_EQUAL_INT (1, count);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_defaults);
RUN_TEST (test_infinite_both_inproc_bind_first);
RUN_TEST (test_infinite_both_inproc_connect_first);
RUN_TEST (test_infinite_receive_inproc_bind_first);
RUN_TEST (test_infinite_receive_inproc_connect_first);
RUN_TEST (test_infinite_send_inproc_bind_first);
RUN_TEST (test_infinite_send_inproc_connect_first);
RUN_TEST (test_finite_both_bind_first);
RUN_TEST (test_finite_both_connect_first);
RUN_TEST (test_infinite_recv_connect_and_close_first);
RUN_TEST (test_infinite_recv_bind_and_close_first);
return UNITY_END ();
}

304
vendor/ZMQ/tests/test_hwm_pubsub.cpp vendored Normal file
View File

@@ -0,0 +1,304 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
// NOTE: on OSX the endpoint returned by ZMQ_LAST_ENDPOINT may be quite long,
// ensure we have extra space for that:
#define SOCKET_STRING_LEN (MAX_SOCKET_STRING * 4)
SETUP_TEARDOWN_TESTCONTEXT
int test_defaults (int send_hwm_, int msg_cnt_, const char *endpoint_)
{
char pub_endpoint[SOCKET_STRING_LEN];
// Set up and bind XPUB socket
void *pub_socket = test_context_socket (ZMQ_XPUB);
test_bind (pub_socket, endpoint_, pub_endpoint, sizeof pub_endpoint);
// Set up and connect SUB socket
void *sub_socket = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_socket, pub_endpoint));
//set a hwm on publisher
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pub_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, 0, 0));
// Wait before starting TX operations till 1 subscriber has subscribed
// (in this test there's 1 subscriber only)
const char subscription_to_all_topics[] = {1, 0};
recv_string_expect_success (pub_socket, subscription_to_all_topics, 0);
// Send until we reach "mute" state
int send_count = 0;
while (send_count < msg_cnt_
&& zmq_send (pub_socket, "test message", 13, ZMQ_DONTWAIT) == 13)
++send_count;
TEST_ASSERT_EQUAL_INT (send_hwm_, send_count);
msleep (SETTLE_TIME);
// Now receive all sent messages
int recv_count = 0;
char dummybuff[64];
while (13 == zmq_recv (sub_socket, &dummybuff, 64, ZMQ_DONTWAIT)) {
++recv_count;
}
TEST_ASSERT_EQUAL_INT (send_hwm_, recv_count);
// Clean up
test_context_socket_close (sub_socket);
test_context_socket_close (pub_socket);
return recv_count;
}
int receive (void *socket_, int *is_termination_)
{
int recv_count = 0;
*is_termination_ = 0;
// Now receive all sent messages
char buffer[255];
int len;
while ((len = zmq_recv (socket_, buffer, sizeof (buffer), 0)) >= 0) {
++recv_count;
if (len == 3 && strncmp (buffer, "end", len) == 0) {
*is_termination_ = 1;
return recv_count;
}
}
return recv_count;
}
int test_blocking (int send_hwm_, int msg_cnt_, const char *endpoint_)
{
char pub_endpoint[SOCKET_STRING_LEN];
// Set up bind socket
void *pub_socket = test_context_socket (ZMQ_XPUB);
test_bind (pub_socket, endpoint_, pub_endpoint, sizeof pub_endpoint);
// Set up connect socket
void *sub_socket = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_socket, pub_endpoint));
//set a hwm on publisher
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pub_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
int wait = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pub_socket, ZMQ_XPUB_NODROP, &wait, sizeof (wait)));
int timeout_ms = 10;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
sub_socket, ZMQ_RCVTIMEO, &timeout_ms, sizeof (timeout_ms)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, 0, 0));
// Wait before starting TX operations till 1 subscriber has subscribed
// (in this test there's 1 subscriber only)
const uint8_t subscription_to_all_topics[] = {1};
recv_array_expect_success (pub_socket, subscription_to_all_topics, 0);
// Send until we block
int send_count = 0;
int recv_count = 0;
int blocked_count = 0;
int is_termination = 0;
while (send_count < msg_cnt_) {
const int rc = zmq_send (pub_socket, NULL, 0, ZMQ_DONTWAIT);
if (rc == 0) {
++send_count;
} else if (-1 == rc) {
// if the PUB socket blocks due to HWM, errno should be EAGAIN:
blocked_count++;
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
recv_count += receive (sub_socket, &is_termination);
}
}
// if send_hwm_ < msg_cnt_, we should block at least once:
char counts_string[128];
snprintf (counts_string, sizeof counts_string - 1,
"sent = %i, received = %i", send_count, recv_count);
TEST_ASSERT_GREATER_THAN_INT_MESSAGE (0, blocked_count, counts_string);
// dequeue SUB socket again, to make sure XPUB has space to send the termination message
recv_count += receive (sub_socket, &is_termination);
// send termination message
send_string_expect_success (pub_socket, "end", 0);
// now block on the SUB side till we get the termination message
while (is_termination == 0)
recv_count += receive (sub_socket, &is_termination);
// remove termination message from the count:
recv_count--;
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
// Clean up
test_context_socket_close (sub_socket);
test_context_socket_close (pub_socket);
return recv_count;
}
// hwm should apply to the messages that have already been received
// with hwm 11024: send 9999 msg, receive 9999, send 1100, receive 1100
void test_reset_hwm ()
{
const int first_count = 9999;
const int second_count = 1100;
int hwm = 11024;
char my_endpoint[SOCKET_STRING_LEN];
// Set up bind socket
void *pub_socket = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pub_socket, ZMQ_SNDHWM, &hwm, sizeof (hwm)));
bind_loopback_ipv4 (pub_socket, my_endpoint, MAX_SOCKET_STRING);
// Set up connect socket
void *sub_socket = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub_socket, ZMQ_RCVHWM, &hwm, sizeof (hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_socket, my_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, 0, 0));
msleep (SETTLE_TIME);
// Send messages
int send_count = 0;
while (send_count < first_count
&& zmq_send (pub_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
TEST_ASSERT_EQUAL_INT (first_count, send_count);
msleep (SETTLE_TIME);
// Now receive all sent messages
int recv_count = 0;
while (0 == zmq_recv (sub_socket, NULL, 0, ZMQ_DONTWAIT)) {
++recv_count;
}
TEST_ASSERT_EQUAL_INT (first_count, recv_count);
msleep (SETTLE_TIME);
// Send messages
send_count = 0;
while (send_count < second_count
&& zmq_send (pub_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
TEST_ASSERT_EQUAL_INT (second_count, send_count);
msleep (SETTLE_TIME);
// Now receive all sent messages
recv_count = 0;
while (0 == zmq_recv (sub_socket, NULL, 0, ZMQ_DONTWAIT)) {
++recv_count;
}
TEST_ASSERT_EQUAL_INT (second_count, recv_count);
// Clean up
test_context_socket_close (sub_socket);
test_context_socket_close (pub_socket);
}
void test_defaults_large (const char *bind_endpoint_)
{
// send 1000 msg on hwm 1000, receive 1000
TEST_ASSERT_EQUAL_INT (1000, test_defaults (1000, 1000, bind_endpoint_));
}
void test_defaults_small (const char *bind_endpoint_)
{
// send 1000 msg on hwm 100, receive 100
TEST_ASSERT_EQUAL_INT (100, test_defaults (100, 100, bind_endpoint_));
}
void test_blocking (const char *bind_endpoint_)
{
// send 6000 msg on hwm 2000, drops above hwm, only receive hwm:
TEST_ASSERT_EQUAL_INT (6000, test_blocking (2000, 6000, bind_endpoint_));
}
#define DEFINE_REGULAR_TEST_CASES(name, bind_endpoint) \
void test_defaults_large_##name () \
{ \
test_defaults_large (bind_endpoint); \
} \
\
void test_defaults_small_##name () \
{ \
test_defaults_small (bind_endpoint); \
} \
\
void test_blocking_##name () { test_blocking (bind_endpoint); }
#define RUN_REGULAR_TEST_CASES(name) \
RUN_TEST (test_defaults_large_##name); \
RUN_TEST (test_defaults_small_##name); \
RUN_TEST (test_blocking_##name)
DEFINE_REGULAR_TEST_CASES (tcp, "tcp://127.0.0.1:*")
DEFINE_REGULAR_TEST_CASES (inproc, "inproc://a")
#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU)
DEFINE_REGULAR_TEST_CASES (ipc, "ipc://*")
#endif
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_REGULAR_TEST_CASES (tcp);
RUN_REGULAR_TEST_CASES (inproc);
#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU)
RUN_REGULAR_TEST_CASES (ipc);
#endif
RUN_TEST (test_reset_hwm);
return UNITY_END ();
}

221
vendor/ZMQ/tests/test_immediate.cpp vendored Normal file
View File

@@ -0,0 +1,221 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_immediate_1 ()
{
int val;
int rc;
char buffer[16];
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
// TEST 1.
// First we're going to attempt to send messages to two
// pipes, one connected, the other not. We should see
// the PUSH load balancing to both pipes, and hence half
// of the messages getting queued, as connect() creates a
// pipe immediately.
void *to = test_context_socket (ZMQ_PULL);
// Bind the one valid receiver
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof (val)));
bind_loopback_ipv4 (to, my_endpoint, len);
// Create a socket pushing to two endpoints - only 1 message should arrive.
void *from = test_context_socket (ZMQ_PUSH);
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)));
// This pipe will not connect (provided the ephemeral port is not 5556)
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tcp://localhost:5556"));
// This pipe will
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, my_endpoint));
msleep (SETTLE_TIME);
// We send 10 messages, 5 should just get stuck in the queue
// for the not-yet-connected pipe
for (int i = 0; i < 10; ++i) {
send_string_expect_success (from, "Hello", 0);
}
// We now consume from the connected pipe
// - we should see just 5
int timeout = 250;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
int seen = 0;
while (true) {
rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
if (rc == -1)
break; // Break when we didn't get a message
seen++;
}
TEST_ASSERT_EQUAL_INT (5, seen);
test_context_socket_close (from);
test_context_socket_close (to);
}
void test_immediate_2 ()
{
// This time we will do the same thing, connect two pipes,
// one of which will succeed in connecting to a bound
// receiver, the other of which will fail. However, we will
// also set the delay attach on connect flag, which should
// cause the pipe attachment to be delayed until the connection
// succeeds.
// Bind the valid socket
void *to = test_context_socket (ZMQ_PULL);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (to, my_endpoint, len);
int val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof (val)));
// Create a socket pushing to two endpoints - all messages should arrive.
void *from = test_context_socket (ZMQ_PUSH);
val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)));
// Set the key flag
val = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (from, ZMQ_IMMEDIATE, &val, sizeof (val)));
// Connect to the invalid socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tcp://localhost:5561"));
// Connect to the valid socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, my_endpoint));
// Send 10 messages, all should be routed to the connected pipe
for (int i = 0; i < 10; ++i) {
send_string_expect_success (from, "Hello", 0);
}
int timeout = 250;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
int seen = 0;
while (true) {
char buffer[16];
int rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
if (rc == -1)
break; // Break when we didn't get a message
seen++;
}
TEST_ASSERT_EQUAL_INT (10, seen);
test_context_socket_close (from);
test_context_socket_close (to);
}
void test_immediate_3 ()
{
// This time we want to validate that the same blocking behaviour
// occurs with an existing connection that is broken. We will send
// messages to a connected pipe, disconnect and verify the messages
// block. Then we reconnect and verify messages flow again.
void *backend = test_context_socket (ZMQ_DEALER);
void *frontend = test_context_socket (ZMQ_DEALER);
int zero = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero)));
// Frontend connects to backend using IMMEDIATE
int on = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_IMMEDIATE, &on, sizeof (on)));
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (backend, my_endpoint, len);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (frontend, my_endpoint));
// Ping backend to frontend so we know when the connection is up
send_string_expect_success (backend, "Hello", 0);
recv_string_expect_success (frontend, "Hello", 0);
// Send message from frontend to backend
send_string_expect_success (frontend, "Hello", ZMQ_DONTWAIT);
test_context_socket_close (backend);
// Give time to process disconnect
msleep (SETTLE_TIME * 10);
// Send a message, should fail
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT));
// Recreate backend socket
backend = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (backend, my_endpoint));
// Ping backend to frontend so we know when the connection is up
send_string_expect_success (backend, "Hello", 0);
recv_string_expect_success (frontend, "Hello", 0);
// After the reconnect, should succeed
send_string_expect_success (frontend, "Hello", ZMQ_DONTWAIT);
test_context_socket_close (backend);
test_context_socket_close (frontend);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_immediate_1);
RUN_TEST (test_immediate_2);
RUN_TEST (test_immediate_3);
return UNITY_END ();
}

353
vendor/ZMQ/tests/test_inproc_connect.cpp vendored Normal file
View File

@@ -0,0 +1,353 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
static void pusher (void * /*unused*/)
{
// Connect first
// do not use test_context_socket here, as it is not thread-safe
void *connect_socket = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://sink"));
// Queue up some data
send_string_expect_success (connect_socket, "foobar", 0);
// Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
}
static void simult_conn (void *endpt_)
{
// Pull out arguments - endpoint string
const char *endpt = static_cast<const char *> (endpt_);
// Connect
// do not use test_context_socket here, as it is not thread-safe
void *connect_socket = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, endpt));
// Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
}
static void simult_bind (void *endpt_)
{
// Pull out arguments - context followed by endpoint string
const char *endpt = static_cast<const char *> (endpt_);
// Bind
// do not use test_context_socket here, as it is not thread-safe
void *bind_socket = zmq_socket (get_test_context (), ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, endpt));
// Cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));
}
void test_bind_before_connect ()
{
// Bind first
void *bind_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://bbc"));
// Now connect
void *connect_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://bbc"));
// Queue up some data
send_string_expect_success (connect_socket, "foobar", 0);
// Read pending message
recv_string_expect_success (bind_socket, "foobar", 0);
// Cleanup
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
}
void test_connect_before_bind ()
{
// Connect first
void *connect_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://cbb"));
// Queue up some data
send_string_expect_success (connect_socket, "foobar", 0);
// Now bind
void *bind_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://cbb"));
// Read pending message
recv_string_expect_success (bind_socket, "foobar", 0);
// Cleanup
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
}
void test_connect_before_bind_pub_sub ()
{
// Connect first
void *connect_socket = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://cbbps"));
// Queue up some data, this will be dropped
send_string_expect_success (connect_socket, "before", 0);
// Now bind
void *bind_socket = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (bind_socket, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://cbbps"));
// Wait for pub-sub connection to happen
msleep (SETTLE_TIME);
// Queue up some data, this not will be dropped
send_string_expect_success (connect_socket, "after", 0);
// Read pending message
recv_string_expect_success (bind_socket, "after", 0);
// Cleanup
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket);
}
void test_connect_before_bind_ctx_term ()
{
for (int i = 0; i < 20; ++i) {
// Connect first
void *connect_socket = test_context_socket (ZMQ_ROUTER);
char ep[32];
sprintf (ep, "inproc://cbbrr%d", i);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, ep));
// Cleanup
test_context_socket_close (connect_socket);
}
}
void test_multiple_connects ()
{
const unsigned int no_of_connects = 10;
void *connect_socket[no_of_connects];
// Connect first
for (unsigned int i = 0; i < no_of_connects; ++i) {
connect_socket[i] = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (connect_socket[i], "inproc://multiple"));
// Queue up some data
send_string_expect_success (connect_socket[i], "foobar", 0);
}
// Now bind
void *bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://multiple"));
for (unsigned int i = 0; i < no_of_connects; ++i) {
recv_string_expect_success (bind_socket, "foobar", 0);
}
// Cleanup
for (unsigned int i = 0; i < no_of_connects; ++i) {
test_context_socket_close (connect_socket[i]);
}
test_context_socket_close (bind_socket);
}
void test_multiple_threads ()
{
const unsigned int no_of_threads = 30;
void *threads[no_of_threads];
// Connect first
for (unsigned int i = 0; i < no_of_threads; ++i) {
threads[i] = zmq_threadstart (&pusher, NULL);
}
// Now bind
void *bind_socket = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://sink"));
for (unsigned int i = 0; i < no_of_threads; ++i) {
// Read pending message
recv_string_expect_success (bind_socket, "foobar", 0);
}
// Cleanup
for (unsigned int i = 0; i < no_of_threads; ++i) {
zmq_threadclose (threads[i]);
}
test_context_socket_close (bind_socket);
}
void test_simultaneous_connect_bind_threads ()
{
const unsigned int no_of_times = 50;
void *threads[no_of_times * 2];
void *thr_args[no_of_times];
char endpts[no_of_times][20];
// Set up thread arguments: context followed by endpoint string
for (unsigned int i = 0; i < no_of_times; ++i) {
thr_args[i] = (void *) endpts[i];
sprintf (endpts[i], "inproc://foo_%d", i);
}
// Spawn all threads as simultaneously as possible
for (unsigned int i = 0; i < no_of_times; ++i) {
threads[i * 2 + 0] = zmq_threadstart (&simult_conn, thr_args[i]);
threads[i * 2 + 1] = zmq_threadstart (&simult_bind, thr_args[i]);
}
// Close all threads
for (unsigned int i = 0; i < no_of_times; ++i) {
zmq_threadclose (threads[i * 2 + 0]);
zmq_threadclose (threads[i * 2 + 1]);
}
}
void test_routing_id ()
{
// Create the infrastructure
void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://routing_id"));
void *sb = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://routing_id"));
// Send 2-part message.
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (sc, "A", 1, ZMQ_SNDMORE)));
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (sc, "B", 1, 0)));
// Routing id comes first.
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0));
TEST_ASSERT_EQUAL_INT (1, zmq_msg_more (&msg));
// Then the first part of the message body.
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
TEST_ASSERT_EQUAL_INT (1, zmq_msg_more (&msg));
// And finally, the second part of the message body.
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
TEST_ASSERT_EQUAL_INT (0, zmq_msg_more (&msg));
// Deallocate the infrastructure.
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_connect_only ()
{
void *connect_socket = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
test_context_socket_close (connect_socket);
}
void test_unbind ()
{
// Bind and unbind socket 1
void *bind_socket1 = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket1, "inproc://unbind"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (bind_socket1, "inproc://unbind"));
// Bind socket 2
void *bind_socket2 = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket2, "inproc://unbind"));
// Now connect
void *connect_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://unbind"));
// Queue up some data
send_string_expect_success (connect_socket, "foobar", 0);
// Read pending message
recv_string_expect_success (bind_socket2, "foobar", 0);
// Cleanup
test_context_socket_close (connect_socket);
test_context_socket_close (bind_socket1);
test_context_socket_close (bind_socket2);
}
void test_shutdown_during_pend ()
{
// Connect first
void *connect_socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://cbb"));
zmq_ctx_shutdown (get_test_context ());
// Cleanup
test_context_socket_close (connect_socket);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_bind_before_connect);
RUN_TEST (test_connect_before_bind);
RUN_TEST (test_connect_before_bind_pub_sub);
RUN_TEST (test_connect_before_bind_ctx_term);
RUN_TEST (test_multiple_connects);
RUN_TEST (test_multiple_threads);
RUN_TEST (test_simultaneous_connect_bind_threads);
RUN_TEST (test_routing_id);
RUN_TEST (test_connect_only);
RUN_TEST (test_unbind);
RUN_TEST (test_shutdown_during_pend);
return UNITY_END ();
}

91
vendor/ZMQ/tests/test_invalid_rep.cpp vendored Normal file
View File

@@ -0,0 +1,91 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_invalid_rep ()
{
// Create REQ/ROUTER wiring.
void *router_socket = test_context_socket (ZMQ_ROUTER);
void *req_socket = test_context_socket (ZMQ_REQ);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router_socket, ZMQ_LINGER, &linger, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req_socket, ZMQ_LINGER, &linger, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router_socket, "inproc://hi"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req_socket, "inproc://hi"));
// Initial request.
send_string_expect_success (req_socket, "r", 0);
// Receive the request.
char addr[32];
int addr_size;
char bottom[1];
char body[1];
TEST_ASSERT_SUCCESS_ERRNO (
addr_size = zmq_recv (router_socket, addr, sizeof (addr), 0));
TEST_ASSERT_EQUAL_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
router_socket, bottom, sizeof (bottom), 0)));
TEST_ASSERT_EQUAL_INT (1, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
router_socket, body, sizeof (body), 0)));
// Send invalid reply.
TEST_ASSERT_EQUAL_INT (addr_size, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (
router_socket, addr, addr_size, 0)));
// Send valid reply.
TEST_ASSERT_EQUAL_INT (
addr_size, TEST_ASSERT_SUCCESS_ERRNO (
zmq_send (router_socket, addr, addr_size, ZMQ_SNDMORE)));
TEST_ASSERT_EQUAL_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (
router_socket, bottom, 0, ZMQ_SNDMORE)));
send_string_expect_success (router_socket, "b", 0);
// Check whether we've got the valid reply.
recv_string_expect_success (req_socket, "b", 0);
// Tear down the wiring.
test_context_socket_close (router_socket);
test_context_socket_close (req_socket);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_invalid_rep);
return UNITY_END ();
}

154
vendor/ZMQ/tests/test_iov.cpp vendored Normal file
View File

@@ -0,0 +1,154 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
// XSI vector I/O
#if defined ZMQ_HAVE_UIO
#include <sys/uio.h>
#else
struct iovec
{
void *iov_base;
size_t iov_len;
};
#endif
static void do_check (void *sb_, void *sc_, size_t msg_size_)
{
TEST_ASSERT_NOT_NULL (sb_);
TEST_ASSERT_NOT_NULL (sc_);
TEST_ASSERT_GREATER_THAN (0, msg_size_);
const char msg_val = '1';
const int num_messages = 10;
size_t send_count, recv_count;
send_count = recv_count = num_messages;
char *ref_msg = static_cast<char *> (malloc (msg_size_));
TEST_ASSERT_NOT_NULL (ref_msg);
memset (ref_msg, msg_val, msg_size_);
// zmq_sendiov(3) as a single multi-part send
struct iovec send_iov[num_messages];
char *buf = static_cast<char *> (malloc (msg_size_ * num_messages));
for (int i = 0; i < num_messages; i++) {
send_iov[i].iov_base = &buf[i * msg_size_];
send_iov[i].iov_len = msg_size_;
memcpy (send_iov[i].iov_base, ref_msg, msg_size_);
// TODO: this assertion only checks if memcpy behaves as expected... remove this or assert something else?
TEST_ASSERT_EQUAL_HEX8_ARRAY (ref_msg, send_iov[i].iov_base, msg_size_);
}
// Test errors - zmq_recviov - null socket
TEST_ASSERT_FAILURE_ERRNO (
ENOTSOCK, zmq_sendiov (NULL, send_iov, send_count, ZMQ_SNDMORE));
// Test errors - zmq_recviov - invalid send count
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_sendiov (sc_, send_iov, 0, 0));
// Test errors - zmq_recviov - null iovec
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_sendiov (sc_, NULL, send_count, 0));
// Test success
// The zmq_sendiov(3) API method does not follow the same semantics as
// zmq_recviov(3); the latter returns the count of messages sent, rightly
// so, whilst the former sends the number of bytes successfully sent from
// the last message, which does not hold much sense from a batch send
// perspective; hence the assert checks if the result is same as msg_size.
TEST_ASSERT_EQUAL_INT (
(int) msg_size_, TEST_ASSERT_SUCCESS_ERRNO (
zmq_sendiov (sc_, send_iov, send_count, ZMQ_SNDMORE)));
// zmq_recviov(3) single-shot
struct iovec recv_iov[num_messages];
// Test errors - zmq_recviov - null socket
TEST_ASSERT_FAILURE_ERRNO (ENOTSOCK,
zmq_recviov (NULL, recv_iov, &recv_count, 0));
// Test error - zmq_recviov - invalid receive count
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_recviov (sb_, recv_iov, NULL, 0));
size_t invalid_recv_count = 0;
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_recviov (sb_, recv_iov, &invalid_recv_count, 0));
// Test error - zmq_recviov - null iovec
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_recviov (sb_, NULL, &recv_count, 0));
// Test success
TEST_ASSERT_EQUAL_INT (
num_messages,
TEST_ASSERT_SUCCESS_ERRNO (zmq_recviov (sb_, recv_iov, &recv_count, 0)));
for (int i = 0; i < num_messages; i++) {
TEST_ASSERT_NOT_NULL (recv_iov[i].iov_base);
TEST_ASSERT_EQUAL_STRING_LEN (ref_msg, recv_iov[i].iov_base, msg_size_);
free (recv_iov[i].iov_base);
}
TEST_ASSERT_EQUAL_INT (send_count, recv_count);
free (ref_msg);
free (buf);
}
void test_iov ()
{
void *sb = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
msleep (SETTLE_TIME);
void *sc = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
// message bigger than VSM max
do_check (sb, sc, 100);
// message smaller than VSM max
do_check (sb, sc, 10);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_iov);
return UNITY_END ();
}

57
vendor/ZMQ/tests/test_ipc_wildcard.cpp vendored Normal file
View File

@@ -0,0 +1,57 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_ipc_wildcard ()
{
void *sb = test_context_socket (ZMQ_PAIR);
char endpoint[200];
bind_loopback_ipc (sb, endpoint, sizeof endpoint);
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_ipc_wildcard);
return UNITY_END ();
}

98
vendor/ZMQ/tests/test_issue_566.cpp vendored Normal file
View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
// Issue 566 describes a problem in libzmq v4.0.0 where a dealer to router
// connection would fail randomly. The test works when the two sockets are
// on the same context, and failed when they were on separate contexts.
// Fixed by https://github.com/zeromq/libzmq/commit/be25cf.
void test_issue_566 ()
{
char my_endpoint[MAX_SOCKET_STRING];
void *ctx1 = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx1);
void *ctx2 = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx2);
void *router = zmq_socket (ctx1, ZMQ_ROUTER);
int on = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY, &on, sizeof (on)));
bind_loopback_ipv4 (router, my_endpoint, sizeof (my_endpoint));
// Repeat often enough to be sure this works as it should
for (int cycle = 0; cycle < 100; cycle++) {
// Create dealer with unique explicit routing id
// We assume the router learns this out-of-band
void *dealer = zmq_socket (ctx2, ZMQ_DEALER);
// Leave space for NULL char from sprintf, gcc warning
char routing_id[11];
sprintf (routing_id, "%09d", cycle);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer, ZMQ_ROUTING_ID, routing_id, 10));
int rcvtimeo = 1000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));
// Router will try to send to dealer, at short intervals.
// It typically takes 2-5 msec for the connection to establish
// on a loopback interface, but we'll allow up to one second
// before failing the test (e.g. for running on a debugger or
// a very slow system).
for (int attempt = 0; attempt < 500; attempt++) {
zmq_poll (NULL, 0, 2);
int rc = zmq_send (router, routing_id, 10, ZMQ_SNDMORE);
if (rc == -1 && errno == EHOSTUNREACH)
continue;
TEST_ASSERT_EQUAL (10, rc);
send_string_expect_success (router, "HELLO", 0);
break;
}
recv_string_expect_success (dealer, "HELLO", 0);
close_zero_linger (dealer);
}
zmq_close (router);
zmq_ctx_destroy (ctx1);
zmq_ctx_destroy (ctx2);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_issue_566);
return UNITY_END ();
}

65
vendor/ZMQ/tests/test_last_endpoint.cpp vendored Normal file
View File

@@ -0,0 +1,65 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
static void do_bind_and_verify (void *s_, const char *endpoint_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s_, endpoint_));
char reported[255];
size_t size = 255;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (s_, ZMQ_LAST_ENDPOINT, reported, &size));
TEST_ASSERT_EQUAL_STRING (endpoint_, reported);
}
void test_last_endpoint ()
{
void *sb = test_context_socket (ZMQ_ROUTER);
int val = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sb, ZMQ_LINGER, &val, sizeof (val)));
do_bind_and_verify (sb, ENDPOINT_1);
do_bind_and_verify (sb, ENDPOINT_2);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_last_endpoint);
return UNITY_END ();
}

98
vendor/ZMQ/tests/test_many_sockets.cpp vendored Normal file
View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
SETUP_TEARDOWN_TESTCONTEXT
void test_system_max ()
{
// Keep allocating sockets until we run out of system resources
const int no_of_sockets = 2 * 65536;
zmq_ctx_set (get_test_context (), ZMQ_MAX_SOCKETS, no_of_sockets);
std::vector<void *> sockets;
while (true) {
void *socket = zmq_socket (get_test_context (), ZMQ_PAIR);
if (!socket)
break;
sockets.push_back (socket);
}
TEST_ASSERT_LESS_OR_EQUAL (no_of_sockets,
static_cast<int> (sockets.size ()));
printf ("Socket creation failed after %i sockets\n",
static_cast<int> (sockets.size ()));
// System is out of resources, further calls to zmq_socket should return NULL
for (unsigned int i = 0; i < 10; ++i) {
TEST_ASSERT_NULL (zmq_socket (get_test_context (), ZMQ_PAIR));
}
// Clean up.
for (unsigned int i = 0; i < sockets.size (); ++i)
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (sockets[i]));
}
void test_zmq_default_max ()
{
// Keep allocating sockets until we hit the default limit
std::vector<void *> sockets;
while (true) {
void *socket = zmq_socket (get_test_context (), ZMQ_PAIR);
if (!socket)
break;
sockets.push_back (socket);
}
// We may stop sooner if system has fewer available sockets
TEST_ASSERT_LESS_OR_EQUAL (ZMQ_MAX_SOCKETS_DFLT, sockets.size ());
// Further calls to zmq_socket should return NULL
for (unsigned int i = 0; i < 10; ++i) {
TEST_ASSERT_NULL (zmq_socket (get_test_context (), ZMQ_PAIR));
}
// Clean up
for (unsigned int i = 0; i < sockets.size (); ++i)
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (sockets[i]));
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_system_max);
RUN_TEST (test_zmq_default_max);
return UNITY_END ();
}

136
vendor/ZMQ/tests/test_metadata.cpp vendored Normal file
View File

@@ -0,0 +1,136 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <unity.h>
void setUp ()
{
}
void tearDown ()
{
}
static void zap_handler (void *handler_)
{
uint8_t metadata[] = {5, 'H', 'e', 'l', 'l', 'o', 0, 0,
0, 5, 'W', 'o', 'r', 'l', 'd'};
// Process ZAP requests forever
while (true) {
char *version = s_recv (handler_);
if (!version)
break; // Terminating
char *sequence = s_recv (handler_);
char *domain = s_recv (handler_);
char *address = s_recv (handler_);
char *routing_id = s_recv (handler_);
char *mechanism = s_recv (handler_);
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("NULL", mechanism);
send_string_expect_success (handler_, version, ZMQ_SNDMORE);
send_string_expect_success (handler_, sequence, ZMQ_SNDMORE);
if (streq (domain, "DOMAIN")) {
send_string_expect_success (handler_, "200", ZMQ_SNDMORE);
send_string_expect_success (handler_, "OK", ZMQ_SNDMORE);
send_string_expect_success (handler_, "anonymous", ZMQ_SNDMORE);
zmq_send (handler_, metadata, sizeof (metadata), 0);
} else {
send_string_expect_success (handler_, "400", ZMQ_SNDMORE);
send_string_expect_success (handler_, "BAD DOMAIN", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", 0);
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
}
close_zero_linger (handler_);
}
void test_metadata ()
{
char my_endpoint[MAX_SOCKET_STRING];
setup_test_context ();
// Spawn ZAP handler
// We create and bind ZAP socket in main thread to avoid case
// where child thread does not start up fast enough.
void *handler = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_NOT_NULL (handler);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
void *zap_thread = zmq_threadstart (&zap_handler, handler);
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "DOMAIN", 6));
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
send_string_expect_success (client, "This is a message", 0);
zmq_msg_t msg;
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, server, 0));
TEST_ASSERT_EQUAL_STRING ("World", zmq_msg_gets (&msg, "Hello"));
TEST_ASSERT_EQUAL_STRING ("DEALER", zmq_msg_gets (&msg, "Socket-Type"));
TEST_ASSERT_EQUAL_STRING ("anonymous", zmq_msg_gets (&msg, "User-Id"));
TEST_ASSERT_EQUAL_STRING ("127.0.0.1", zmq_msg_gets (&msg, "Peer-Address"));
TEST_ASSERT_NULL (zmq_msg_gets (&msg, "No Such"));
TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ());
zmq_msg_close (&msg);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
// Shutdown
teardown_test_context ();
// Wait until ZAP handler terminates
zmq_threadclose (zap_thread);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_metadata);
return UNITY_END ();
}

244
vendor/ZMQ/tests/test_mock_pub_sub.cpp vendored Normal file
View File

@@ -0,0 +1,244 @@
/*
Copyright (c) 2018 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.
static int get_monitor_event (void *monitor_)
{
for (int i = 0; i < 2; i++) {
// First frame in message contains event number and value
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
if (zmq_msg_recv (&msg, monitor_, ZMQ_DONTWAIT) == -1) {
msleep (SETTLE_TIME);
continue; // Interrupted, presumably
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
uint8_t *data = static_cast<uint8_t *> (zmq_msg_data (&msg));
uint16_t event = *reinterpret_cast<uint16_t *> (data);
// Second frame in message contains event address
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
if (zmq_msg_recv (&msg, monitor_, 0) == -1) {
return -1; // Interrupted, presumably
}
TEST_ASSERT_FALSE (zmq_msg_more (&msg));
return event;
}
return -1;
}
static void recv_with_retry (fd_t fd_, char *buffer_, int bytes_)
{
int received = 0;
while (true) {
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
recv (fd_, buffer_ + received, bytes_ - received, 0));
TEST_ASSERT_GREATER_THAN_INT (0, rc);
received += rc;
TEST_ASSERT_LESS_OR_EQUAL_INT (bytes_, received);
if (received == bytes_)
break;
}
}
static void mock_handshake (fd_t fd_, bool sub_command, bool mock_pub)
{
char buffer[128];
memset (buffer, 0, sizeof (buffer));
memcpy (buffer, zmtp_greeting_null, sizeof (zmtp_greeting_null));
// Mock ZMTP 3.1 which uses commands
if (sub_command) {
buffer[11] = 1;
}
int rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd_, buffer, 64, 0));
TEST_ASSERT_EQUAL_INT (64, rc);
recv_with_retry (fd_, buffer, 64);
if (!mock_pub) {
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
fd_, (const char *) zmtp_ready_sub, sizeof (zmtp_ready_sub), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_sub), rc);
} else {
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (
fd_, (const char *) zmtp_ready_xpub, sizeof (zmtp_ready_xpub), 0));
TEST_ASSERT_EQUAL_INT (sizeof (zmtp_ready_xpub), rc);
}
// greeting - XPUB has one extra byte
memset (buffer, 0, sizeof (buffer));
recv_with_retry (fd_, buffer,
mock_pub ? sizeof (zmtp_ready_sub)
: sizeof (zmtp_ready_xpub));
}
static void prep_server_socket (void **server_out_,
void **mon_out_,
char *endpoint_,
size_t ep_length_,
int socket_type)
{
// We'll be using this socket in raw mode
void *server = test_context_socket (socket_type);
int value = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_LINGER, &value, sizeof (value)));
bind_loopback_ipv4 (server, endpoint_, ep_length_);
// Create and connect a socket for collecting monitor events on xpub
void *server_mon = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
server, "inproc://monitor-dealer",
ZMQ_EVENT_CONNECTED | ZMQ_EVENT_DISCONNECTED | ZMQ_EVENT_ACCEPTED));
// Connect to the inproc endpoint so we'll get events
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (server_mon, "inproc://monitor-dealer"));
*server_out_ = server;
*mon_out_ = server_mon;
}
static void test_mock_pub_sub (bool sub_command_, bool mock_pub_)
{
int rc;
char my_endpoint[MAX_SOCKET_STRING];
void *server, *server_mon;
prep_server_socket (&server, &server_mon, my_endpoint, MAX_SOCKET_STRING,
mock_pub_ ? ZMQ_SUB : ZMQ_XPUB);
fd_t s = connect_socket (my_endpoint);
// Mock a ZMTP 3 client so we can forcibly try sub commands
mock_handshake (s, sub_command_, mock_pub_);
// By now everything should report as connected
rc = get_monitor_event (server_mon);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_ACCEPTED, rc);
char buffer[32];
memset (buffer, 0, sizeof (buffer));
if (mock_pub_) {
rc = zmq_setsockopt (server, ZMQ_SUBSCRIBE, "A", 1);
TEST_ASSERT_EQUAL_INT (0, rc);
// SUB binds, let its state machine run
// Because zeromq attach the pipe after the handshake, we need more time here before we can run the state-machine
msleep (1);
zmq_recv (server, buffer, 16, ZMQ_DONTWAIT);
if (sub_command_) {
recv_with_retry (s, buffer, 13);
TEST_ASSERT_EQUAL_INT (0,
memcmp (buffer, "\4\xb\x9SUBSCRIBEA", 13));
} else {
recv_with_retry (s, buffer, 4);
TEST_ASSERT_EQUAL_INT (0, memcmp (buffer, "\0\2\1A", 4));
}
memcpy (buffer, "\0\4ALOL", 6);
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (send (s, buffer, 6, 0));
TEST_ASSERT_EQUAL_INT (6, rc);
memset (buffer, 0, sizeof (buffer));
rc = zmq_recv (server, buffer, 4, 0);
TEST_ASSERT_EQUAL_INT (4, rc);
TEST_ASSERT_EQUAL_INT (0, memcmp (buffer, "ALOL", 4));
} else {
if (sub_command_) {
const uint8_t sub[13] = {4, 11, 9, 'S', 'U', 'B', 'S',
'C', 'R', 'I', 'B', 'E', 'A'};
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (s, (const char *) sub, 13, 0));
TEST_ASSERT_EQUAL_INT (13, rc);
} else {
const uint8_t sub[4] = {0, 2, 1, 'A'};
rc = TEST_ASSERT_SUCCESS_RAW_ERRNO (
send (s, (const char *) sub, 4, 0));
TEST_ASSERT_EQUAL_INT (4, rc);
}
rc = zmq_recv (server, buffer, 2, 0);
TEST_ASSERT_EQUAL_INT (2, rc);
TEST_ASSERT_EQUAL_INT (0, memcmp (buffer, "\1A", 2));
rc = zmq_send (server, "ALOL", 4, 0);
TEST_ASSERT_EQUAL_INT (4, rc);
memset (buffer, 0, sizeof (buffer));
recv_with_retry (s, buffer, 6);
TEST_ASSERT_EQUAL_INT (0, memcmp (buffer, "\0\4ALOL", 6));
}
close (s);
test_context_socket_close (server);
test_context_socket_close (server_mon);
}
void test_mock_sub_command ()
{
test_mock_pub_sub (true, false);
}
void test_mock_sub_legacy ()
{
test_mock_pub_sub (false, false);
}
void test_mock_pub_command ()
{
test_mock_pub_sub (true, true);
}
void test_mock_pub_legacy ()
{
test_mock_pub_sub (false, true);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_mock_sub_command);
RUN_TEST (test_mock_sub_legacy);
RUN_TEST (test_mock_pub_command);
RUN_TEST (test_mock_pub_legacy);
return UNITY_END ();
}

463
vendor/ZMQ/tests/test_monitor.cpp vendored Normal file
View File

@@ -0,0 +1,463 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_monitoring.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_monitor_invalid_protocol_fails ()
{
void *client = test_context_socket (ZMQ_DEALER);
// Socket monitoring only works over inproc://
TEST_ASSERT_FAILURE_ERRNO (
EPROTONOSUPPORT, zmq_socket_monitor (client, "tcp://127.0.0.1:*", 0));
#ifdef ZMQ_EVENT_PIPES_STATS
// Stats command needs to be called on a valid socket with monitoring
// enabled
TEST_ASSERT_FAILURE_ERRNO (ENOTSOCK, zmq_socket_monitor_pipes_stats (NULL));
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_socket_monitor_pipes_stats (client));
#endif
test_context_socket_close_zero_linger (client);
}
void test_monitor_basic ()
{
char my_endpoint[MAX_SOCKET_STRING];
// We'll monitor these two sockets
void *client = test_context_socket (ZMQ_DEALER);
void *server = test_context_socket (ZMQ_DEALER);
// Monitor all events on client and server sockets
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (client, "inproc://monitor-client", ZMQ_EVENT_ALL));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (server, "inproc://monitor-server", ZMQ_EVENT_ALL));
// Create two sockets for collecting monitor events
void *client_mon = test_context_socket (ZMQ_PAIR);
void *server_mon = test_context_socket (ZMQ_PAIR);
// Connect these to the inproc endpoints so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (client_mon, "inproc://monitor-client"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (server_mon, "inproc://monitor-server"));
// Now do a basic ping test
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
// Close client and server
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
// Now collect and check events from both sockets
int event = get_monitor_event (client_mon, NULL, NULL);
if (event == ZMQ_EVENT_CONNECT_DELAYED)
event = get_monitor_event (client_mon, NULL, NULL);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_CONNECTED, event);
expect_monitor_event (client_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
event = get_monitor_event (client_mon, NULL, NULL);
if (event == ZMQ_EVENT_DISCONNECTED) {
expect_monitor_event (client_mon, ZMQ_EVENT_CONNECT_RETRIED);
expect_monitor_event (client_mon, ZMQ_EVENT_MONITOR_STOPPED);
} else
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_MONITOR_STOPPED, event);
// This is the flow of server events
expect_monitor_event (server_mon, ZMQ_EVENT_LISTENING);
expect_monitor_event (server_mon, ZMQ_EVENT_ACCEPTED);
expect_monitor_event (server_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
event = get_monitor_event (server_mon, NULL, NULL);
// Sometimes the server sees the client closing before it gets closed.
if (event != ZMQ_EVENT_DISCONNECTED) {
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_CLOSED, event);
event = get_monitor_event (server_mon, NULL, NULL);
}
if (event != ZMQ_EVENT_DISCONNECTED) {
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_MONITOR_STOPPED, event);
}
// TODO: When not waiting until the monitor stopped, the I/O thread runs
// into some deadlock. This must be fixed, but until it is fixed, we wait
// here in order to have more reliable test execution.
while (event != ZMQ_EVENT_MONITOR_STOPPED) {
event = get_monitor_event (server_mon, NULL, NULL);
}
// Close down the sockets
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (client_mon);
test_context_socket_close_zero_linger (server_mon);
}
#if (defined ZMQ_CURRENT_EVENT_VERSION && ZMQ_CURRENT_EVENT_VERSION >= 2) \
|| (defined ZMQ_CURRENT_EVENT_VERSION \
&& ZMQ_CURRENT_EVENT_VERSION_DRAFT >= 2)
void test_monitor_versioned_invalid_socket_type ()
{
void *client = test_context_socket (ZMQ_DEALER);
// Socket monitoring only works with ZMQ_PAIR, ZMQ_PUB and ZMQ_PUSH.
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_socket_monitor_versioned (
client, "inproc://invalid-socket-type", 0, 2, ZMQ_CLIENT));
test_context_socket_close_zero_linger (client);
}
void test_monitor_versioned_basic (bind_function_t bind_function_,
const char *expected_prefix_,
int type_)
{
char server_endpoint[MAX_SOCKET_STRING];
char client_mon_endpoint[MAX_SOCKET_STRING];
char server_mon_endpoint[MAX_SOCKET_STRING];
// Create a unique endpoint for each call so we don't have
// to wait for the sockets to unbind.
snprintf (client_mon_endpoint, MAX_SOCKET_STRING, "inproc://client%s%d",
expected_prefix_, type_);
snprintf (server_mon_endpoint, MAX_SOCKET_STRING, "inproc://server%s%d",
expected_prefix_, type_);
// We'll monitor these two sockets
void *client = test_context_socket (ZMQ_DEALER);
void *server = test_context_socket (ZMQ_DEALER);
// Monitor all events on client and server sockets
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor_versioned (
client, client_mon_endpoint, ZMQ_EVENT_ALL_V2, 2, type_));
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor_versioned (
server, server_mon_endpoint, ZMQ_EVENT_ALL_V2, 2, type_));
// Choose the appropriate consumer socket type.
int mon_type = ZMQ_PAIR;
switch (type_) {
case ZMQ_PAIR:
mon_type = ZMQ_PAIR;
break;
case ZMQ_PUSH:
mon_type = ZMQ_PULL;
break;
case ZMQ_PUB:
mon_type = ZMQ_SUB;
break;
}
// Create two sockets for collecting monitor events
void *client_mon = test_context_socket (mon_type);
void *server_mon = test_context_socket (mon_type);
// Additionally subscribe to all events if a PUB socket is used.
if (type_ == ZMQ_PUB) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client_mon, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_mon, ZMQ_SUBSCRIBE, "", 0));
}
// Connect these to the inproc endpoints so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_mon, client_mon_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (server_mon, server_mon_endpoint));
// Now do a basic ping test
bind_function_ (server, server_endpoint, sizeof server_endpoint);
int ipv6;
size_t ipv6_size = sizeof (ipv6);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (server, ZMQ_IPV6, &ipv6, &ipv6_size));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_IPV6, &ipv6, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, server_endpoint));
bounce (server, client);
// Close client and server
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
char *client_local_address = NULL;
char *client_remote_address = NULL;
// Now collect and check events from both sockets
int64_t event = get_monitor_event_v2 (
client_mon, NULL, &client_local_address, &client_remote_address);
if (event == ZMQ_EVENT_CONNECT_DELAYED) {
free (client_local_address);
free (client_remote_address);
event = get_monitor_event_v2 (client_mon, NULL, &client_local_address,
&client_remote_address);
}
TEST_ASSERT_EQUAL (ZMQ_EVENT_CONNECTED, event);
TEST_ASSERT_EQUAL_STRING (server_endpoint, client_remote_address);
TEST_ASSERT_EQUAL_STRING_LEN (expected_prefix_, client_local_address,
strlen (expected_prefix_));
TEST_ASSERT_NOT_EQUAL (
0, strcmp (client_local_address, client_remote_address));
expect_monitor_event_v2 (client_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED,
client_local_address, client_remote_address);
event = get_monitor_event_v2 (client_mon, NULL, NULL, NULL);
if (event == ZMQ_EVENT_DISCONNECTED) {
expect_monitor_event_v2 (client_mon, ZMQ_EVENT_CONNECT_RETRIED,
client_local_address, client_remote_address);
expect_monitor_event_v2 (client_mon, ZMQ_EVENT_MONITOR_STOPPED, "", "");
} else
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_MONITOR_STOPPED, event);
// This is the flow of server events
expect_monitor_event_v2 (server_mon, ZMQ_EVENT_LISTENING,
client_remote_address, "");
expect_monitor_event_v2 (server_mon, ZMQ_EVENT_ACCEPTED,
client_remote_address, client_local_address);
expect_monitor_event_v2 (server_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED,
client_remote_address, client_local_address);
event = get_monitor_event_v2 (server_mon, NULL, NULL, NULL);
// Sometimes the server sees the client closing before it gets closed.
if (event != ZMQ_EVENT_DISCONNECTED) {
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_CLOSED, event);
event = get_monitor_event_v2 (server_mon, NULL, NULL, NULL);
}
if (event != ZMQ_EVENT_DISCONNECTED) {
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_MONITOR_STOPPED, event);
}
// TODO: When not waiting until the monitor stopped, the I/O thread runs
// into some deadlock. This must be fixed, but until it is fixed, we wait
// here in order to have more reliable test execution.
while (event != ZMQ_EVENT_MONITOR_STOPPED) {
event = get_monitor_event_v2 (server_mon, NULL, NULL, NULL);
}
free (client_local_address);
free (client_remote_address);
// Close down the sockets
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (client_mon);
test_context_socket_close_zero_linger (server_mon);
}
void test_monitor_versioned_basic_tcp_ipv4 ()
{
static const char prefix[] = "tcp://127.0.0.1:";
test_monitor_versioned_basic (bind_loopback_ipv4, prefix, ZMQ_PAIR);
test_monitor_versioned_basic (bind_loopback_ipv4, prefix, ZMQ_PUB);
test_monitor_versioned_basic (bind_loopback_ipv4, prefix, ZMQ_PUSH);
}
void test_monitor_versioned_basic_tcp_ipv6 ()
{
static const char prefix[] = "tcp://[::1]:";
test_monitor_versioned_basic (bind_loopback_ipv6, prefix, ZMQ_PAIR);
test_monitor_versioned_basic (bind_loopback_ipv6, prefix, ZMQ_PUB);
test_monitor_versioned_basic (bind_loopback_ipv6, prefix, ZMQ_PUSH);
}
void test_monitor_versioned_basic_ipc ()
{
static const char prefix[] = "ipc://";
test_monitor_versioned_basic (bind_loopback_ipc, prefix, ZMQ_PAIR);
test_monitor_versioned_basic (bind_loopback_ipc, prefix, ZMQ_PUB);
test_monitor_versioned_basic (bind_loopback_ipc, prefix, ZMQ_PUSH);
}
void test_monitor_versioned_basic_tipc ()
{
static const char prefix[] = "tipc://";
test_monitor_versioned_basic (bind_loopback_tipc, prefix, ZMQ_PAIR);
test_monitor_versioned_basic (bind_loopback_tipc, prefix, ZMQ_PUB);
test_monitor_versioned_basic (bind_loopback_tipc, prefix, ZMQ_PUSH);
}
#ifdef ZMQ_EVENT_PIPES_STATS
void test_monitor_versioned_stats (bind_function_t bind_function_,
const char *expected_prefix_)
{
char server_endpoint[MAX_SOCKET_STRING];
const int pulls_count = 4;
void *pulls[pulls_count];
// We'll monitor these two sockets
void *push = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor_versioned (
push, "inproc://monitor-push", ZMQ_EVENT_PIPES_STATS, 2, ZMQ_PAIR));
// Should fail if there are no pipes to monitor
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_socket_monitor_pipes_stats (push));
void *push_mon = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (push_mon, "inproc://monitor-push"));
// Set lower HWM - queues will be filled so we should see it in the stats
int send_hwm = 500;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (push, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)));
// Set very low TCP buffers so that messages cannot be stored in-flight
const int tcp_buffer_size = 4096;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
push, ZMQ_SNDBUF, &tcp_buffer_size, sizeof (tcp_buffer_size)));
bind_function_ (push, server_endpoint, sizeof (server_endpoint));
int ipv6;
size_t ipv6_size = sizeof (ipv6);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (push, ZMQ_IPV6, &ipv6, &ipv6_size));
for (int i = 0; i < pulls_count; ++i) {
pulls[i] = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pulls[i], ZMQ_IPV6, &ipv6, sizeof (int)));
int timeout_ms = 10;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
pulls[i], ZMQ_RCVTIMEO, &timeout_ms, sizeof (timeout_ms)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pulls[i], ZMQ_RCVHWM, &send_hwm, sizeof (send_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
pulls[i], ZMQ_RCVBUF, &tcp_buffer_size, sizeof (tcp_buffer_size)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pulls[i], server_endpoint));
}
// Send until we block
int send_count = 0;
// Saturate the TCP buffers too
char data[tcp_buffer_size * 2];
memset (data, 0, sizeof (data));
// Saturate all pipes - send + receive - on all connections
while (send_count < send_hwm * 2 * pulls_count) {
TEST_ASSERT_EQUAL_INT (sizeof (data),
zmq_send (push, data, sizeof (data), 0));
++send_count;
}
// Drain one of the pulls - doesn't matter how many messages, at least one
send_count = send_count / 4;
do {
zmq_recv (pulls[0], data, sizeof (data), 0);
--send_count;
} while (send_count > 0);
// To kick the application thread, do a dummy getsockopt - users here
// should use the monitor and the other sockets in a poll.
unsigned long int dummy;
size_t dummy_size = sizeof (dummy);
msleep (SETTLE_TIME);
// Note that the pipe stats on the sender will not get updated until the
// receiver has processed at least lwm ((hwm + 1) / 2) messages AND until
// the application thread has ran through the mailbox, as the update is
// delivered via a message (send_activate_write)
zmq_getsockopt (push, ZMQ_EVENTS, &dummy, &dummy_size);
// Ask for stats and check that they match
zmq_socket_monitor_pipes_stats (push);
msleep (SETTLE_TIME);
zmq_getsockopt (push, ZMQ_EVENTS, &dummy, &dummy_size);
for (int i = 0; i < pulls_count; ++i) {
char *push_local_address = NULL;
char *push_remote_address = NULL;
uint64_t queue_stat[2];
int64_t event = get_monitor_event_v2 (
push_mon, queue_stat, &push_local_address, &push_remote_address);
TEST_ASSERT_EQUAL_STRING (server_endpoint, push_local_address);
TEST_ASSERT_EQUAL_STRING_LEN (expected_prefix_, push_remote_address,
strlen (expected_prefix_));
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_PIPES_STATS, event);
TEST_ASSERT_EQUAL_INT (i == 0 ? 0 : send_hwm, queue_stat[0]);
TEST_ASSERT_EQUAL_INT (0, queue_stat[1]);
free (push_local_address);
free (push_remote_address);
}
// Close client and server
test_context_socket_close_zero_linger (push_mon);
test_context_socket_close_zero_linger (push);
for (int i = 0; i < pulls_count; ++i)
test_context_socket_close_zero_linger (pulls[i]);
}
void test_monitor_versioned_stats_tcp_ipv4 ()
{
static const char prefix[] = "tcp://127.0.0.1:";
test_monitor_versioned_stats (bind_loopback_ipv4, prefix);
}
void test_monitor_versioned_stats_tcp_ipv6 ()
{
static const char prefix[] = "tcp://[::1]:";
test_monitor_versioned_stats (bind_loopback_ipv6, prefix);
}
void test_monitor_versioned_stats_ipc ()
{
static const char prefix[] = "ipc://";
test_monitor_versioned_stats (bind_loopback_ipc, prefix);
}
#endif // ZMQ_EVENT_PIPES_STATS
#endif
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_monitor_invalid_protocol_fails);
RUN_TEST (test_monitor_basic);
#if (defined ZMQ_CURRENT_EVENT_VERSION && ZMQ_CURRENT_EVENT_VERSION >= 2) \
|| (defined ZMQ_CURRENT_EVENT_VERSION \
&& ZMQ_CURRENT_EVENT_VERSION_DRAFT >= 2)
RUN_TEST (test_monitor_versioned_invalid_socket_type);
RUN_TEST (test_monitor_versioned_basic_tcp_ipv4);
RUN_TEST (test_monitor_versioned_basic_tcp_ipv6);
RUN_TEST (test_monitor_versioned_basic_ipc);
RUN_TEST (test_monitor_versioned_basic_tipc);
#ifdef ZMQ_EVENT_PIPES_STATS
RUN_TEST (test_monitor_versioned_stats_tcp_ipv4);
RUN_TEST (test_monitor_versioned_stats_tcp_ipv6);
RUN_TEST (test_monitor_versioned_stats_ipc);
#endif
#endif
return UNITY_END ();
}

126
vendor/ZMQ/tests/test_msg_ffn.cpp vendored Normal file
View File

@@ -0,0 +1,126 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void ffn (void *data_, void *hint_)
{
// Signal that ffn has been called by writing "freed" to hint
(void) data_; // Suppress 'unused' warnings at compile time
memcpy (hint_, (void *) "freed", 5);
}
void test_msg_init_ffn ()
{
// Create the infrastructure
char my_endpoint[MAX_SOCKET_STRING];
void *router = test_context_socket (ZMQ_ROUTER);
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
void *dealer = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));
// Test that creating and closing a message triggers ffn
zmq_msg_t msg;
char hint[5];
char data[255];
memset (data, 0, 255);
memcpy (data, (void *) "data", 4);
memcpy (hint, (void *) "hint", 4);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
msleep (SETTLE_TIME);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
memcpy (hint, (void *) "hint", 4);
// Making and closing a copy triggers ffn
zmq_msg_t msg2;
zmq_msg_init (&msg2);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_copy (&msg2, &msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
msleep (SETTLE_TIME);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
memcpy (hint, (void *) "hint", 4);
// Test that sending a message triggers ffn
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint));
zmq_msg_send (&msg, dealer, 0);
char buf[255];
TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (router, buf, 255, 0));
TEST_ASSERT_EQUAL_INT (255, zmq_recv (router, buf, 255, 0));
TEST_ASSERT_EQUAL_STRING_LEN (data, buf, 4);
msleep (SETTLE_TIME);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
memcpy (hint, (void *) "hint", 4);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
// Sending a copy of a message triggers ffn
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg2));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_copy (&msg2, &msg));
zmq_msg_send (&msg, dealer, 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (router, buf, 255, 0));
TEST_ASSERT_EQUAL_INT (255, zmq_recv (router, buf, 255, 0));
TEST_ASSERT_EQUAL_STRING_LEN (data, buf, 4);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
msleep (SETTLE_TIME);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
// Deallocate the infrastructure.
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_msg_init_ffn);
return UNITY_END ();
}

117
vendor/ZMQ/tests/test_msg_flags.cpp vendored Normal file
View File

@@ -0,0 +1,117 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_more ()
{
// Create the infrastructure
void *sb = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
// Send 2-part message.
send_string_expect_success (sc, "A", ZMQ_SNDMORE);
send_string_expect_success (sc, "B", 0);
// Routing id comes first.
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0));
TEST_ASSERT_EQUAL_INT (1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_more (&msg)));
// Then the first part of the message body.
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
TEST_ASSERT_EQUAL_INT (1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_more (&msg)));
// And finally, the second part of the message body.
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, sb, 0)));
TEST_ASSERT_EQUAL_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_more (&msg)));
// Deallocate the infrastructure.
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_shared_refcounted ()
{
// Test ZMQ_SHARED property (case 1, refcounted messages)
zmq_msg_t msg_a;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_size (&msg_a, 1024)); // large enough to be a type_lmsg
// Message is not shared
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_get (&msg_a, ZMQ_SHARED));
zmq_msg_t msg_b;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg_b));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_copy (&msg_b, &msg_a));
// Message is now shared
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_get (&msg_b, ZMQ_SHARED)));
// cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg_a));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg_b));
}
void test_shared_const ()
{
zmq_msg_t msg_a;
// Test ZMQ_SHARED property (case 2, constant data messages)
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg_a, (void *) "TEST", 5, 0, 0));
// Message reports as shared
TEST_ASSERT_EQUAL_INT (
1, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_get (&msg_a, ZMQ_SHARED)));
// cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg_a));
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_more);
RUN_TEST (test_shared_refcounted);
RUN_TEST (test_shared_const);
return UNITY_END ();
}

86
vendor/ZMQ/tests/test_msg_init.cpp vendored Normal file
View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_msg_init ()
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
void test_msg_init_size ()
{
const char *data = "foobar";
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 6));
TEST_ASSERT_EQUAL_INT (6, zmq_msg_size (&msg));
memcpy (zmq_msg_data (&msg), data, 6);
TEST_ASSERT_EQUAL_STRING_LEN (data, zmq_msg_data (&msg), 6);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
zmq_msg_t msg2;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg2, 0));
TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg2));
}
void test_msg_init_buffer ()
{
const char *data = "foobar";
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_buffer (&msg, data, 6));
TEST_ASSERT_EQUAL_INT (6, zmq_msg_size (&msg));
TEST_ASSERT (data != zmq_msg_data (&msg));
TEST_ASSERT_EQUAL_STRING_LEN (data, zmq_msg_data (&msg), 6);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
zmq_msg_t msg2;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_buffer (&msg2, NULL, 0));
TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg2));
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_msg_init);
RUN_TEST (test_msg_init_size);
RUN_TEST (test_msg_init_buffer);
return UNITY_END ();
}

82
vendor/ZMQ/tests/test_pair_inproc.cpp vendored Normal file
View File

@@ -0,0 +1,82 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
void *sb;
void *sc;
void setUp ()
{
setup_test_context ();
sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
}
void tearDown ()
{
test_context_socket_close (sc);
test_context_socket_close (sb);
teardown_test_context ();
}
void test_roundtrip ()
{
bounce (sb, sc);
}
// TODO it appears that this has nothing to do with pair or inproc, and belongs somewhere else
void test_zmq_send_const ()
{
TEST_ASSERT_EQUAL_INT (3, TEST_ASSERT_SUCCESS_ERRNO (
zmq_send_const (sb, "foo", 3, ZMQ_SNDMORE)));
TEST_ASSERT_EQUAL_INT (
6, TEST_ASSERT_SUCCESS_ERRNO (zmq_send_const (sb, "foobar", 6, 0)));
recv_string_expect_success (sc, "foo", 0);
recv_string_expect_success (sc, "foobar", 0);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
RUN_TEST (test_zmq_send_const);
return UNITY_END ();
}

81
vendor/ZMQ/tests/test_pair_ipc.cpp vendored Normal file
View File

@@ -0,0 +1,81 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string>
SETUP_TEARDOWN_TESTCONTEXT
void test_roundtrip ()
{
char my_endpoint[256];
void *sb = test_context_socket (ZMQ_PAIR);
bind_loopback_ipc (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
static const char prefix[] = "ipc://";
void test_endpoint_too_long ()
{
std::string endpoint_too_long;
endpoint_too_long.append (prefix);
for (size_t i = 0; i < 108; ++i) {
endpoint_too_long.append ("a");
}
void *sb = test_context_socket (ZMQ_PAIR);
// TODO ENAMETOOLONG is not listed in the errors returned by zmq_bind,
// should this be EINVAL?
TEST_ASSERT_FAILURE_ERRNO (ENAMETOOLONG,
zmq_bind (sb, endpoint_too_long.data ()));
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
RUN_TEST (test_endpoint_too_long);
return UNITY_END ();
}

161
vendor/ZMQ/tests/test_pair_tcp.cpp vendored Normal file
View File

@@ -0,0 +1,161 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#if defined _WIN32
#include "../src/windows.hpp"
#endif
SETUP_TEARDOWN_TESTCONTEXT
typedef void (*extra_func_t) (void *socket_);
#ifdef ZMQ_BUILD_DRAFT
void set_sockopt_fastpath (void *socket)
{
int value = 1;
int rc =
zmq_setsockopt (socket, ZMQ_LOOPBACK_FASTPATH, &value, sizeof value);
assert (rc == 0);
}
#endif
void test_pair_tcp (extra_func_t extra_func_ = NULL)
{
void *sb = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sb);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_pair_tcp_regular ()
{
test_pair_tcp ();
}
void test_pair_tcp_connect_by_name ()
{
// all other tcp test cases bind to a loopback wildcard address, then
// retrieve the bound endpoint, which is numerical, and use that to
// connect. this test cases specifically uses "localhost" to connect
// to ensure that names are correctly resolved
void *sb = test_context_socket (ZMQ_PAIR);
char bound_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (sb, bound_endpoint, sizeof bound_endpoint);
// extract the bound port number
const char *pos = strrchr (bound_endpoint, ':');
TEST_ASSERT_NOT_NULL (pos);
const char connect_endpoint_prefix[] = "tcp://localhost";
char connect_endpoint[MAX_SOCKET_STRING];
strcpy (connect_endpoint, connect_endpoint_prefix);
strcat (connect_endpoint, pos);
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, connect_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
#ifdef ZMQ_BUILD_DRAFT
void test_pair_tcp_fastpath ()
{
test_pair_tcp (set_sockopt_fastpath);
}
#endif
#ifdef _WIN32
void test_io_completion_port ()
{
void *const s = test_context_socket (ZMQ_PAIR);
SOCKET fd;
size_t fd_size = sizeof fd;
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (s, ZMQ_FD, &fd, &fd_size));
::WSAPROTOCOL_INFO pi;
TEST_ASSERT_SUCCESS_RAW_ERRNO (
::WSADuplicateSocket (fd, ::GetCurrentProcessId (), &pi));
const SOCKET socket = ::WSASocket (pi.iAddressFamily /*AF_INET*/,
pi.iSocketType /*SOCK_STREAM*/,
pi.iProtocol /*IPPROTO_TCP*/, &pi, 0, 0);
const HANDLE iocp =
::CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL, 0, 0);
TEST_ASSERT_NOT_EQUAL (NULL, iocp);
const HANDLE res =
::CreateIoCompletionPort (reinterpret_cast<HANDLE> (socket), iocp, 0, 0);
TEST_ASSERT_NOT_EQUAL (NULL, res);
TEST_ASSERT_SUCCESS_RAW_ERRNO (closesocket (socket));
TEST_ASSERT_TRUE (CloseHandle (iocp));
test_context_socket_close (s);
}
#endif
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_pair_tcp_regular);
RUN_TEST (test_pair_tcp_connect_by_name);
#ifdef ZMQ_BUILD_DRAFT
RUN_TEST (test_pair_tcp_fastpath);
#endif
#ifdef _WIN32
RUN_TEST (test_io_completion_port);
#endif
return UNITY_END ();
}

View File

@@ -0,0 +1,80 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
typedef void (*extra_func_t) (void *socket_);
void set_sockopt_bind_to_device (void *socket)
{
const char device[] = "lo";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_BINDTODEVICE, &device, sizeof (device) - 1));
}
// TODO this is duplicated from test_pair_tcp
void test_pair_tcp (extra_func_t extra_func_ = NULL)
{
void *sb = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sb);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_PAIR);
if (extra_func_)
extra_func_ (sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void test_pair_tcp_bind_to_device ()
{
test_pair_tcp (set_sockopt_bind_to_device);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_pair_tcp_bind_to_device);
return UNITY_END ();
}

60
vendor/ZMQ/tests/test_pair_tipc.cpp vendored Normal file
View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_roundtrip ()
{
void *sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "tipc://{5560,0,0}"));
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "tipc://{5560,0}@0.0.0"));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main ()
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

64
vendor/ZMQ/tests/test_pair_vmci.cpp vendored Normal file
View File

@@ -0,0 +1,64 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <sstream>
#include <vmci_sockets.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_pair_vmci ()
{
std::stringstream s;
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
std::string endpoint = s.str ();
void *sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ()));
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_pair_vmci);
return UNITY_END ();
}

113
vendor/ZMQ/tests/test_peer.cpp vendored Normal file
View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_peer ()
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *peer1 = test_context_socket (ZMQ_PEER);
bind_loopback (peer1, false, my_endpoint, len);
void *peer2 = test_context_socket (ZMQ_PEER);
uint32_t peer1_routing_id = zmq_connect_peer (peer2, my_endpoint);
TEST_ASSERT_NOT_EQUAL (0, peer1_routing_id);
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 1));
char *data = static_cast<char *> (zmq_msg_data (&msg));
data[0] = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_set_routing_id (&msg, peer1_routing_id));
int rc = zmq_msg_send (&msg, peer2, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
}
uint32_t peer2_routing_id;
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
int rc = TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, peer1, 0));
TEST_ASSERT_EQUAL_INT (1, rc);
peer2_routing_id = zmq_msg_routing_id (&msg);
TEST_ASSERT_NOT_EQUAL (0, peer2_routing_id);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 1));
char *data = static_cast<char *> (zmq_msg_data (&msg));
data[0] = 2;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_set_routing_id (&msg, peer2_routing_id));
int rc = zmq_msg_send (&msg, peer1, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
}
{
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
int rc = zmq_msg_recv (&msg, peer2, 0);
TEST_ASSERT_EQUAL_INT (1, rc);
uint32_t routing_id = zmq_msg_routing_id (&msg);
TEST_ASSERT_EQUAL_UINT32 (peer1_routing_id, routing_id);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
}
test_context_socket_close (peer1);
test_context_socket_close (peer2);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_peer);
return UNITY_END ();
}

778
vendor/ZMQ/tests/test_poller.cpp vendored Normal file
View File

@@ -0,0 +1,778 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <limits.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
SETUP_TEARDOWN_TESTCONTEXT
fd_t get_fd (void *socket_)
{
fd_t fd;
size_t fd_size = sizeof fd;
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (socket_, ZMQ_FD, &fd, &fd_size));
return fd;
}
void test_null_poller_pointers_destroy_direct ()
{
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_destroy (NULL));
}
void test_null_poller_pointers_destroy_indirect ()
{
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_destroy (&null_poller));
}
void test_null_poller_pointers_size_direct ()
{
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_size (NULL));
}
void test_null_poller_pointers_size_indirect ()
{
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_size (&null_poller));
}
void test_null_poller_pointers_add_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_add (NULL, socket, NULL, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_add_indirect ()
{
void *null_poller = NULL;
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_poller_add (&null_poller, socket, NULL, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_modify_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_modify (NULL, socket, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_modify_indirect ()
{
void *null_poller = NULL;
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_poller_modify (&null_poller, socket, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_remove_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_remove (NULL, socket));
test_context_socket_close (socket);
}
void test_null_poller_pointers_remove_indirect ()
{
void *null_poller = NULL;
void *socket = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_remove (&null_poller, socket));
test_context_socket_close (socket);
}
void test_null_poller_pointers_add_fd_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_add_fd (NULL, fd, NULL, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_add_fd_indirect ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_poller_add_fd (&null_poller, fd, NULL, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_modify_fd_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_modify_fd (NULL, fd, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_modify_fd_indirect ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_poller_modify_fd (&null_poller, fd, ZMQ_POLLIN));
test_context_socket_close (socket);
}
void test_null_poller_pointers_remove_fd_direct ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_remove_fd (NULL, fd));
test_context_socket_close (socket);
}
void test_null_poller_pointers_remove_fd_indirect ()
{
void *socket = test_context_socket (ZMQ_PAIR);
const fd_t fd = get_fd (socket);
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_remove_fd (&null_poller, fd));
test_context_socket_close (socket);
}
void test_null_poller_pointers_wait_direct ()
{
zmq_poller_event_t event;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_wait (NULL, &event, 0));
}
void test_null_poller_pointers_wait_indirect ()
{
zmq_poller_event_t event;
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_wait (&null_poller, &event, 0));
}
void test_null_poller_pointers_wait_all_direct ()
{
zmq_poller_event_t event;
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_wait_all (NULL, &event, 1, 0));
}
void test_null_poller_pointers_wait_all_indirect ()
{
zmq_poller_event_t event;
void *null_poller = NULL;
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_poller_wait_all (&null_poller, &event, 1, 0));
}
void test_null_poller_pointer_poller_fd ()
{
void *null_poller = NULL;
fd_t fd;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_fd (&null_poller, &fd));
}
void test_null_socket_pointers ()
{
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
TEST_ASSERT_FAILURE_ERRNO (ENOTSOCK,
zmq_poller_add (poller, NULL, NULL, ZMQ_POLLIN));
TEST_ASSERT_FAILURE_ERRNO (ENOTSOCK,
zmq_poller_modify (poller, NULL, ZMQ_POLLIN));
TEST_ASSERT_FAILURE_ERRNO (ENOTSOCK, zmq_poller_remove (poller, NULL));
fd_t null_socket_fd = retired_fd;
TEST_ASSERT_FAILURE_ERRNO (
EBADF, zmq_poller_add_fd (poller, null_socket_fd, NULL, ZMQ_POLLIN));
TEST_ASSERT_FAILURE_ERRNO (
EBADF, zmq_poller_modify_fd (poller, null_socket_fd, ZMQ_POLLIN));
TEST_ASSERT_FAILURE_ERRNO (EBADF,
zmq_poller_remove_fd (poller, null_socket_fd));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
}
typedef void (*extra_poller_socket_func_t) (void *poller_, void *socket_);
void test_with_empty_poller (extra_poller_socket_func_t extra_func_)
{
void *socket = test_context_socket (ZMQ_PAIR);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
extra_func_ (poller, socket);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
test_context_socket_close (socket);
}
typedef void (*extra_poller_func_t) (void *poller_);
void test_with_valid_poller (extra_poller_func_t extra_func_)
{
void *socket = test_context_socket (ZMQ_PAIR);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN));
extra_func_ (poller);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
test_context_socket_close (socket);
}
void test_call_poller_fd_no_signaler ()
{
void *socket = test_context_socket (ZMQ_PAIR);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN));
fd_t fd;
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_poller_fd (poller, &fd));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
test_context_socket_close (socket);
}
void test_call_poller_fd ()
{
void *socket = test_context_socket (ZMQ_CLIENT);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN));
fd_t fd;
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_fd (poller, &fd));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
test_context_socket_close (socket);
}
void call_poller_wait_null_event_fails (void *poller_)
{
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_wait (poller_, NULL, 0));
}
void call_poller_wait_all_null_event_fails_event_count_nonzero (void *poller_)
{
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_wait_all (poller_, NULL, 1, 0));
}
void call_poller_wait_all_null_event_fails_event_count_zero (void *poller_)
{
#if 0
// TODO this causes an assertion, which is not consistent if the number
// of events may be 0, the pointer should be allowed to by NULL in that
// case too
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_wait_all (poller, NULL, 0, 0));
#endif
}
#define TEST_CASE_FUNC_PARAM(name, func) \
void test_##name () { func (name); }
TEST_CASE_FUNC_PARAM (call_poller_wait_null_event_fails, test_with_valid_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_null_event_fails_event_count_nonzero,
test_with_valid_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_null_event_fails_event_count_zero,
test_with_valid_poller)
void call_poller_size (void *poller_, void *socket_)
{
int rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller_, socket_, NULL, ZMQ_POLLIN));
rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 1);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_modify (poller_, socket_, 0));
rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 1);
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add_fd (poller_, plain_socket, NULL, ZMQ_POLLOUT));
rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove (poller_, socket_));
rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 1);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove_fd (poller_, plain_socket));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
rc = zmq_poller_size (poller_);
TEST_ASSERT_SUCCESS_ERRNO (rc);
TEST_ASSERT_EQUAL (rc, 0);
}
void call_poller_add_twice_fails (void *poller_, void *socket_)
{
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller_, socket_, NULL, ZMQ_POLLIN));
// attempt to add the same socket twice
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_add (poller_, socket_, NULL, ZMQ_POLLIN));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove (poller_, socket_));
}
void call_poller_remove_unregistered_fails (void *poller_, void *socket_)
{
// attempt to remove socket that is not present
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_poller_remove (poller_, socket_));
}
void call_poller_modify_unregistered_fails (void *poller_, void *socket_)
{
// attempt to modify socket that is not present
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_modify (poller_, socket_, ZMQ_POLLIN));
}
void call_poller_add_no_events (void *poller_, void *socket_)
{
// add a socket with no events initially (may be activated later with
// zmq_poller_modify)
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_add (poller_, socket_, NULL, 0));
// TODO test that no events are signalled
}
void call_poller_modify_no_events (void *poller_, void *socket_)
{
// deactivates all events for a socket temporarily (may be activated again
// later with zmq_poller_modify)
zmq_poller_add (poller_, socket_, NULL, ZMQ_POLLIN);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_modify (poller_, socket_, 0));
// TODO test that no events are signalled
}
void call_poller_add_fd_twice_fails (void *poller_, void * /*zeromq_socket*/)
{
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add_fd (poller_, plain_socket, NULL, ZMQ_POLLIN));
// attempt to add the same plain socket twice
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_add_fd (poller_, plain_socket, NULL, ZMQ_POLLIN));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove_fd (poller_, plain_socket));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
}
void call_poller_remove_fd_unregistered_fails (void *poller_,
void * /*zeromq_socket*/)
{
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
// attempt to remove plain socket that is not present
TEST_ASSERT_FAILURE_ERRNO (EINVAL,
zmq_poller_remove_fd (poller_, plain_socket));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
}
void call_poller_modify_fd_unregistered_fails (void *poller_,
void * /*zeromq_socket*/)
{
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
// attempt to remove plain socket that is not present
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_modify_fd (poller_, plain_socket, ZMQ_POLLIN));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
}
void call_poller_add_invalid_events_fails (void *poller_, void *zeromq_socket_)
{
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_add (poller_, zeromq_socket_, NULL, SHRT_MAX));
}
void call_poller_modify_invalid_events_fails (void *poller_,
void *zeromq_socket_)
{
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller_, zeromq_socket_, NULL, 0));
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_modify (poller_, zeromq_socket_, SHRT_MAX));
}
void call_poller_add_fd_invalid_events_fails (void *poller_,
void * /*zeromq_socket*/)
{
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_add_fd (poller_, plain_socket, NULL, SHRT_MAX));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
}
void call_poller_modify_fd_invalid_events_fails (void *poller_,
void * /*zeromq_socket*/)
{
fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add_fd (poller_, plain_socket, NULL, 0));
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_poller_modify_fd (poller_, plain_socket, SHRT_MAX));
TEST_ASSERT_SUCCESS_ERRNO (close (plain_socket));
}
TEST_CASE_FUNC_PARAM (call_poller_size, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_twice_fails, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_remove_unregistered_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_unregistered_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_no_events, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_no_events, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_fd_twice_fails, test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_remove_fd_unregistered_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_fd_unregistered_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_invalid_events_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_invalid_events_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_add_fd_invalid_events_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_modify_fd_invalid_events_fails,
test_with_empty_poller)
void call_poller_wait_empty_with_timeout_fails (void *poller_,
void * /*socket*/)
{
zmq_poller_event_t event;
// waiting on poller with no registered sockets should report error
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_poller_wait (poller_, &event, 0));
}
void call_poller_wait_empty_without_timeout_fails (void *poller_,
void * /*socket*/)
{
zmq_poller_event_t event;
// this would never be able to return since no socket was registered, and should yield an error
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_poller_wait (poller_, &event, -1));
}
void call_poller_wait_all_empty_negative_count_fails (void *poller_,
void * /*socket*/)
{
zmq_poller_event_t event;
TEST_ASSERT_FAILURE_ERRNO (EINVAL,
zmq_poller_wait_all (poller_, &event, -1, 0));
}
void call_poller_wait_all_empty_without_timeout_fails (void *poller_,
void * /*socket*/)
{
zmq_poller_event_t event;
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_poller_wait_all (poller_, &event, 0, 0));
}
void call_poller_wait_all_empty_with_timeout_fails (void *poller_,
void * /*socket*/)
{
zmq_poller_event_t event;
// this would never be able to return since no socket was registered, and should yield an error
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_wait_all (poller_, &event, 0, -1));
}
void call_poller_wait_all_inf_disabled_fails (void *poller_, void *socket_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_add (poller_, socket_, NULL, 0));
zmq_poller_event_t events[1];
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_poller_wait_all (poller_, events, 1, 0));
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_poller_wait_all (poller_, events, 1, -1));
}
TEST_CASE_FUNC_PARAM (call_poller_wait_empty_with_timeout_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_empty_without_timeout_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_empty_negative_count_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_empty_without_timeout_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_empty_with_timeout_fails,
test_with_empty_poller)
TEST_CASE_FUNC_PARAM (call_poller_wait_all_inf_disabled_fails,
test_with_empty_poller)
void test_poll_basic ()
{
// Create few sockets
void *vent = test_context_socket (ZMQ_PUSH);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (vent, my_endpoint, len);
void *sink = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sink, my_endpoint));
// Set up poller
void *poller = zmq_poller_new ();
// register sink
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_add (poller, sink, sink, ZMQ_POLLIN));
// Send a message
const char *vent_sink_msg = "H";
send_string_expect_success (vent, vent_sink_msg, 0);
// We expect a message only on the sink
zmq_poller_event_t event;
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_wait (poller, &event, -1));
TEST_ASSERT_EQUAL_PTR (sink, event.socket);
TEST_ASSERT_EQUAL_PTR (sink, event.user_data);
recv_string_expect_success (sink, vent_sink_msg, 0);
// We expect timed out
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_poller_wait (poller, &event, 0));
// Stop polling sink
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove (poller, sink));
// Clean up
test_context_socket_close (vent);
test_context_socket_close (sink);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
}
void test_poll_fd ()
{
// Create sockets
void *vent = test_context_socket (ZMQ_PUSH);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (vent, my_endpoint, len);
void *bowl = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (bowl, my_endpoint));
// Set up poller
void *poller = zmq_poller_new ();
// Check we can poll an FD
const fd_t fd = get_fd (bowl);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add_fd (poller, fd, bowl, ZMQ_POLLIN));
zmq_poller_event_t event;
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_wait (poller, &event, 500));
TEST_ASSERT_NULL (event.socket);
TEST_ASSERT_EQUAL (fd, event.fd);
TEST_ASSERT_EQUAL_PTR (bowl, event.user_data);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove_fd (poller, fd));
// Clean up
test_context_socket_close (vent);
test_context_socket_close (bowl);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
}
void test_poll_client_server ()
{
#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
// Create sockets
void *server = test_context_socket (ZMQ_SERVER);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, len);
void *client = test_context_socket (ZMQ_CLIENT);
// Set up poller
void *poller = zmq_poller_new ();
// Polling on thread safe sockets
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, server, NULL, ZMQ_POLLIN));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
const char *client_server_msg = "I";
send_string_expect_success (client, client_server_msg, 0);
zmq_poller_event_t event;
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_wait (poller, &event, 500));
TEST_ASSERT_EQUAL_PTR (server, event.socket);
TEST_ASSERT_NULL (event.user_data);
#ifndef _WIN32
TEST_ASSERT (event.fd == -1);
#endif
recv_string_expect_success (server, client_server_msg, 0);
// Polling on pollout
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_modify (poller, server, ZMQ_POLLOUT | ZMQ_POLLIN));
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_wait (poller, &event, 0));
TEST_ASSERT_EQUAL_PTR (server, event.socket);
TEST_ASSERT_NULL (event.user_data);
#ifndef _WIN32
TEST_ASSERT (event.fd == -1);
#endif
TEST_ASSERT_EQUAL_INT (ZMQ_POLLOUT, event.events);
// Stop polling server
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_remove (poller, server));
// Clean up
test_context_socket_close (server);
test_context_socket_close (client);
TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));
#endif
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_null_poller_pointers_destroy_direct);
RUN_TEST (test_null_poller_pointers_destroy_indirect);
RUN_TEST (test_null_poller_pointers_size_direct);
RUN_TEST (test_null_poller_pointers_size_indirect);
RUN_TEST (test_null_poller_pointers_add_direct);
RUN_TEST (test_null_poller_pointers_add_indirect);
RUN_TEST (test_null_poller_pointers_modify_direct);
RUN_TEST (test_null_poller_pointers_modify_indirect);
RUN_TEST (test_null_poller_pointers_remove_direct);
RUN_TEST (test_null_poller_pointers_remove_indirect);
RUN_TEST (test_null_poller_pointers_add_fd_direct);
RUN_TEST (test_null_poller_pointers_add_fd_indirect);
RUN_TEST (test_null_poller_pointers_modify_fd_direct);
RUN_TEST (test_null_poller_pointers_modify_fd_indirect);
RUN_TEST (test_null_poller_pointers_remove_fd_direct);
RUN_TEST (test_null_poller_pointers_remove_fd_indirect);
RUN_TEST (test_null_poller_pointers_wait_direct);
RUN_TEST (test_null_poller_pointers_wait_indirect);
RUN_TEST (test_null_poller_pointers_wait_all_direct);
RUN_TEST (test_null_poller_pointers_wait_all_indirect);
RUN_TEST (test_null_poller_pointer_poller_fd);
RUN_TEST (test_null_socket_pointers);
RUN_TEST (test_call_poller_wait_null_event_fails);
RUN_TEST (test_call_poller_wait_all_null_event_fails_event_count_nonzero);
RUN_TEST (test_call_poller_wait_all_null_event_fails_event_count_zero);
RUN_TEST (test_call_poller_size);
RUN_TEST (test_call_poller_add_twice_fails);
RUN_TEST (test_call_poller_remove_unregistered_fails);
RUN_TEST (test_call_poller_modify_unregistered_fails);
RUN_TEST (test_call_poller_add_no_events);
RUN_TEST (test_call_poller_modify_no_events);
RUN_TEST (test_call_poller_add_fd_twice_fails);
RUN_TEST (test_call_poller_remove_fd_unregistered_fails);
RUN_TEST (test_call_poller_modify_fd_unregistered_fails);
RUN_TEST (test_call_poller_add_invalid_events_fails);
RUN_TEST (test_call_poller_modify_invalid_events_fails);
RUN_TEST (test_call_poller_add_fd_invalid_events_fails);
RUN_TEST (test_call_poller_modify_fd_invalid_events_fails);
RUN_TEST (test_call_poller_wait_empty_with_timeout_fails);
RUN_TEST (test_call_poller_wait_empty_without_timeout_fails);
RUN_TEST (test_call_poller_wait_all_empty_negative_count_fails);
RUN_TEST (test_call_poller_wait_all_empty_without_timeout_fails);
RUN_TEST (test_call_poller_wait_all_empty_with_timeout_fails);
RUN_TEST (test_call_poller_wait_all_inf_disabled_fails);
RUN_TEST (test_call_poller_fd_no_signaler);
RUN_TEST (test_call_poller_fd);
RUN_TEST (test_poll_basic);
RUN_TEST (test_poll_fd);
RUN_TEST (test_poll_client_server);
return UNITY_END ();
}

113
vendor/ZMQ/tests/test_probe_router.cpp vendored Normal file
View File

@@ -0,0 +1,113 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_probe_router_router ()
{
// Create server and bind to endpoint
void *server = test_context_socket (ZMQ_ROUTER);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
// Create client and connect to server, doing a probe
void *client = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_ROUTING_ID, "X", 1));
int probe = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PROBE_ROUTER, &probe, sizeof (probe)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
// We expect a routing id=X + empty message from client
recv_string_expect_success (server, "X", 0);
unsigned char buffer[255];
TEST_ASSERT_EQUAL_INT (
0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (server, buffer, 255, 0)));
// Send a message to client now
send_string_expect_success (server, "X", ZMQ_SNDMORE);
send_string_expect_success (server, "Hello", 0);
// receive the routing ID, which is auto-generated in this case, since the
// peer did not set one explicitly
TEST_ASSERT_EQUAL_INT (
5, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (client, buffer, 255, 0)));
recv_string_expect_success (client, "Hello", 0);
test_context_socket_close (server);
test_context_socket_close (client);
}
void test_probe_router_dealer ()
{
// Create server and bind to endpoint
void *server = test_context_socket (ZMQ_ROUTER);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint));
// Create client and connect to server, doing a probe
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (client, ZMQ_ROUTING_ID, "X", 1));
int probe = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PROBE_ROUTER, &probe, sizeof (probe)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
// We expect a routing id=X + empty message from client
recv_string_expect_success (server, "X", 0);
unsigned char buffer[255];
TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (server, buffer, 255, 0));
// Send a message to client now
send_string_expect_success (server, "X", ZMQ_SNDMORE);
send_string_expect_success (server, "Hello", 0);
recv_string_expect_success (client, "Hello", 0);
test_context_socket_close (server);
test_context_socket_close (client);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_probe_router_router);
RUN_TEST (test_probe_router_dealer);
return UNITY_END ();
}

470
vendor/ZMQ/tests/test_proxy.cpp vendored Normal file
View File

@@ -0,0 +1,470 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
#define CONTENT_SIZE 13
#define CONTENT_SIZE_MAX 32
#define ROUTING_ID_SIZE 10
#define ROUTING_ID_SIZE_MAX 32
#define QT_WORKERS 5
#define QT_CLIENTS 3
#define is_verbose 0
struct thread_data
{
int id;
};
typedef struct
{
uint64_t msg_in;
uint64_t bytes_in;
uint64_t msg_out;
uint64_t bytes_out;
} zmq_socket_stats_t;
typedef struct
{
zmq_socket_stats_t frontend;
zmq_socket_stats_t backend;
} zmq_proxy_stats_t;
void *g_clients_pkts_out = NULL;
void *g_workers_pkts_out = NULL;
// Asynchronous client-to-server (DEALER to ROUTER) - pure libzmq
//
// While this example runs in a single process, that is to make
// it easier to start and stop the example. Each task may have its own
// context and conceptually acts as a separate process. To have this
// behaviour, it is necessary to replace the inproc transport of the
// control socket by a tcp transport.
// This is our client task
// It connects to the server, and then sends a request once per second
// It collects responses as they arrive, and it prints them out. We will
// run several client tasks in parallel, each with a different random ID.
static void client_task (void *db_)
{
const thread_data *const databag = static_cast<const thread_data *> (db_);
// Endpoint socket gets random port to avoid test failing when port in use
void *endpoint = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_NOT_NULL (endpoint);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (endpoint, ZMQ_LINGER, &linger, sizeof (linger)));
char endpoint_source[256];
sprintf (endpoint_source, "inproc://endpoint%d", databag->id);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (endpoint, endpoint_source));
char *my_endpoint = s_recv (endpoint);
TEST_ASSERT_NOT_NULL (my_endpoint);
void *client = zmq_socket (get_test_context (), ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (client);
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
char content[CONTENT_SIZE_MAX] = {};
// Set random routing id to make tracing easier
char routing_id[ROUTING_ID_SIZE] = {};
sprintf (routing_id, "%04X-%04X", rand () % 0xFFFF, rand () % 0xFFFF);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_ROUTING_ID, routing_id,
ROUTING_ID_SIZE)); // includes '\0' as an helper for printf
linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
zmq_pollitem_t items[] = {{client, 0, ZMQ_POLLIN, 0},
{control, 0, ZMQ_POLLIN, 0}};
int request_nbr = 0;
bool run = true;
bool keep_sending = true;
while (run) {
// Tick once per 200 ms, pulling in arriving messages
int centitick;
for (centitick = 0; centitick < 20; centitick++) {
zmq_poll (items, 2, 10);
if (items[0].revents & ZMQ_POLLIN) {
int rcvmore;
size_t sz = sizeof (rcvmore);
int rc = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (client, content, CONTENT_SIZE_MAX, 0));
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE, rc);
if (is_verbose)
printf (
"client receive - routing_id = %s content = %s\n",
routing_id, content);
// Check that message is still the same
TEST_ASSERT_EQUAL_STRING_LEN ("request #", content, 9);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (client, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
}
if (items[1].revents & ZMQ_POLLIN) {
int rc = zmq_recv (control, content, CONTENT_SIZE_MAX, 0);
if (rc > 0) {
content[rc] = 0; // NULL-terminate the command string
if (is_verbose)
printf (
"client receive - routing_id = %s command = %s\n",
routing_id, content);
if (memcmp (content, "TERMINATE", 9) == 0) {
run = false;
break;
}
if (memcmp (content, "STOP", 4) == 0) {
keep_sending = false;
break;
}
}
}
}
if (keep_sending) {
sprintf (content, "request #%03d", ++request_nbr); // CONTENT_SIZE
if (is_verbose)
printf ("client send - routing_id = %s request #%03d\n",
routing_id, request_nbr);
zmq_atomic_counter_inc (g_clients_pkts_out);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE,
zmq_send (client, content, CONTENT_SIZE, 0));
}
}
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (client));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (endpoint));
free (my_endpoint);
}
// This is our server task.
// It uses the multithreaded server model to deal requests out to a pool
// of workers and route replies back to clients. One worker can handle
// one request at a time but one client can talk to multiple workers at
// once.
static void server_worker (void * /*unused_*/);
void server_task (void * /*unused_*/)
{
// Frontend socket talks to clients over TCP
char my_endpoint[MAX_SOCKET_STRING];
void *frontend = zmq_socket (get_test_context (), ZMQ_ROUTER);
TEST_ASSERT_NOT_NULL (frontend);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (frontend, ZMQ_LINGER, &linger, sizeof (linger)));
bind_loopback_ipv4 (frontend, my_endpoint, sizeof my_endpoint);
// Backend socket talks to workers over inproc
void *backend = zmq_socket (get_test_context (), ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (backend);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (backend, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (backend, "inproc://backend"));
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control_proxy"));
// Launch pool of worker threads, precise number is not critical
int thread_nbr;
void *threads[5];
for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++)
threads[thread_nbr] = zmq_threadstart (&server_worker, NULL);
// Endpoint socket sends random port to avoid test failing when port in use
void *endpoint_receivers[QT_CLIENTS];
char endpoint_source[256];
for (int i = 0; i < QT_CLIENTS; ++i) {
endpoint_receivers[i] = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_NOT_NULL (endpoint_receivers[i]);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
endpoint_receivers[i], ZMQ_LINGER, &linger, sizeof (linger)));
sprintf (endpoint_source, "inproc://endpoint%d", i);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (endpoint_receivers[i], endpoint_source));
}
for (int i = 0; i < QT_CLIENTS; ++i) {
send_string_expect_success (endpoint_receivers[i], my_endpoint, 0);
}
// Connect backend to frontend via a proxy
TEST_ASSERT_SUCCESS_ERRNO (
zmq_proxy_steerable (frontend, backend, NULL, control));
for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++)
zmq_threadclose (threads[thread_nbr]);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (frontend));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (backend));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
for (int i = 0; i < QT_CLIENTS; ++i) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (endpoint_receivers[i]));
}
}
// Each worker task works on one request at a time and sends a random number
// of replies back, with random delays between replies:
// The comments in the first column, if suppressed, makes it a poller version
static void server_worker (void * /*unused_*/)
{
void *worker = zmq_socket (get_test_context (), ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (worker);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (worker, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (worker, "inproc://backend"));
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
char content[CONTENT_SIZE_MAX] =
{}; // bigger than what we need to check that
char routing_id[ROUTING_ID_SIZE_MAX] =
{}; // the size received is the size sent
bool run = true;
bool keep_sending = true;
while (run) {
int rc = zmq_recv (control, content, CONTENT_SIZE_MAX,
ZMQ_DONTWAIT); // usually, rc == -1 (no message)
if (rc > 0) {
content[rc] = 0; // NULL-terminate the command string
if (is_verbose)
printf ("server_worker receives command = %s\n", content);
if (memcmp (content, "TERMINATE", 9) == 0)
run = false;
if (memcmp (content, "STOP", 4) == 0)
keep_sending = false;
}
// The DEALER socket gives us the reply envelope and message
// if we don't poll, we have to use ZMQ_DONTWAIT, if we poll, we can block-receive with 0
rc = zmq_recv (worker, routing_id, ROUTING_ID_SIZE_MAX, ZMQ_DONTWAIT);
if (rc == ROUTING_ID_SIZE) {
rc = zmq_recv (worker, content, CONTENT_SIZE_MAX, 0);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE, rc);
if (is_verbose)
printf ("server receive - routing_id = %s content = %s\n",
routing_id, content);
// Send 0..4 replies back
if (keep_sending) {
int reply, replies = rand () % 5;
for (reply = 0; reply < replies; reply++) {
// Sleep for some fraction of a second
msleep (rand () % 10 + 1);
// Send message from server to client
if (is_verbose)
printf ("server send - routing_id = %s reply\n",
routing_id);
zmq_atomic_counter_inc (g_workers_pkts_out);
rc = zmq_send (worker, routing_id, ROUTING_ID_SIZE,
ZMQ_SNDMORE);
TEST_ASSERT_EQUAL_INT (ROUTING_ID_SIZE, rc);
rc = zmq_send (worker, content, CONTENT_SIZE, 0);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE, rc);
}
}
}
}
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (worker));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
}
uint64_t recv_stat (void *sock_, bool last_)
{
uint64_t res;
zmq_msg_t stats_msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&stats_msg));
TEST_ASSERT_EQUAL_INT (sizeof (uint64_t),
zmq_recvmsg (sock_, &stats_msg, 0));
memcpy (&res, zmq_msg_data (&stats_msg), zmq_msg_size (&stats_msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&stats_msg));
int more;
size_t moresz = sizeof more;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (sock_, ZMQ_RCVMORE, &more, &moresz));
TEST_ASSERT_TRUE ((last_ && !more) || (!last_ && more));
return res;
}
// Utility function to interrogate the proxy:
void check_proxy_stats (void *control_proxy_)
{
zmq_proxy_stats_t total_stats;
send_string_expect_success (control_proxy_, "STATISTICS", 0);
// first frame of the reply contains FRONTEND stats:
total_stats.frontend.msg_in = recv_stat (control_proxy_, false);
total_stats.frontend.bytes_in = recv_stat (control_proxy_, false);
total_stats.frontend.msg_out = recv_stat (control_proxy_, false);
total_stats.frontend.bytes_out = recv_stat (control_proxy_, false);
// second frame of the reply contains BACKEND stats:
total_stats.backend.msg_in = recv_stat (control_proxy_, false);
total_stats.backend.bytes_in = recv_stat (control_proxy_, false);
total_stats.backend.msg_out = recv_stat (control_proxy_, false);
total_stats.backend.bytes_out = recv_stat (control_proxy_, true);
// check stats
if (is_verbose) {
printf (
"frontend: pkts_in=%lu bytes_in=%lu pkts_out=%lu bytes_out=%lu\n",
static_cast<unsigned long int> (total_stats.frontend.msg_in),
static_cast<unsigned long int> (total_stats.frontend.bytes_in),
static_cast<unsigned long int> (total_stats.frontend.msg_out),
static_cast<unsigned long int> (total_stats.frontend.bytes_out));
printf (
"backend: pkts_in=%lu bytes_in=%lu pkts_out=%lu bytes_out=%lu\n",
static_cast<unsigned long int> (total_stats.backend.msg_in),
static_cast<unsigned long int> (total_stats.backend.bytes_in),
static_cast<unsigned long int> (total_stats.backend.msg_out),
static_cast<unsigned long int> (total_stats.backend.bytes_out));
printf ("clients sent out %d requests\n",
zmq_atomic_counter_value (g_clients_pkts_out));
printf ("workers sent out %d replies\n",
zmq_atomic_counter_value (g_workers_pkts_out));
}
TEST_ASSERT_EQUAL_UINT (
(unsigned) zmq_atomic_counter_value (g_clients_pkts_out),
total_stats.frontend.msg_in);
TEST_ASSERT_EQUAL_UINT (
(unsigned) zmq_atomic_counter_value (g_workers_pkts_out),
total_stats.frontend.msg_out);
TEST_ASSERT_EQUAL_UINT (
(unsigned) zmq_atomic_counter_value (g_workers_pkts_out),
total_stats.backend.msg_in);
TEST_ASSERT_EQUAL_UINT (
(unsigned) zmq_atomic_counter_value (g_clients_pkts_out),
total_stats.backend.msg_out);
}
// The main thread simply starts several clients and a server, and then
// waits for the server to finish.
void test_proxy ()
{
g_clients_pkts_out = zmq_atomic_counter_new ();
g_workers_pkts_out = zmq_atomic_counter_new ();
// Control socket receives terminate command from main over inproc
void *control = test_context_socket (ZMQ_PUB);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (control, "inproc://control"));
// Control socket receives terminate command from main over inproc
void *control_proxy = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (control_proxy, ZMQ_LINGER, &linger, sizeof (linger)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (control_proxy, "inproc://control_proxy"));
void *threads[QT_CLIENTS + 1];
struct thread_data databags[QT_CLIENTS + 1];
for (int i = 0; i < QT_CLIENTS; i++) {
databags[i].id = i;
threads[i] = zmq_threadstart (&client_task, &databags[i]);
}
threads[QT_CLIENTS] = zmq_threadstart (&server_task, NULL);
msleep (500); // Run for 500 ms then quit
if (is_verbose)
printf ("stopping all clients and server workers\n");
send_string_expect_success (control, "STOP", 0);
msleep (500); // Wait for all clients and workers to STOP
if (is_verbose)
printf ("retrieving stats from the proxy\n");
check_proxy_stats (control_proxy);
if (is_verbose)
printf ("shutting down all clients and server workers\n");
send_string_expect_success (control, "TERMINATE", 0);
if (is_verbose)
printf ("shutting down the proxy\n");
send_string_expect_success (control_proxy, "TERMINATE", 0);
test_context_socket_close (control);
test_context_socket_close (control_proxy);
for (int i = 0; i < QT_CLIENTS + 1; i++)
zmq_threadclose (threads[i]);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_proxy);
return UNITY_END ();
}

426
vendor/ZMQ/tests/test_proxy_hwm.cpp vendored Normal file
View File

@@ -0,0 +1,426 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#include <unity.h>
#include <assert.h>
#include <unistd.h>
//
// Asynchronous proxy test using ZMQ_XPUB_NODROP and HWM:
//
// Topology:
//
// XPUB SUB
// | |
// \-----> XSUB -> XPUB -----/
// ^^^^^^^^^^^^^^
// ZMQ proxy
//
// All connections use "inproc" transport and have artificially-low HWMs set.
// Then the PUB socket starts flooding the Proxy. The SUB is artificially slow
// at receiving messages.
// This scenario simulates what happens when a SUB is slower than
// its (X)PUB: since ZMQ_XPUB_NODROP=1, the XPUB will block and then
// also the (X)PUB socket will block.
// The exact number of the messages that go through before (X)PUB blocks depends
// on ZeroMQ internals and how the OS will schedule the different threads.
// In the meanwhile asking statistics to the Proxy must NOT be blocking.
//
#define HWM 10
#define NUM_BYTES_PER_MSG 50000
typedef struct
{
void *context;
const char *frontend_endpoint;
const char *backend_endpoint;
const char *control_endpoint;
void *subscriber_received_all;
} proxy_hwm_cfg_t;
static void lower_hwm (void *skt_)
{
int send_hwm = HWM;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (skt_, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (skt_, ZMQ_RCVHWM, &send_hwm, sizeof (send_hwm)));
}
static void publisher_thread_main (void *pvoid_)
{
const proxy_hwm_cfg_t *const cfg =
static_cast<const proxy_hwm_cfg_t *> (pvoid_);
void *pubsocket = zmq_socket (cfg->context, ZMQ_XPUB);
assert (pubsocket);
lower_hwm (pubsocket);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pubsocket, cfg->frontend_endpoint));
int optval = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pubsocket, ZMQ_XPUB_NODROP, &optval, sizeof (optval)));
// Wait before starting TX operations till 1 subscriber has subscribed
// (in this test there's 1 subscriber only)
const char subscription_to_all_topics[] = {1, 0};
recv_string_expect_success (pubsocket, subscription_to_all_topics, 0);
uint64_t send_count = 0;
while (true) {
zmq_msg_t msg;
int rc = zmq_msg_init_size (&msg, NUM_BYTES_PER_MSG);
assert (rc == 0);
/* Fill in message content with 'AAAAAA' */
memset (zmq_msg_data (&msg), 'A', NUM_BYTES_PER_MSG);
/* Send the message to the socket */
rc = zmq_msg_send (&msg, pubsocket, ZMQ_DONTWAIT);
if (rc != -1) {
send_count++;
} else {
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
break;
}
}
// VERIFY EXPECTED RESULTS
// EXPLANATION FOR TX TO BE CONSIDERED SUCCESSFUL:
// this test has 3 threads doing I/O across 2 queues. Depending on the scheduling,
// it might happen that 20, 30 or 40 messages go through before the pub blocks.
// That's because the receiver thread gets kicked once every (hwm_ + 1) / 2 sent
// messages (search for zeromq sources compute_lwm function).
// So depending on the scheduling of the second thread, the publisher might get one,
// two or three more batches in. The ceiling is 40 as there's 2 queues.
//
assert (4 * HWM >= send_count && 2 * HWM <= send_count);
// CLEANUP
zmq_close (pubsocket);
}
static void subscriber_thread_main (void *pvoid_)
{
const proxy_hwm_cfg_t *const cfg =
static_cast<const proxy_hwm_cfg_t *> (pvoid_);
void *subsocket = zmq_socket (cfg->context, ZMQ_SUB);
assert (subsocket);
lower_hwm (subsocket);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (subsocket, ZMQ_SUBSCRIBE, 0, 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (subsocket, cfg->backend_endpoint));
// receive all sent messages
uint64_t rxsuccess = 0;
bool success = true;
while (success) {
zmq_msg_t msg;
int rc = zmq_msg_init (&msg);
assert (rc == 0);
rc = zmq_msg_recv (&msg, subsocket, 0);
if (rc != -1) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
rxsuccess++;
// after receiving 1st message, set a finite timeout (default is infinite)
int timeout_ms = 100;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
subsocket, ZMQ_RCVTIMEO, &timeout_ms, sizeof (timeout_ms)));
} else {
break;
}
msleep (100);
}
// VERIFY EXPECTED RESULTS
// EXPLANATION FOR RX TO BE CONSIDERED SUCCESSFUL:
// see publisher thread why we have 3 possible outcomes as number of RX messages
assert (4 * HWM >= rxsuccess && 2 * HWM <= rxsuccess);
// INFORM THAT WE COMPLETED:
zmq_atomic_counter_inc (cfg->subscriber_received_all);
// CLEANUP
zmq_close (subsocket);
}
bool recv_stat (void *sock_, bool last_, uint64_t *res_)
{
zmq_msg_t stats_msg;
int rc = zmq_msg_init (&stats_msg);
assert (rc == 0);
rc = zmq_msg_recv (&stats_msg, sock_, 0); //ZMQ_DONTWAIT);
if (rc == -1 && errno == EAGAIN) {
rc = zmq_msg_close (&stats_msg);
assert (rc == 0);
return false; // cannot retrieve the stat
}
assert (rc == sizeof (uint64_t));
memcpy (res_, zmq_msg_data (&stats_msg), zmq_msg_size (&stats_msg));
rc = zmq_msg_close (&stats_msg);
assert (rc == 0);
int more;
size_t moresz = sizeof more;
rc = zmq_getsockopt (sock_, ZMQ_RCVMORE, &more, &moresz);
assert (rc == 0);
assert ((last_ && !more) || (!last_ && more));
return true;
}
// Utility function to interrogate the proxy:
typedef struct
{
uint64_t msg_in;
uint64_t bytes_in;
uint64_t msg_out;
uint64_t bytes_out;
} zmq_socket_stats_t;
typedef struct
{
zmq_socket_stats_t frontend;
zmq_socket_stats_t backend;
} zmq_proxy_stats_t;
bool check_proxy_stats (void *control_proxy_)
{
zmq_proxy_stats_t total_stats;
int rc;
rc = zmq_send (control_proxy_, "STATISTICS", 10, ZMQ_DONTWAIT);
assert (rc == 10 || (rc == -1 && errno == EAGAIN));
if (rc == -1 && errno == EAGAIN) {
return false;
}
// first frame of the reply contains FRONTEND stats:
if (!recv_stat (control_proxy_, false, &total_stats.frontend.msg_in)) {
return false;
}
recv_stat (control_proxy_, false, &total_stats.frontend.bytes_in);
recv_stat (control_proxy_, false, &total_stats.frontend.msg_out);
recv_stat (control_proxy_, false, &total_stats.frontend.bytes_out);
// second frame of the reply contains BACKEND stats:
recv_stat (control_proxy_, false, &total_stats.backend.msg_in);
recv_stat (control_proxy_, false, &total_stats.backend.bytes_in);
recv_stat (control_proxy_, false, &total_stats.backend.msg_out);
recv_stat (control_proxy_, true, &total_stats.backend.bytes_out);
return true;
}
static void proxy_stats_asker_thread_main (void *pvoid_)
{
const proxy_hwm_cfg_t *const cfg =
static_cast<const proxy_hwm_cfg_t *> (pvoid_);
// CONTROL REQ
void *control_req =
zmq_socket (cfg->context,
ZMQ_REQ); // this one can be used to send command to the proxy
assert (control_req);
// connect CONTROL-REQ: a socket to which send commands
int rc = zmq_connect (control_req, cfg->control_endpoint);
assert (rc == 0);
// IMPORTANT: by setting the tx/rx timeouts, we avoid getting blocked when interrogating a proxy which is
// itself blocked in a zmq_msg_send() on its XPUB socket having ZMQ_XPUB_NODROP=1!
int optval = 10;
rc = zmq_setsockopt (control_req, ZMQ_SNDTIMEO, &optval, sizeof (optval));
assert (rc == 0);
rc = zmq_setsockopt (control_req, ZMQ_RCVTIMEO, &optval, sizeof (optval));
assert (rc == 0);
optval = 10;
rc =
zmq_setsockopt (control_req, ZMQ_REQ_CORRELATE, &optval, sizeof (optval));
assert (rc == 0);
rc =
zmq_setsockopt (control_req, ZMQ_REQ_RELAXED, &optval, sizeof (optval));
assert (rc == 0);
// Start!
while (!zmq_atomic_counter_value (cfg->subscriber_received_all)) {
check_proxy_stats (control_req);
usleep (1000); // 1ms -> in best case we will get 1000updates/second
}
// Ask the proxy to exit: the subscriber has received all messages
rc = zmq_send (control_req, "TERMINATE", 9, 0);
assert (rc == 9);
zmq_close (control_req);
}
static void proxy_thread_main (void *pvoid_)
{
const proxy_hwm_cfg_t *const cfg =
static_cast<const proxy_hwm_cfg_t *> (pvoid_);
int rc;
// FRONTEND SUB
void *frontend_xsub = zmq_socket (
cfg->context,
ZMQ_XSUB); // the frontend is the one exposed to internal threads (INPROC)
assert (frontend_xsub);
lower_hwm (frontend_xsub);
// bind FRONTEND
rc = zmq_bind (frontend_xsub, cfg->frontend_endpoint);
assert (rc == 0);
// BACKEND PUB
void *backend_xpub = zmq_socket (
cfg->context,
ZMQ_XPUB); // the backend is the one exposed to the external world (TCP)
assert (backend_xpub);
int optval = 1;
rc =
zmq_setsockopt (backend_xpub, ZMQ_XPUB_NODROP, &optval, sizeof (optval));
assert (rc == 0);
lower_hwm (backend_xpub);
// bind BACKEND
rc = zmq_bind (backend_xpub, cfg->backend_endpoint);
assert (rc == 0);
// CONTROL REP
void *control_rep = zmq_socket (
cfg->context,
ZMQ_REP); // this one is used by the proxy to receive&reply to commands
assert (control_rep);
// bind CONTROL
rc = zmq_bind (control_rep, cfg->control_endpoint);
assert (rc == 0);
// start proxying!
zmq_proxy_steerable (frontend_xsub, backend_xpub, NULL, control_rep);
zmq_close (frontend_xsub);
zmq_close (backend_xpub);
zmq_close (control_rep);
}
// The main thread simply starts several clients and a server, and then
// waits for the server to finish.
int main (void)
{
setup_test_environment ();
void *context = zmq_ctx_new ();
assert (context);
// START ALL SECONDARY THREADS
proxy_hwm_cfg_t cfg;
cfg.context = context;
cfg.frontend_endpoint = "inproc://frontend";
cfg.backend_endpoint = "inproc://backend";
cfg.control_endpoint = "inproc://ctrl";
cfg.subscriber_received_all = zmq_atomic_counter_new ();
void *proxy = zmq_threadstart (&proxy_thread_main, (void *) &cfg);
assert (proxy != 0);
void *publisher = zmq_threadstart (&publisher_thread_main, (void *) &cfg);
assert (publisher != 0);
void *subscriber = zmq_threadstart (&subscriber_thread_main, (void *) &cfg);
assert (subscriber != 0);
void *asker =
zmq_threadstart (&proxy_stats_asker_thread_main, (void *) &cfg);
assert (asker != 0);
// CLEANUP
zmq_threadclose (publisher);
zmq_threadclose (subscriber);
zmq_threadclose (asker);
zmq_threadclose (proxy);
int rc = zmq_ctx_term (context);
assert (rc == 0);
zmq_atomic_counter_destroy (&cfg.subscriber_received_all);
return 0;
}

View File

@@ -0,0 +1,101 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
SETUP_TEARDOWN_TESTCONTEXT
// This is our server task.
// It runs a proxy with a single REP socket as both frontend and backend.
void server_task (void * /*unused_*/)
{
char my_endpoint[MAX_SOCKET_STRING];
void *rep = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_NOT_NULL (rep);
bind_loopback_ipv4 (rep, my_endpoint, sizeof my_endpoint);
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
send_string_expect_success (control, my_endpoint, 0);
// Use rep as both frontend and backend
TEST_ASSERT_SUCCESS_ERRNO (zmq_proxy_steerable (rep, rep, NULL, control));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (rep));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
}
// The main thread simply starts several clients and a server, and then
// waits for the server to finish.
void test_proxy_single_socket ()
{
void *server_thread = zmq_threadstart (&server_task, NULL);
// Control socket receives terminate command from main over inproc
void *control = test_context_socket (ZMQ_REP);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (control, "inproc://control"));
char *my_endpoint = s_recv (control);
TEST_ASSERT_NOT_NULL (my_endpoint);
// client socket pings proxy over tcp
void *req = test_context_socket (ZMQ_REQ);
TEST_ASSERT_NOT_NULL (req);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req, my_endpoint));
send_string_expect_success (req, "msg1", 0);
recv_string_expect_success (req, "msg1", 0);
send_string_expect_success (req, "msg22", 0);
recv_string_expect_success (req, "msg22", 0);
send_string_expect_success (control, "TERMINATE", 0);
test_context_socket_close (control);
test_context_socket_close (req);
free (my_endpoint);
zmq_threadclose (server_thread);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_proxy_single_socket);
return UNITY_END ();
}

View File

@@ -0,0 +1,116 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
SETUP_TEARDOWN_TESTCONTEXT
// This is a test for issue #1382. The server thread creates a SUB-PUSH
// steerable proxy. The main process then sends messages to the SUB
// but there is no pull on the other side, previously the proxy blocks
// in writing to the backend, preventing the proxy from terminating
void server_task (void * /*unused_*/)
{
char my_endpoint[MAX_SOCKET_STRING];
// Frontend socket talks to main process
void *frontend = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_NOT_NULL (frontend);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (frontend, ZMQ_SUBSCRIBE, "", 0));
bind_loopback_ipv4 (frontend, my_endpoint, sizeof my_endpoint);
// Nice socket which is never read
void *backend = zmq_socket (get_test_context (), ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (backend);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (backend, "tcp://127.0.0.1:*"));
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
send_string_expect_success (control, my_endpoint, 0);
// Connect backend to frontend via a proxy
TEST_ASSERT_SUCCESS_ERRNO (
zmq_proxy_steerable (frontend, backend, NULL, control));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (frontend));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (backend));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
}
// The main thread simply starts a basic steerable proxy server, publishes some messages, and then
// waits for the server to terminate.
void test_proxy_terminate ()
{
void *thread = zmq_threadstart (&server_task, NULL);
// Control socket receives terminate command from main over inproc
void *control = test_context_socket (ZMQ_REP);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (control, "inproc://control"));
char *my_endpoint = s_recv (control);
TEST_ASSERT_NOT_NULL (my_endpoint);
msleep (500); // Run for 500 ms
// Start a secondary publisher which writes data to the SUB-PUSH server socket
void *publisher = test_context_socket (ZMQ_PUB);
TEST_ASSERT_NOT_NULL (publisher);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (publisher, my_endpoint));
msleep (SETTLE_TIME);
send_string_expect_success (publisher, "This is a test", 0);
msleep (50);
send_string_expect_success (publisher, "This is a test", 0);
msleep (50);
send_string_expect_success (publisher, "This is a test", 0);
send_string_expect_success (control, "TERMINATE", 0);
test_context_socket_close (publisher);
test_context_socket_close (control);
free (my_endpoint);
zmq_threadclose (thread);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_proxy_terminate);
return UNITY_END ();
}

View File

@@ -0,0 +1,120 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test ()
{
// Create a publisher
void *pub = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, "inproc://soname"));
// Create two subscribers
void *sub1 = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub1, "inproc://soname"));
void *sub2 = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub2, "inproc://soname"));
// Subscribe pub1 to one prefix
// and pub2 to another prefix.
const char prefi_x1[] = "prefix1";
const char prefi_x2[] = "p2";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub1, ZMQ_SUBSCRIBE, prefi_x1, strlen (prefi_x1)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub2, ZMQ_SUBSCRIBE, prefi_x2, strlen (prefi_x2)));
// Send a message with the first prefix
send_string_expect_success (pub, prefi_x1, 0);
msleep (SETTLE_TIME);
// sub1 should receive it, but not sub2
recv_string_expect_success (sub1, prefi_x1, ZMQ_DONTWAIT);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (sub2, NULL, 0, ZMQ_DONTWAIT));
// Send a message with the second prefix
send_string_expect_success (pub, prefi_x2, 0);
msleep (SETTLE_TIME);
// sub2 should receive it, but not sub1
recv_string_expect_success (sub2, prefi_x2, ZMQ_DONTWAIT);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (sub1, NULL, 0, ZMQ_DONTWAIT));
// Now invert the matching
int invert = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (pub, ZMQ_INVERT_MATCHING, &invert, sizeof (invert)));
// ... on both sides, otherwise the SUB socket will filter the messages out
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub1, ZMQ_INVERT_MATCHING, &invert, sizeof (invert)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub2, ZMQ_INVERT_MATCHING, &invert, sizeof (invert)));
// Send a message with the first prefix
send_string_expect_success (pub, prefi_x1, 0);
msleep (SETTLE_TIME);
// sub2 should receive it, but not sub1
recv_string_expect_success (sub2, prefi_x1, ZMQ_DONTWAIT);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (sub1, NULL, 0, ZMQ_DONTWAIT));
// Send a message with the second prefix
send_string_expect_success (pub, prefi_x2, 0);
msleep (SETTLE_TIME);
// sub1 should receive it, but not sub2
recv_string_expect_success (sub1, prefi_x2, ZMQ_DONTWAIT);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (sub2, NULL, 0, ZMQ_DONTWAIT));
// Clean up.
test_context_socket_close (pub);
test_context_socket_close (sub1);
test_context_socket_close (sub2);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test);
return UNITY_END ();
}

82
vendor/ZMQ/tests/test_pubsub.cpp vendored Normal file
View File

@@ -0,0 +1,82 @@
/*
Copyright (c) 2007-2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test (const char *address)
{
// Create a publisher
void *publisher = test_context_socket (ZMQ_PUB);
char my_endpoint[MAX_SOCKET_STRING];
// Bind publisher
test_bind (publisher, address, my_endpoint, MAX_SOCKET_STRING);
// Create a subscriber
void *subscriber = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (subscriber, my_endpoint));
// Subscribe to all messages.
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE, "", 0));
// Wait a bit till the subscription gets to the publisher
msleep (SETTLE_TIME);
// Send an empty message
send_string_expect_success (publisher, "test", 0);
// Receive the message in the subscriber
recv_string_expect_success (subscriber, "test", 0);
// Clean up.
test_context_socket_close (publisher);
test_context_socket_close (subscriber);
}
void test_norm ()
{
#if defined ZMQ_HAVE_NORM
test ("norm://224.1.2.3:5556");
#else
TEST_IGNORE_MESSAGE ("libzmq without NORM, ignoring test");
#endif
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_norm);
return UNITY_END ();
}

555
vendor/ZMQ/tests/test_radio_dish.cpp vendored Normal file
View File

@@ -0,0 +1,555 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
// Helper macro to define the v4/v6 function pairs
#define MAKE_TEST_V4V6(_test) \
static void _test##_ipv4 () { _test (false); } \
\
static void _test##_ipv6 () \
{ \
if (!is_ipv6_available ()) { \
TEST_IGNORE_MESSAGE ("ipv6 is not available"); \
} \
_test (true); \
}
SETUP_TEARDOWN_TESTCONTEXT
void msg_send_expect_success (void *s_, const char *group_, const char *body_)
{
zmq_msg_t msg;
const size_t len = strlen (body_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, len));
memcpy (zmq_msg_data (&msg), body_, len);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_set_group (&msg, group_));
int rc = zmq_msg_send (&msg, s_, 0);
TEST_ASSERT_EQUAL_INT ((int) len, rc);
// TODO isn't the msg closed by zmq_msg_send?
zmq_msg_close (&msg);
}
void msg_recv_cmp (void *s_, const char *group_, const char *body_)
{
zmq_msg_t msg;
const size_t len = strlen (body_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
int recv_rc = TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, s_, 0));
TEST_ASSERT_EQUAL_INT (len, recv_rc);
TEST_ASSERT_EQUAL_STRING (group_, zmq_msg_group (&msg));
TEST_ASSERT_EQUAL_STRING_LEN (body_, zmq_msg_data (&msg), len);
zmq_msg_close (&msg);
}
void test_leave_unjoined_fails ()
{
void *dish = test_context_socket (ZMQ_DISH);
// Leaving a group which we didn't join
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_leave (dish, "Movies"));
test_context_socket_close (dish);
}
void test_long_group ()
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *radio = test_context_socket (ZMQ_RADIO);
bind_loopback (radio, false, my_endpoint, len);
void *dish = test_context_socket (ZMQ_DISH);
// Joining to a long group, over 14 chars
char group[19] = "0123456789ABCDEFGH";
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, group));
// Connecting
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dish, my_endpoint));
msleep (SETTLE_TIME);
// This is going to be sent to the dish
msg_send_expect_success (radio, group, "HELLO");
// Check the correct message arrived
msg_recv_cmp (dish, group, "HELLO");
test_context_socket_close (dish);
test_context_socket_close (radio);
}
void test_join_too_long_fails ()
{
void *dish = test_context_socket (ZMQ_DISH);
// Joining too long group
char too_long_group[ZMQ_GROUP_MAX_LENGTH + 2];
for (int index = 0; index < ZMQ_GROUP_MAX_LENGTH + 2; index++)
too_long_group[index] = 'A';
too_long_group[ZMQ_GROUP_MAX_LENGTH + 1] = '\0';
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_join (dish, too_long_group));
test_context_socket_close (dish);
}
void test_join_twice_fails ()
{
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "Movies"));
// Duplicate Joining
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_join (dish, "Movies"));
test_context_socket_close (dish);
}
void test_radio_dish_tcp_poll (int ipv6_)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *radio = test_context_socket (ZMQ_RADIO);
bind_loopback (radio, ipv6_, my_endpoint, len);
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dish, ZMQ_IPV6, &ipv6_, sizeof (int)));
// Joining
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "Movies"));
// Connecting
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dish, my_endpoint));
msleep (SETTLE_TIME);
// This is not going to be sent as dish only subscribe to "Movies"
msg_send_expect_success (radio, "TV", "Friends");
// This is going to be sent to the dish
msg_send_expect_success (radio, "Movies", "Godfather");
// Check the correct message arrived
msg_recv_cmp (dish, "Movies", "Godfather");
// Join group during connection optvallen
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "TV"));
zmq_sleep (1);
// This should arrive now as we joined the group
msg_send_expect_success (radio, "TV", "Friends");
// Check the correct message arrived
msg_recv_cmp (dish, "TV", "Friends");
// Leaving group
TEST_ASSERT_SUCCESS_ERRNO (zmq_leave (dish, "TV"));
zmq_sleep (1);
// This is not going to be sent as dish only subscribe to "Movies"
msg_send_expect_success (radio, "TV", "Friends");
// This is going to be sent to the dish
msg_send_expect_success (radio, "Movies", "Godfather");
// test zmq_poll with dish
zmq_pollitem_t items[] = {
{radio, 0, ZMQ_POLLIN, 0}, // read publications
{dish, 0, ZMQ_POLLIN, 0}, // read subscriptions
};
int rc = zmq_poll (items, 2, 2000);
TEST_ASSERT_EQUAL_INT (1, rc);
TEST_ASSERT_EQUAL_INT (ZMQ_POLLIN, items[1].revents);
// Check the correct message arrived
msg_recv_cmp (dish, "Movies", "Godfather");
test_context_socket_close (dish);
test_context_socket_close (radio);
}
MAKE_TEST_V4V6 (test_radio_dish_tcp_poll)
void test_dish_connect_fails (int ipv6_)
{
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dish, ZMQ_IPV6, &ipv6_, sizeof (int)));
const char *url = ipv6_ ? "udp://[::1]:5556" : "udp://127.0.0.1:5556";
// Connecting dish should fail
TEST_ASSERT_FAILURE_ERRNO (ENOCOMPATPROTO, zmq_connect (dish, url));
test_context_socket_close (dish);
}
MAKE_TEST_V4V6 (test_dish_connect_fails)
void test_radio_bind_fails (int ipv6_)
{
void *radio = test_context_socket (ZMQ_RADIO);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (radio, ZMQ_IPV6, &ipv6_, sizeof (int)));
// Connecting dish should fail
// Bind radio should fail
TEST_ASSERT_FAILURE_ERRNO (ENOCOMPATPROTO,
zmq_bind (radio, "udp://*:5556"));
test_context_socket_close (radio);
}
MAKE_TEST_V4V6 (test_radio_bind_fails)
void test_radio_dish_udp (int ipv6_)
{
void *radio = test_context_socket (ZMQ_RADIO);
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (radio, ZMQ_IPV6, &ipv6_, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dish, ZMQ_IPV6, &ipv6_, sizeof (int)));
const char *radio_url = ipv6_ ? "udp://[::1]:5556" : "udp://127.0.0.1:5556";
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dish, "udp://*:5556"));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (radio, radio_url));
msleep (SETTLE_TIME);
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "TV"));
msg_send_expect_success (radio, "TV", "Friends");
msg_recv_cmp (dish, "TV", "Friends");
test_context_socket_close (dish);
test_context_socket_close (radio);
}
MAKE_TEST_V4V6 (test_radio_dish_udp)
#define MCAST_IPV4 "226.8.5.5"
#define MCAST_IPV6 "ff02::7a65:726f:6df1:0a01"
static const char *mcast_url (int ipv6_)
{
if (ipv6_) {
return "udp://[" MCAST_IPV6 "]:5555";
}
return "udp://" MCAST_IPV4 ":5555";
}
// OSX uses a different name for this socket option
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
union sa_u
{
struct sockaddr generic;
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
};
// Test if multicast is available on this machine by attempting to
// send a receive a multicast datagram
static bool is_multicast_available (int ipv6_)
{
int family = ipv6_ ? AF_INET6 : AF_INET;
fd_t bind_sock = retired_fd;
fd_t send_sock = retired_fd;
int port = 5555;
bool success = false;
const char *msg = "it works";
char buf[32];
union sa_u any;
union sa_u mcast;
socklen_t sl;
int rc;
if (ipv6_) {
struct sockaddr_in6 *any_ipv6 = &any.ipv6;
struct sockaddr_in6 *mcast_ipv6 = &mcast.ipv6;
any_ipv6->sin6_family = AF_INET6;
any_ipv6->sin6_port = htons (port);
any_ipv6->sin6_flowinfo = 0;
any_ipv6->sin6_scope_id = 0;
rc = test_inet_pton (AF_INET6, "::", &any_ipv6->sin6_addr);
if (rc == 0) {
goto out;
}
*mcast_ipv6 = *any_ipv6;
rc = test_inet_pton (AF_INET6, MCAST_IPV6, &mcast_ipv6->sin6_addr);
if (rc == 0) {
goto out;
}
sl = sizeof (*any_ipv6);
} else {
struct sockaddr_in *any_ipv4 = &any.ipv4;
struct sockaddr_in *mcast_ipv4 = &mcast.ipv4;
any_ipv4->sin_family = AF_INET;
any_ipv4->sin_port = htons (5555);
rc = test_inet_pton (AF_INET, "0.0.0.0", &any_ipv4->sin_addr);
if (rc == 0) {
goto out;
}
*mcast_ipv4 = *any_ipv4;
rc = test_inet_pton (AF_INET, MCAST_IPV4, &mcast_ipv4->sin_addr);
if (rc == 0) {
goto out;
}
sl = sizeof (*any_ipv4);
}
bind_sock = socket (family, SOCK_DGRAM, IPPROTO_UDP);
if (bind_sock < 0) {
goto out;
}
send_sock = socket (family, SOCK_DGRAM, IPPROTO_UDP);
if (bind_sock < 0) {
goto out;
}
rc = bind (bind_sock, &any.generic, sl);
if (rc < 0) {
goto out;
}
if (ipv6_) {
struct ipv6_mreq mreq;
const sockaddr_in6 *const mcast_ipv6 = &mcast.ipv6;
mreq.ipv6mr_multiaddr = mcast_ipv6->sin6_addr;
mreq.ipv6mr_interface = 0;
rc = setsockopt (bind_sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
as_setsockopt_opt_t (&mreq), sizeof (mreq));
if (rc < 0) {
goto out;
}
int loop = 1;
rc = setsockopt (send_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
as_setsockopt_opt_t (&loop), sizeof (loop));
if (rc < 0) {
goto out;
}
} else {
struct ip_mreq mreq;
const sockaddr_in *const mcast_ipv4 = &mcast.ipv4;
mreq.imr_multiaddr = mcast_ipv4->sin_addr;
mreq.imr_interface.s_addr = htonl (INADDR_ANY);
rc = setsockopt (bind_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
as_setsockopt_opt_t (&mreq), sizeof (mreq));
if (rc < 0) {
goto out;
}
int loop = 1;
rc = setsockopt (send_sock, IPPROTO_IP, IP_MULTICAST_LOOP,
as_setsockopt_opt_t (&loop), sizeof (loop));
if (rc < 0) {
goto out;
}
}
msleep (SETTLE_TIME);
rc = sendto (send_sock, msg, static_cast<socklen_t> (strlen (msg)), 0,
&mcast.generic, sl);
if (rc < 0) {
goto out;
}
msleep (SETTLE_TIME);
rc = recvfrom (bind_sock, buf, sizeof (buf) - 1, 0, NULL, 0);
if (rc < 0) {
goto out;
}
buf[rc] = '\0';
success = (strcmp (msg, buf) == 0);
out:
if (bind_sock >= 0) {
close (bind_sock);
}
if (send_sock >= 0) {
close (send_sock);
}
return success;
}
static void ignore_if_unavailable (int ipv6_)
{
if (ipv6_ && !is_ipv6_available ())
TEST_IGNORE_MESSAGE ("No IPV6 available");
if (!is_multicast_available (ipv6_))
TEST_IGNORE_MESSAGE ("No multicast available");
}
static void test_radio_dish_mcast (int ipv6_)
{
ignore_if_unavailable (ipv6_);
void *radio = test_context_socket (ZMQ_RADIO);
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (radio, ZMQ_IPV6, &ipv6_, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dish, ZMQ_IPV6, &ipv6_, sizeof (int)));
const char *url = mcast_url (ipv6_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dish, url));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (radio, url));
msleep (SETTLE_TIME);
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "TV"));
msg_send_expect_success (radio, "TV", "Friends");
msg_recv_cmp (dish, "TV", "Friends");
test_context_socket_close (dish);
test_context_socket_close (radio);
}
MAKE_TEST_V4V6 (test_radio_dish_mcast)
static void test_radio_dish_no_loop (int ipv6_)
{
#ifdef _WIN32
TEST_IGNORE_MESSAGE (
"ZMQ_MULTICAST_LOOP=false does not appear to work on Windows (TODO)");
#endif
ignore_if_unavailable (ipv6_);
void *radio = test_context_socket (ZMQ_RADIO);
void *dish = test_context_socket (ZMQ_DISH);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (radio, ZMQ_IPV6, &ipv6_, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dish, ZMQ_IPV6, &ipv6_, sizeof (int)));
// Disable multicast loop for radio
int loop = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (radio, ZMQ_MULTICAST_LOOP, &loop, sizeof (int)));
const char *url = mcast_url (ipv6_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dish, url));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (radio, url));
msleep (SETTLE_TIME);
TEST_ASSERT_SUCCESS_ERRNO (zmq_join (dish, "TV"));
msg_send_expect_success (radio, "TV", "Friends");
// Looping is disabled, we shouldn't receive anything
msleep (SETTLE_TIME);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (dish, NULL, 0, ZMQ_DONTWAIT));
test_context_socket_close (dish);
test_context_socket_close (radio);
}
MAKE_TEST_V4V6 (test_radio_dish_no_loop)
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_leave_unjoined_fails);
RUN_TEST (test_join_too_long_fails);
RUN_TEST (test_long_group);
RUN_TEST (test_join_twice_fails);
RUN_TEST (test_radio_bind_fails_ipv4);
RUN_TEST (test_radio_bind_fails_ipv6);
RUN_TEST (test_dish_connect_fails_ipv4);
RUN_TEST (test_dish_connect_fails_ipv6);
RUN_TEST (test_radio_dish_tcp_poll_ipv4);
RUN_TEST (test_radio_dish_tcp_poll_ipv6);
RUN_TEST (test_radio_dish_udp_ipv4);
RUN_TEST (test_radio_dish_udp_ipv6);
RUN_TEST (test_radio_dish_mcast_ipv4);
RUN_TEST (test_radio_dish_no_loop_ipv4);
RUN_TEST (test_radio_dish_mcast_ipv6);
RUN_TEST (test_radio_dish_no_loop_ipv6);
return UNITY_END ();
}

69
vendor/ZMQ/tests/test_rebind_ipc.cpp vendored Normal file
View File

@@ -0,0 +1,69 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_rebind_ipc ()
{
char my_endpoint[MAX_SOCKET_STRING];
make_random_ipc_endpoint (my_endpoint);
void *sb0 = test_context_socket (ZMQ_PUSH);
void *sb1 = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb0, my_endpoint));
void *sc = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
send_string_expect_success (sb0, "42", 0);
recv_string_expect_success (sc, "42", 0);
test_context_socket_close (sb0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb1, my_endpoint));
send_string_expect_success (sb1, "42", 0);
recv_string_expect_success (sc, "42", 0);
test_context_socket_close (sc);
test_context_socket_close (sb1);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_rebind_ipc);
return UNITY_END ();
}

111
vendor/ZMQ/tests/test_reconnect_ivl.cpp vendored Normal file
View File

@@ -0,0 +1,111 @@
/*
Copyright (c) 2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_reconnect_ivl_against_pair_socket (const char *my_endpoint_,
void *sb_)
{
void *sc = test_context_socket (ZMQ_PAIR);
int interval = -1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_RECONNECT_IVL, &interval, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_));
bounce (sb_, sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb_, my_endpoint_));
expect_bounce_fail (sb_, sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb_, my_endpoint_));
expect_bounce_fail (sb_, sc);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_));
bounce (sb_, sc);
test_context_socket_close (sc);
}
#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU)
void test_reconnect_ivl_ipc (void)
{
char my_endpoint[256];
make_random_ipc_endpoint (my_endpoint);
void *sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, my_endpoint));
test_reconnect_ivl_against_pair_socket (my_endpoint, sb);
test_context_socket_close (sb);
}
#endif
void test_reconnect_ivl_tcp (bind_function_t bind_function_)
{
char my_endpoint[MAX_SOCKET_STRING];
void *sb = test_context_socket (ZMQ_PAIR);
bind_function_ (sb, my_endpoint, sizeof my_endpoint);
test_reconnect_ivl_against_pair_socket (my_endpoint, sb);
test_context_socket_close (sb);
}
void test_reconnect_ivl_tcp_ipv4 ()
{
test_reconnect_ivl_tcp (bind_loopback_ipv4);
}
void test_reconnect_ivl_tcp_ipv6 ()
{
if (is_ipv6_available ()) {
zmq_ctx_set (get_test_context (), ZMQ_IPV6, 1);
test_reconnect_ivl_tcp (bind_loopback_ipv6);
}
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU)
RUN_TEST (test_reconnect_ivl_ipc);
#endif
RUN_TEST (test_reconnect_ivl_tcp_ipv4);
RUN_TEST (test_reconnect_ivl_tcp_ipv6);
return UNITY_END ();
}

View File

@@ -0,0 +1,297 @@
/*
Copyright (c) 2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include "testutil_monitoring.hpp"
#include <unity.h>
// test behavior with (mostly) default values
void reconnect_default ()
{
// setup pub socket
void *pub = test_context_socket (ZMQ_PUB);
// Bind pub socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
// setup sub socket
void *sub = test_context_socket (ZMQ_SUB);
// Monitor all events on sub
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
// Create socket for collecting monitor events
void *sub_mon = test_context_socket (ZMQ_PAIR);
// Connect so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
// set reconnect interval so only a single reconnect is tried
int interval = 60 * 1000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub, ZMQ_RECONNECT_IVL, &interval, sizeof (interval)));
// connect to pub
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// close the pub socket
test_context_socket_close_zero_linger (pub);
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
// ZMQ_EVENT_CONNECT_RETRIED should be last event, because of timeout set above
int event;
char *event_address;
int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
2 * 1000);
assert (rc == -1);
// Close sub
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub);
// Close monitor
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub_mon);
}
// test successful reconnect
void reconnect_success ()
{
// setup pub socket
void *pub = test_context_socket (ZMQ_PUB);
// Bind pub socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
// setup sub socket
void *sub = test_context_socket (ZMQ_SUB);
// Monitor all events on sub
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
// Create socket for collecting monitor events
void *sub_mon = test_context_socket (ZMQ_PAIR);
// Connect so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
// set reconnect interval so only a single reconnect is tried
int interval = 1 * 1000;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sub, ZMQ_RECONNECT_IVL, &interval, sizeof (interval)));
// connect to pub
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// close the pub socket
test_context_socket_close_zero_linger (pub);
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
// ZMQ_EVENT_CONNECT_RETRIED should be last event, because of timeout set above
int event;
char *event_address;
int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
SETTLE_TIME);
assert (rc == -1);
// Now re-bind pub socket and wait for re-connect
pub = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
msleep (SETTLE_TIME);
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// ZMQ_EVENT_HANDSHAKE_SUCCEEDED should be last event
rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
SETTLE_TIME);
assert (rc == -1);
// Close sub
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub);
test_context_socket_close_zero_linger (pub);
// Close monitor
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub_mon);
}
#ifdef ZMQ_BUILD_DRAFT_API
// test stopping reconnect on connection refused
void reconnect_stop_on_refused ()
{
// setup pub socket
void *pub = test_context_socket (ZMQ_PUB);
// Bind pub socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
// setup sub socket
void *sub = test_context_socket (ZMQ_SUB);
// Monitor all events on sub
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
// Create socket for collecting monitor events
void *sub_mon = test_context_socket (ZMQ_PAIR);
// Connect so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
// set option to stop reconnecting on error
int stopReconnectOnError = ZMQ_RECONNECT_STOP_CONN_REFUSED;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_RECONNECT_STOP,
&stopReconnectOnError,
sizeof (stopReconnectOnError)));
// connect to pub
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// close the pub socket
test_context_socket_close_zero_linger (pub);
// confirm that we get following events
expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CLOSED);
// ZMQ_EVENT_CLOSED should be last event, because of ZMQ_RECONNECT_STOP set above
int event = 0;
char *event_address;
int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
2 * 1000);
int limit = 0;
while ((rc != -1) && (++limit < 1000)) {
print_unexpected_event_stderr (event, rc, 0, -1);
rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
2 * 1000);
}
// Close sub
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub);
// Close monitor
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub_mon);
}
#endif
#ifdef ZMQ_BUILD_DRAFT_API
// test stopping reconnect on connection refused
void reconnect_stop_on_handshake_failed ()
{
char bind_address[MAX_SOCKET_STRING];
size_t addr_length = sizeof (bind_address);
void *dummy = test_context_socket (ZMQ_STREAM);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dummy, "tcp://127.0.0.1:0"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (dummy, ZMQ_LAST_ENDPOINT, bind_address, &addr_length));
// setup sub socket
void *sub = test_context_socket (ZMQ_SUB);
// Monitor all events on sub
TEST_ASSERT_SUCCESS_ERRNO (
zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
// Create socket for collecting monitor events
void *sub_mon = test_context_socket (ZMQ_PAIR);
// Connect so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
// set handshake interval (i.e., timeout) to a more reasonable value
int handshakeInterval = 1000;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
sub, ZMQ_HANDSHAKE_IVL, &handshakeInterval, sizeof (handshakeInterval)));
// set option to stop reconnecting on failed handshake
int stopReconnectOnError = ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_RECONNECT_STOP,
&stopReconnectOnError,
sizeof (stopReconnectOnError)));
// connect to dummy stream socket above
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, bind_address));
#if 1
// ZMQ_EVENT_DISCONNECTED should be last event, because of ZMQ_RECONNECT_STOP set above
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL);
expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
#else
print_events (sub_mon, 2 * 1000, 1000);
#endif
// Close sub
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub);
test_context_socket_close_zero_linger (dummy);
// Close monitor
// TODO why does this use zero_linger?
test_context_socket_close_zero_linger (sub_mon);
}
#endif
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (reconnect_default);
RUN_TEST (reconnect_success);
#ifdef ZMQ_BUILD_DRAFT_API
RUN_TEST (reconnect_stop_on_refused);
RUN_TEST (reconnect_stop_on_handshake_failed);
#endif
return UNITY_END ();
}

120
vendor/ZMQ/tests/test_req_correlate.cpp vendored Normal file
View File

@@ -0,0 +1,120 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_req_correlate ()
{
void *req = test_context_socket (ZMQ_REQ);
void *router = test_context_socket (ZMQ_ROUTER);
int enabled = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int)));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req, my_endpoint));
// Send a multi-part request.
s_send_seq (req, "ABC", "DEF", SEQ_END);
zmq_msg_t msg;
zmq_msg_init (&msg);
// Receive peer routing id
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, router, 0));
TEST_ASSERT_GREATER_THAN_INT (0, zmq_msg_size (&msg));
zmq_msg_t peer_id_msg;
zmq_msg_init (&peer_id_msg);
zmq_msg_copy (&peer_id_msg, &msg);
int more = 0;
size_t more_size = sizeof (more);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_TRUE (more);
// Receive request id 1
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, router, 0));
TEST_ASSERT_EQUAL_UINT (sizeof (uint32_t), zmq_msg_size (&msg));
const uint32_t req_id = *static_cast<uint32_t *> (zmq_msg_data (&msg));
zmq_msg_t req_id_msg;
zmq_msg_init (&req_id_msg);
zmq_msg_copy (&req_id_msg, &msg);
more = 0;
more_size = sizeof (more);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_TRUE (more);
// Receive the rest.
s_recv_seq (router, 0, "ABC", "DEF", SEQ_END);
uint32_t bad_req_id = req_id + 1;
// Send back a bad reply: wrong req id, 0, data
zmq_msg_copy (&msg, &peer_id_msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&msg, router, ZMQ_SNDMORE));
zmq_msg_init_data (&msg, &bad_req_id, sizeof (uint32_t), NULL, NULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&msg, router, ZMQ_SNDMORE));
s_send_seq (router, 0, "DATA", SEQ_END);
// Send back a good reply: good req id, 0, data
zmq_msg_copy (&msg, &peer_id_msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&msg, router, ZMQ_SNDMORE));
zmq_msg_copy (&msg, &req_id_msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&msg, router, ZMQ_SNDMORE));
s_send_seq (router, 0, "GHI", SEQ_END);
// Receive reply. If bad reply got through, we wouldn't see
// this particular data.
s_recv_seq (req, "GHI", SEQ_END);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&peer_id_msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&req_id_msg));
test_context_socket_close_zero_linger (req);
test_context_socket_close_zero_linger (router);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_req_correlate);
return UNITY_END ();
}

233
vendor/ZMQ/tests/test_req_relaxed.cpp vendored Normal file
View File

@@ -0,0 +1,233 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unity.h>
const size_t services = 5;
void *req;
void *rep[services];
void setUp ()
{
setup_test_context ();
char my_endpoint[MAX_SOCKET_STRING];
req = test_context_socket (ZMQ_REQ);
int enabled = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req, ZMQ_REQ_RELAXED, &enabled, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int)));
bind_loopback_ipv4 (req, my_endpoint, sizeof (my_endpoint));
for (size_t peer = 0; peer < services; peer++) {
rep[peer] = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rep[peer], my_endpoint));
// These tests require strict ordering, so wait for the connections to
// happen before opening the next, so that messages flow in the
// expected direction
msleep (SETTLE_TIME);
}
}
void tearDown ()
{
test_context_socket_close_zero_linger (req);
for (size_t peer = 0; peer < services; peer++)
test_context_socket_close_zero_linger (rep[peer]);
teardown_test_context ();
}
static void bounce (void *socket_)
{
int more;
size_t more_size = sizeof (more);
do {
zmq_msg_t recv_part, sent_part;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&recv_part));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&recv_part, socket_, 0));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size));
zmq_msg_init (&sent_part);
zmq_msg_copy (&sent_part, &recv_part);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&sent_part, socket_, more ? ZMQ_SNDMORE : 0));
zmq_msg_close (&recv_part);
} while (more);
}
static int get_events (void *socket_)
{
int events;
size_t events_size = sizeof (events);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_EVENTS, &events, &events_size));
return events;
}
void test_case_1 ()
{
// Case 1: Second send() before a reply arrives in a pipe.
int events = get_events (req);
TEST_ASSERT_EQUAL_INT (ZMQ_POLLOUT, events);
// Send a request, ensure it arrives, don't send a reply
s_send_seq (req, "A", "B", SEQ_END);
s_recv_seq (rep[0], "A", "B", SEQ_END);
events = get_events (req);
TEST_ASSERT_EQUAL_INT (ZMQ_POLLOUT, events);
// Send another request on the REQ socket
s_send_seq (req, "C", "D", SEQ_END);
s_recv_seq (rep[1], "C", "D", SEQ_END);
events = get_events (req);
TEST_ASSERT_EQUAL_INT (ZMQ_POLLOUT, events);
// Send a reply to the first request - that should be discarded by the REQ
s_send_seq (rep[0], "WRONG", SEQ_END);
// Send the expected reply
s_send_seq (rep[1], "OK", SEQ_END);
s_recv_seq (req, "OK", SEQ_END);
// Another standard req-rep cycle, just to check
s_send_seq (req, "E", SEQ_END);
s_recv_seq (rep[2], "E", SEQ_END);
s_send_seq (rep[2], "F", "G", SEQ_END);
s_recv_seq (req, "F", "G", SEQ_END);
}
void test_case_2 ()
{
// Case 2: Second send() after a reply is already in a pipe on the REQ.
// TODO instead of rerunning the previous test cases, only do the relevant parts (or change the peer)
test_case_1 ();
// Send a request, ensure it arrives, send a reply
s_send_seq (req, "H", SEQ_END);
s_recv_seq (rep[3], "H", SEQ_END);
s_send_seq (rep[3], "BAD", SEQ_END);
// Wait for message to be there.
msleep (SETTLE_TIME);
// Without receiving that reply, send another request on the REQ socket
s_send_seq (req, "I", SEQ_END);
s_recv_seq (rep[4], "I", SEQ_END);
// Send the expected reply
s_send_seq (rep[4], "GOOD", SEQ_END);
s_recv_seq (req, "GOOD", SEQ_END);
}
void test_case_3 ()
{
// Case 3: Check issue #1690. Two send() in a row should not close the
// communication pipes. For example pipe from req to rep[0] should not be
// closed after executing Case 1. So rep[0] should be the next to receive,
// not rep[1].
// TODO instead of rerunning the previous test cases, only do the relevant parts (or change the peer)
test_case_2 ();
s_send_seq (req, "J", SEQ_END);
s_recv_seq (rep[0], "J", SEQ_END);
}
void test_case_4 ()
{
// TODO this test case does not use the sockets from setUp
// Case 4: Check issue #1695. As messages may pile up before a responder
// is available, we check that responses to messages other than the last
// sent one are correctly discarded by the REQ pipe
// Setup REQ socket as client
void *req = test_context_socket (ZMQ_REQ);
int enabled = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req, ZMQ_REQ_RELAXED, &enabled, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req, ENDPOINT_0));
// Setup ROUTER socket as server but do not bind it just yet
void *router = test_context_socket (ZMQ_ROUTER);
// Send two requests
s_send_seq (req, "TO_BE_DISCARDED", SEQ_END);
s_send_seq (req, "TO_BE_ANSWERED", SEQ_END);
// Bind server allowing it to receive messages
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, ENDPOINT_0));
// Read the two messages and send them back as is
bounce (router);
bounce (router);
// Read the expected correlated reply. As the ZMQ_REQ_CORRELATE is active,
// the expected answer is "TO_BE_ANSWERED", not "TO_BE_DISCARDED".
s_recv_seq (req, "TO_BE_ANSWERED", SEQ_END);
test_context_socket_close_zero_linger (req);
test_context_socket_close_zero_linger (router);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_case_1);
RUN_TEST (test_case_2);
RUN_TEST (test_case_3);
RUN_TEST (test_case_4);
return UNITY_END ();
}

125
vendor/ZMQ/tests/test_reqrep_device.cpp vendored Normal file
View File

@@ -0,0 +1,125 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_roundtrip ()
{
char endpoint1[MAX_SOCKET_STRING];
char endpoint2[MAX_SOCKET_STRING];
// Create a req/rep device.
void *dealer = test_context_socket (ZMQ_DEALER);
bind_loopback_ipv4 (dealer, endpoint1, sizeof (endpoint1));
void *router = test_context_socket (ZMQ_ROUTER);
bind_loopback_ipv4 (router, endpoint2, sizeof (endpoint2));
// Create a worker.
void *rep = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rep, endpoint1));
// Create a client.
void *req = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req, endpoint2));
// Send a request.
send_string_expect_success (req, "ABC", ZMQ_SNDMORE);
send_string_expect_success (req, "DEF", 0);
// Pass the request through the device.
for (int i = 0; i != 4; i++) {
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, router, 0));
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&msg, dealer, rcvmore ? ZMQ_SNDMORE : 0));
}
// Receive the request.
recv_string_expect_success (rep, "ABC", 0);
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_TRUE (rcvmore);
recv_string_expect_success (rep, "DEF", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
// Send the reply.
send_string_expect_success (rep, "GHI", ZMQ_SNDMORE);
send_string_expect_success (rep, "JKL", 0);
// Pass the reply through the device.
for (int i = 0; i != 4; i++) {
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, dealer, 0));
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (dealer, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&msg, router, rcvmore ? ZMQ_SNDMORE : 0));
}
// Receive the reply.
recv_string_expect_success (req, "GHI", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_TRUE (rcvmore);
recv_string_expect_success (req, "JKL", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
// Clean up.
test_context_socket_close (req);
test_context_socket_close (rep);
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

View File

@@ -0,0 +1,125 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
// TODO this is heavily duplicated with test_reqrep_device.cpp
void test_roundtrip ()
{
// Create a req/rep device.
void *dealer = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dealer, "tipc://{5560,0,0}"));
void *router = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, "tipc://{5561,0,0}"));
// Create a worker.
void *rep = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rep, "tipc://{5560,0}@0.0.0"));
// Create a client.
void *req = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (req, "tipc://{5561,0}@0.0.0"));
// Send a request.
send_string_expect_success (req, "ABC", ZMQ_SNDMORE);
send_string_expect_success (req, "DEF", 0);
// Pass the request through the device.
for (int i = 0; i != 4; i++) {
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, router, 0));
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&msg, dealer, rcvmore ? ZMQ_SNDMORE : 0));
}
// Receive the request.
recv_string_expect_success (rep, "ABC", 0);
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_TRUE (rcvmore);
recv_string_expect_success (rep, "DEF", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
// Send the reply.
send_string_expect_success (rep, "GHI", ZMQ_SNDMORE);
send_string_expect_success (rep, "JKL", 0);
// Pass the reply through the device.
for (int i = 0; i != 4; i++) {
zmq_msg_t msg;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&msg));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, dealer, 0));
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (dealer, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_send (&msg, router, rcvmore ? ZMQ_SNDMORE : 0));
}
// Receive the reply.
recv_string_expect_success (req, "GHI", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_TRUE (rcvmore);
recv_string_expect_success (req, "JKL", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
// Clean up.
test_context_socket_close (req);
test_context_socket_close (rep);
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main ()
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

56
vendor/ZMQ/tests/test_reqrep_inproc.cpp vendored Normal file
View File

@@ -0,0 +1,56 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_roundtrip ()
{
void *sb = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

86
vendor/ZMQ/tests/test_reqrep_ipc.cpp vendored Normal file
View File

@@ -0,0 +1,86 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_leak ()
{
char my_endpoint[256];
void *sb = test_context_socket (ZMQ_REP);
bind_loopback_ipc (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
static const char leakymsg[] = "leakymsg";
send_string_expect_success (sc, leakymsg, 0);
char *buf = s_recv (sb);
free (buf);
test_context_socket_close (sc);
msleep (SETTLE_TIME);
send_string_expect_success (sb, leakymsg, 0);
test_context_socket_close (sb);
}
void test_simple (void)
{
char my_endpoint[256];
void *sb = test_context_socket (ZMQ_REP);
bind_loopback_ipc (sb, my_endpoint, sizeof my_endpoint);
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_simple);
RUN_TEST (test_leak);
return UNITY_END ();
}

220
vendor/ZMQ/tests/test_reqrep_tcp.cpp vendored Normal file
View File

@@ -0,0 +1,220 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_single_connect (int ipv6_)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *sb = test_context_socket (ZMQ_REP);
bind_loopback (sb, ipv6_, my_endpoint, len);
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_IPV6, &ipv6_, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
bounce (sb, sc);
// the sockets are disconnected and unbound explicitly in this test case
// to check that this can be done successfully with the expected
// endpoints/addresses
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb, my_endpoint));
test_context_socket_close (sc);
test_context_socket_close (sb);
}
void make_connect_address (char *connect_address_,
const int ipv6_,
const int port_,
const char *bind_address_)
{
sprintf (connect_address_, "tcp://%s:%i;%s", ipv6_ ? "[::1]" : "127.0.0.1",
port_, strrchr (bind_address_, '/') + 1);
}
void test_multi_connect (int ipv6_)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint_0[MAX_SOCKET_STRING];
char my_endpoint_1[MAX_SOCKET_STRING];
char my_endpoint_2[MAX_SOCKET_STRING];
char my_endpoint_3[MAX_SOCKET_STRING * 2];
void *sb0 = test_context_socket (ZMQ_REP);
bind_loopback (sb0, ipv6_, my_endpoint_0, len);
void *sb1 = test_context_socket (ZMQ_REP);
bind_loopback (sb1, ipv6_, my_endpoint_1, len);
void *sb2 = test_context_socket (ZMQ_REP);
bind_loopback (sb2, ipv6_, my_endpoint_2, len);
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc, ZMQ_IPV6, &ipv6_, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_1));
make_connect_address (my_endpoint_3, ipv6_, 5564, my_endpoint_2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_3));
bounce (sb0, sc);
bounce (sb1, sc);
bounce (sb2, sc);
bounce (sb0, sc);
bounce (sb1, sc);
bounce (sb2, sc);
bounce (sb0, sc);
/// see comment on zmq_disconnect/zmq_unbind in test_single_connect
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_3));
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb0, my_endpoint_0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb1, my_endpoint_1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb2, my_endpoint_2));
test_context_socket_close (sc);
test_context_socket_close (sb0);
test_context_socket_close (sb1);
test_context_socket_close (sb2);
}
void test_multi_connect_same_port (int ipv6_)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint_0[MAX_SOCKET_STRING];
char my_endpoint_1[MAX_SOCKET_STRING];
char my_endpoint_2[MAX_SOCKET_STRING * 2];
char my_endpoint_3[MAX_SOCKET_STRING * 2];
char my_endpoint_4[MAX_SOCKET_STRING * 2];
char my_endpoint_5[MAX_SOCKET_STRING * 2];
void *sb0 = test_context_socket (ZMQ_REP);
bind_loopback (sb0, ipv6_, my_endpoint_0, len);
void *sb1 = test_context_socket (ZMQ_REP);
bind_loopback (sb1, ipv6_, my_endpoint_1, len);
void *sc0 = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc0, ZMQ_IPV6, &ipv6_, sizeof (int)));
make_connect_address (my_endpoint_2, ipv6_, 5564, my_endpoint_0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc0, my_endpoint_2));
make_connect_address (my_endpoint_3, ipv6_, 5565, my_endpoint_1);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc0, my_endpoint_3));
void *sc1 = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (sc1, ZMQ_IPV6, &ipv6_, sizeof (int)));
make_connect_address (my_endpoint_4, ipv6_, 5565, my_endpoint_0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc1, my_endpoint_4));
make_connect_address (my_endpoint_5, ipv6_, 5564, my_endpoint_1);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc1, my_endpoint_5));
bounce (sb0, sc0);
bounce (sb1, sc0);
bounce (sb0, sc1);
bounce (sb1, sc1);
bounce (sb0, sc0);
bounce (sb1, sc0);
/// see comment on zmq_disconnect/zmq_unbind in test_single_connect
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc1, my_endpoint_4));
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc1, my_endpoint_5));
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc0, my_endpoint_2));
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc0, my_endpoint_3));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb0, my_endpoint_0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb1, my_endpoint_1));
test_context_socket_close (sc0);
test_context_socket_close (sc1);
test_context_socket_close (sb0);
test_context_socket_close (sb1);
}
void test_single_connect_ipv4 ()
{
test_single_connect (false);
}
void test_multi_connect_ipv4 ()
{
test_multi_connect (false);
}
void test_multi_connect_same_port_ipv4 ()
{
test_multi_connect_same_port (false);
}
void test_single_connect_ipv6 ()
{
test_single_connect (true);
}
void test_multi_connect_ipv6 ()
{
test_multi_connect (true);
}
void test_multi_connect_same_port_ipv6 ()
{
test_multi_connect_same_port (true);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_single_connect_ipv4);
RUN_TEST (test_multi_connect_ipv4);
RUN_TEST (test_multi_connect_same_port_ipv4);
RUN_TEST (test_single_connect_ipv6);
RUN_TEST (test_multi_connect_ipv6);
RUN_TEST (test_multi_connect_same_port_ipv6);
return UNITY_END ();
}

60
vendor/ZMQ/tests/test_reqrep_tipc.cpp vendored Normal file
View File

@@ -0,0 +1,60 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_roundtrip ()
{
void *sb = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "tipc://{5560,0,0}"));
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "tipc://{5560,0}@0.0.0"));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_roundtrip);
return UNITY_END ();
}

64
vendor/ZMQ/tests/test_reqrep_vmci.cpp vendored Normal file
View File

@@ -0,0 +1,64 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <sstream>
#include <vmci_sockets.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_reqrep_vmci ()
{
std::stringstream s;
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
std::string endpoint = s.str ();
void *sb = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ()));
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc);
test_context_socket_close (sc);
test_context_socket_close (sb);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_reqrep_vmci);
return UNITY_END ();
}

View File

@@ -0,0 +1,155 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_with_handover ()
{
char my_endpoint[MAX_SOCKET_STRING];
void *router = test_context_socket (ZMQ_ROUTER);
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
// Enable the handover flag
int handover = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_HANDOVER,
&handover, sizeof (handover)));
// Create dealer called "X" and connect it to our router
void *dealer_one = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_one, ZMQ_ROUTING_ID, "X", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer_one, my_endpoint));
// Get message from dealer to know when connection is ready
char buffer[255];
send_string_expect_success (dealer_one, "Hello", 0);
recv_string_expect_success (router, "X", 0);
recv_string_expect_success (router, "Hello", 0);
// Now create a second dealer that uses the same routing id
void *dealer_two = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_two, ZMQ_ROUTING_ID, "X", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer_two, my_endpoint));
// Get message from dealer to know when connection is ready
send_string_expect_success (dealer_two, "Hello", 0);
recv_string_expect_success (router, "X", 0);
recv_string_expect_success (router, "Hello", 0);
// Send a message to 'X' routing id. This should be delivered
// to the second dealer, instead of the first because of the handover.
send_string_expect_success (router, "X", ZMQ_SNDMORE);
send_string_expect_success (router, "Hello", 0);
// Ensure that the first dealer doesn't receive the message
// but the second one does
const int timeout = SETTLE_TIME;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_one, ZMQ_RCVTIMEO, &timeout, sizeof timeout));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (dealer_one, buffer, 255, 0));
recv_string_expect_success (dealer_two, "Hello", 0);
test_context_socket_close (router);
test_context_socket_close (dealer_one);
test_context_socket_close (dealer_two);
}
void test_without_handover ()
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *router = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, "tcp://127.0.0.1:*"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_LAST_ENDPOINT, my_endpoint, &len));
// Create dealer called "X" and connect it to our router
void *dealer_one = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_one, ZMQ_ROUTING_ID, "X", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer_one, my_endpoint));
// Get message from dealer to know when connection is ready
char buffer[255];
send_string_expect_success (dealer_one, "Hello", 0);
recv_string_expect_success (router, "X", 0);
recv_string_expect_success (router, "Hello", 0);
// Now create a second dealer that uses the same routing id
void *dealer_two = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_two, ZMQ_ROUTING_ID, "X", 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer_two, my_endpoint));
// Send message from second dealer
send_string_expect_success (dealer_two, "Hello", 0);
// This should be ignored by the router
const int timeout = SETTLE_TIME;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router, ZMQ_RCVTIMEO, &timeout, sizeof timeout));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (router, buffer, 255, 0));
// Send a message to 'X' routing id. This should be delivered
// to the second dealer, instead of the first because of the handover.
send_string_expect_success (router, "X", ZMQ_SNDMORE);
send_string_expect_success (router, "Hello", 0);
// Ensure that the second dealer doesn't receive the message
// but the first one does
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer_two, ZMQ_RCVTIMEO, &timeout, sizeof timeout));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (dealer_two, buffer, 255, 0));
recv_string_expect_success (dealer_one, "Hello", 0);
test_context_socket_close (router);
test_context_socket_close (dealer_one);
test_context_socket_close (dealer_two);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_with_handover);
RUN_TEST (test_without_handover);
return UNITY_END ();
}

View File

@@ -0,0 +1,233 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
#ifdef ZMQ_BUILD_DRAFT_API
bool send_msg_to_peer_if_ready (void *router_, const char *peer_routing_id_)
{
int rc = TEST_ASSERT_SUCCESS_MESSAGE_ERRNO (
zmq_socket_get_peer_state (router_, peer_routing_id_, 1),
peer_routing_id_);
if (rc & ZMQ_POLLOUT) {
send_string_expect_success (router_, peer_routing_id_,
ZMQ_SNDMORE | ZMQ_DONTWAIT);
send_string_expect_success (router_, "Hello", ZMQ_DONTWAIT);
return true;
}
return false;
}
#endif
void test_get_peer_state ()
{
#ifdef ZMQ_BUILD_DRAFT_API
void *router = test_context_socket (ZMQ_ROUTER);
int mandatory = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY,
&mandatory, sizeof (mandatory)));
const char *my_endpoint = "inproc://test_get_peer_state";
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, my_endpoint));
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;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router, ZMQ_SNDHWM, &hwm, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer1, ZMQ_RCVHWM, &hwm, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer2, ZMQ_RCVHWM, &hwm, sizeof (int)));
const char *dealer1_routing_id = "X";
const char *dealer2_routing_id = "Y";
// Name dealer1 "X" and connect it to our router
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer1, ZMQ_ROUTING_ID, dealer1_routing_id, 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer1, my_endpoint));
// Name dealer2 "Y" and connect it to our router
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer2, ZMQ_ROUTING_ID, dealer2_routing_id, 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer2, my_endpoint));
// Get message from both dealers to know when connection is ready
send_string_expect_success (dealer1, "Hello", 0);
recv_string_expect_success (router, dealer1_routing_id, 0);
recv_string_expect_success (router, "Hello", 0);
send_string_expect_success (dealer2, "Hello", 0);
recv_string_expect_success (router, dealer2_routing_id, 0);
recv_string_expect_success (router, "Hello", 0);
void *poller = zmq_poller_new ();
TEST_ASSERT_NOT_NULL (poller);
// Poll on router and dealer1, but not on dealer2
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, router, NULL, ZMQ_POLLOUT));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_add (poller, dealer1, NULL, ZMQ_POLLIN));
const unsigned int count = 10000;
const unsigned int event_size = 2;
bool dealer2_blocked = false;
unsigned int dealer1_sent = 0, dealer2_sent = 0, dealer1_received = 0;
zmq_poller_event_t events[event_size];
for (unsigned int iteration = 0; iteration < count; ++iteration) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_poller_wait_all (poller, events, event_size, -1));
for (unsigned int event_no = 0; event_no < event_size; ++event_no) {
const zmq_poller_event_t &current_event = events[event_no];
if (current_event.socket == router
&& current_event.events & ZMQ_POLLOUT) {
if (send_msg_to_peer_if_ready (router, dealer1_routing_id))
++dealer1_sent;
if (send_msg_to_peer_if_ready (router, dealer2_routing_id))
++dealer2_sent;
else
dealer2_blocked = true;
}
if (current_event.socket == dealer1
&& current_event.events & ZMQ_POLLIN) {
recv_string_expect_success (dealer1, "Hello", ZMQ_DONTWAIT);
int more;
size_t more_size = sizeof (more);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (dealer1, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_FALSE (more);
++dealer1_received;
}
// never read from dealer2, so its pipe becomes full eventually
}
}
printf ("dealer1_sent = %u, dealer2_sent = %u, dealer1_received = %u\n",
dealer1_sent, dealer2_sent, dealer1_received);
TEST_ASSERT_TRUE (dealer2_blocked);
zmq_poller_destroy (&poller);
test_context_socket_close (router);
test_context_socket_close (dealer1);
test_context_socket_close (dealer2);
#endif
}
void test_get_peer_state_corner_cases ()
{
#ifdef ZMQ_BUILD_DRAFT_API
const char peer_routing_id[] = "foo";
// call get_peer_state with NULL socket
int rc = zmq_socket_get_peer_state (NULL, peer_routing_id,
strlen (peer_routing_id));
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno);
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,
strlen (peer_routing_id));
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSUP, errno);
// call get_peer_state for an unknown routing id
rc = zmq_socket_get_peer_state (router, peer_routing_id,
strlen (peer_routing_id));
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EHOSTUNREACH, errno);
test_context_socket_close (router);
test_context_socket_close (dealer);
#endif
}
void test_basic ()
{
char my_endpoint[MAX_SOCKET_STRING];
void *router = test_context_socket (ZMQ_ROUTER);
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
// Send a message to an unknown peer with the default setting
// This will not report any error
send_string_expect_success (router, "UNKNOWN", ZMQ_SNDMORE);
send_string_expect_success (router, "DATA", 0);
// Send a message to an unknown peer with mandatory routing
// This will fail
int mandatory = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY,
&mandatory, sizeof (mandatory)));
int rc = zmq_send (router, "UNKNOWN", 7, ZMQ_SNDMORE);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (EHOSTUNREACH, errno);
// Create dealer called "X" and connect it to our router
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));
// Get message from dealer to know when connection is ready
send_string_expect_success (dealer, "Hello", 0);
recv_string_expect_success (router, "X", 0);
// Send a message to connected dealer now
// It should work
send_string_expect_success (router, "X", ZMQ_SNDMORE);
send_string_expect_success (router, "Hello", 0);
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_basic);
RUN_TEST (test_get_peer_state);
RUN_TEST (test_get_peer_state_corner_cases);
return UNITY_END ();
}

View File

@@ -0,0 +1,120 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
// DEBUG shouldn't be defined in sources as it will cause a redefined symbol
// error when it is defined in the build configuration. It appears that the
// intent here is to semi-permanently disable DEBUG tracing statements, so the
// implementation is changed to accomodate that intent.
//#define DEBUG 0
#define TRACE_ENABLED 0
void test_router_mandatory_hwm ()
{
if (TRACE_ENABLED)
fprintf (stderr, "Staring router mandatory HWM test ...\n");
char my_endpoint[MAX_SOCKET_STRING];
void *router = test_context_socket (ZMQ_ROUTER);
// Configure router socket to mandatory routing and set HWM and linger
int mandatory = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY,
&mandatory, sizeof (mandatory)));
int sndhwm = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router, ZMQ_SNDHWM, &sndhwm, sizeof (sndhwm)));
int linger = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (router, ZMQ_LINGER, &linger, sizeof (linger)));
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
// Create dealer called "X" and connect it to our router, configure HWM
void *dealer = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (dealer, ZMQ_ROUTING_ID, "X", 1));
int rcvhwm = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer, ZMQ_RCVHWM, &rcvhwm, sizeof (rcvhwm)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));
// Get message from dealer to know when connection is ready
send_string_expect_success (dealer, "Hello", 0);
recv_string_expect_success (router, "X", 0);
int i;
const int buf_size = 65536;
const uint8_t buf[buf_size] = {0};
// Send first batch of messages
for (i = 0; i < 100000; ++i) {
if (TRACE_ENABLED)
fprintf (stderr, "Sending message %d ...\n", i);
const int rc = zmq_send (router, "X", 1, ZMQ_DONTWAIT | ZMQ_SNDMORE);
if (rc == -1 && zmq_errno () == EAGAIN)
break;
TEST_ASSERT_EQUAL_INT (1, rc);
send_array_expect_success (router, buf, ZMQ_DONTWAIT);
}
// This should fail after one message but kernel buffering could
// skew results
TEST_ASSERT_LESS_THAN_INT (10, i);
msleep (1000);
// Send second batch of messages
for (; i < 100000; ++i) {
if (TRACE_ENABLED)
fprintf (stderr, "Sending message %d (part 2) ...\n", i);
const int rc = zmq_send (router, "X", 1, ZMQ_DONTWAIT | ZMQ_SNDMORE);
if (rc == -1 && zmq_errno () == EAGAIN)
break;
TEST_ASSERT_EQUAL_INT (1, rc);
send_array_expect_success (router, buf, ZMQ_DONTWAIT);
}
// This should fail after two messages but kernel buffering could
// skew results
TEST_ASSERT_LESS_THAN_INT (20, i);
if (TRACE_ENABLED)
fprintf (stderr, "Done sending messages.\n");
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_router_mandatory_hwm);
return UNITY_END ();
}

View File

@@ -0,0 +1,70 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_router_mandatory_tipc ()
{
if (!is_tipc_available ()) {
TEST_IGNORE_MESSAGE ("TIPC environment unavailable, skipping test");
}
// Creating the first socket.
void *sa = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sa, "tipc://{15560,0,0}"));
// Sending a message to an unknown peer with the default setting
send_string_expect_success (sa, "UNKNOWN", ZMQ_SNDMORE);
send_string_expect_success (sa, "DATA", 0);
int mandatory = 1;
// Set mandatory routing on socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sa, ZMQ_ROUTER_MANDATORY,
&mandatory, sizeof (mandatory)));
// Send a message and check that it fails
TEST_ASSERT_FAILURE_ERRNO (
EHOSTUNREACH, zmq_send (sa, "UNKNOWN", 7, ZMQ_SNDMORE | ZMQ_DONTWAIT));
test_context_socket_close (sa);
}
int main (void)
{
UNITY_BEGIN ();
RUN_TEST (test_router_mandatory_tipc);
return UNITY_END ();
}

322
vendor/ZMQ/tests/test_router_notify.cpp vendored Normal file
View File

@@ -0,0 +1,322 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_sockopt_router_notify ()
{
void *router = test_context_socket (ZMQ_ROUTER);
int opt_notify;
int opt_notify_read;
size_t opt_notify_read_size = sizeof (opt_notify_read);
// default value is off when socket is constructed
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (0, opt_notify_read);
// valid value - Connect
opt_notify = ZMQ_NOTIFY_CONNECT;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (opt_notify, opt_notify_read);
// valid value - Disconnect
opt_notify = ZMQ_NOTIFY_DISCONNECT;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (opt_notify, opt_notify_read);
// valid value - Off
opt_notify = 0;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (opt_notify, opt_notify_read);
// valid value - Both
opt_notify = ZMQ_NOTIFY_CONNECT | ZMQ_NOTIFY_DISCONNECT;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (opt_notify, opt_notify_read);
// value boundary
opt_notify = -1;
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_setsockopt (router, ZMQ_ROUTER_NOTIFY, &opt_notify,
sizeof (opt_notify)));
opt_notify = (ZMQ_NOTIFY_CONNECT | ZMQ_NOTIFY_DISCONNECT) + 1;
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_setsockopt (router, ZMQ_ROUTER_NOTIFY, &opt_notify,
sizeof (opt_notify)));
// failures don't update the value
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (ZMQ_NOTIFY_CONNECT | ZMQ_NOTIFY_DISCONNECT,
opt_notify_read);
test_context_socket_close (router);
// check a non-router socket type
void *dealer = test_context_socket (ZMQ_DEALER);
// setsockopt fails for non-router sockets
opt_notify = ZMQ_NOTIFY_CONNECT;
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_setsockopt (dealer, ZMQ_ROUTER_NOTIFY, &opt_notify,
sizeof (opt_notify)));
// getsockopts returns off for any non-router socket
TEST_ASSERT_SUCCESS_ERRNO (zmq_getsockopt (
dealer, ZMQ_ROUTER_NOTIFY, &opt_notify_read, &opt_notify_read_size));
TEST_ASSERT_EQUAL (0, opt_notify_read);
test_context_socket_close (dealer);
}
void test_router_notify_helper (int opt_notify_)
{
void *router = test_context_socket (ZMQ_ROUTER);
int opt_more;
size_t opt_more_length = sizeof (opt_more);
int opt_events;
size_t opt_events_length = sizeof (opt_events);
char connect_address[MAX_SOCKET_STRING];
// valid values
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify_, sizeof (opt_notify_)));
bind_loopback_ipv4 (router, connect_address, sizeof connect_address);
void *dealer = test_context_socket (ZMQ_DEALER);
const char *dealer_routing_id = "X";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer, ZMQ_ROUTING_ID, dealer_routing_id, 1));
// dealer connects
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, connect_address));
// connection notification msg
if (opt_notify_ & ZMQ_NOTIFY_CONNECT) {
// routing-id only message of the connect
recv_string_expect_success (router, dealer_routing_id,
0); // 1st part: routing-id
recv_string_expect_success (router, "", 0); // 2nd part: empty
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &opt_more, &opt_more_length));
TEST_ASSERT_EQUAL (0, opt_more);
}
// test message from the dealer
send_string_expect_success (dealer, "Hello", 0);
recv_string_expect_success (router, dealer_routing_id, 0);
recv_string_expect_success (router, "Hello", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &opt_more, &opt_more_length));
TEST_ASSERT_EQUAL (0, opt_more);
// dealer disconnects
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (dealer, connect_address));
// need one more process_commands() (???)
msleep (SETTLE_TIME);
zmq_getsockopt (dealer, ZMQ_EVENTS, &opt_events, &opt_events_length);
// connection notification msg
if (opt_notify_ & ZMQ_NOTIFY_DISCONNECT) {
// routing-id only message of the connect
recv_string_expect_success (router, dealer_routing_id,
0); // 1st part: routing-id
recv_string_expect_success (router, "", 0); // 2nd part: empty
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (router, ZMQ_RCVMORE, &opt_more, &opt_more_length));
TEST_ASSERT_EQUAL (0, opt_more);
}
test_context_socket_close (dealer);
test_context_socket_close (router);
}
void test_router_notify_connect ()
{
test_router_notify_helper (ZMQ_NOTIFY_CONNECT);
}
void test_router_notify_disconnect ()
{
test_router_notify_helper (ZMQ_NOTIFY_DISCONNECT);
}
void test_router_notify_both ()
{
test_router_notify_helper (ZMQ_NOTIFY_CONNECT | ZMQ_NOTIFY_DISCONNECT);
}
void test_handshake_fail ()
{
// setup router socket
void *router = test_context_socket (ZMQ_ROUTER);
int opt_timeout = 200;
int opt_notify = ZMQ_NOTIFY_CONNECT | ZMQ_NOTIFY_DISCONNECT;
char connect_address[MAX_SOCKET_STRING];
// valid values
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_RCVTIMEO, &opt_timeout, sizeof (opt_timeout)));
bind_loopback_ipv4 (router, connect_address, sizeof connect_address);
// send something on raw tcp
void *stream = test_context_socket (ZMQ_STREAM);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (stream, connect_address));
send_string_expect_success (stream, "not-a-handshake", 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (stream, connect_address));
test_context_socket_close (stream);
// no notification delivered
char buffer[255];
TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
zmq_recv (router, buffer, sizeof (buffer), 0));
test_context_socket_close (router);
}
void test_error_during_multipart ()
{
/*
* If the disconnect occurs in the middle of the multipart
* message, the socket should not add the notification at the
* end of the incomplete message. It must discard the incomplete
* message, and delivert the notification as a new message.
*/
char connect_address[MAX_SOCKET_STRING];
char long_str[128] = {0};
memset (long_str, '*', sizeof (long_str) - 1);
// setup router
void *router = test_context_socket (ZMQ_ROUTER);
int opt_notify = ZMQ_NOTIFY_DISCONNECT;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_ROUTER_NOTIFY, &opt_notify, sizeof (opt_notify)));
int64_t opt_maxmsgsize = 64; // the handshake fails if this is too small
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
router, ZMQ_MAXMSGSIZE, &opt_maxmsgsize, sizeof (opt_maxmsgsize)));
bind_loopback_ipv4 (router, connect_address, sizeof connect_address);
// setup dealer
void *dealer = test_context_socket (ZMQ_DEALER);
const char *dealer_routing_id = "X";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (dealer, ZMQ_ROUTING_ID, dealer_routing_id, 1));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, connect_address));
// send multipart message, the 2nd part causes a disconnect.
send_string_expect_success (dealer, "Hello2", ZMQ_SNDMORE);
send_string_expect_success (dealer, long_str, 0);
// disconnect notification
recv_string_expect_success (router, dealer_routing_id, 0);
recv_string_expect_success (router, "", 0);
test_context_socket_close (dealer);
test_context_socket_close (router);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_sockopt_router_notify);
RUN_TEST (test_router_notify_connect);
RUN_TEST (test_router_notify_disconnect);
RUN_TEST (test_router_notify_both);
RUN_TEST (test_handshake_fail);
RUN_TEST (test_error_during_multipart);
return UNITY_END ();
}

View File

@@ -0,0 +1,88 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_scatter_gather_multipart_fails ()
{
void *scatter = test_context_socket (ZMQ_SCATTER);
void *gather = test_context_socket (ZMQ_GATHER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (scatter, "inproc://test-scatter-gather"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (gather, "inproc://test-scatter-gather"));
// Should fail, multipart is not supported
TEST_ASSERT_FAILURE_ERRNO (EINVAL,
zmq_send_const (scatter, "1", 1, ZMQ_SNDMORE));
test_context_socket_close (scatter);
test_context_socket_close (gather);
}
void test_scatter_gather ()
{
void *scatter = test_context_socket (ZMQ_SCATTER);
void *gather = test_context_socket (ZMQ_GATHER);
void *gather2 = test_context_socket (ZMQ_GATHER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (scatter, "inproc://test-scatter-gather"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (gather, "inproc://test-scatter-gather"));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (gather2, "inproc://test-scatter-gather"));
send_string_expect_success (scatter, "1", 0);
send_string_expect_success (scatter, "2", 0);
recv_string_expect_success (gather, "1", 0);
recv_string_expect_success (gather2, "2", 0);
test_context_socket_close (scatter);
test_context_socket_close (gather);
test_context_socket_close (gather2);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_scatter_gather);
RUN_TEST (test_scatter_gather_multipart_fails);
return UNITY_END ();
}

608
vendor/ZMQ/tests/test_security_curve.cpp vendored Normal file
View File

@@ -0,0 +1,608 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// TODO remove this workaround for handling libsodium/tweetnacl
// To define SIZE_MAX with older compilers
#define __STDC_LIMIT_MACROS
#if defined ZMQ_CUSTOM_PLATFORM_HPP
#include "platform.hpp"
#else
#include "../src/platform.hpp"
#endif
#ifndef ZMQ_USE_TWEETNACL
#define ZMQ_USE_TWEETNACL
#endif
#ifdef ZMQ_USE_LIBSODIUM
#undef ZMQ_USE_LIBSODIUM
#endif
#include "testutil.hpp"
#include "testutil_security.hpp"
#include <unity.h>
#include "../src/tweetnacl.h"
#include "../src/curve_client_tools.hpp"
#include "../src/random.hpp"
char error_message_buffer[256];
void *handler;
void *zap_thread;
void *server;
void *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
void setUp ()
{
setup_test_context ();
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
my_endpoint);
}
void tearDown ()
{
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
teardown_test_context ();
}
const int timeout = 250;
const char large_routing_id[] = "0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"0123456789012345678901234567890123456789"
"012345678901234";
static void zap_handler_large_routing_id (void * /*unused_*/)
{
zap_handler_generic (zap_ok, large_routing_id);
}
void expect_new_client_curve_bounce_fail (const char *server_public_,
const char *client_public_,
const char *client_secret_,
char *my_endpoint_,
void *server_,
void **client_mon_ = NULL,
int expected_client_event_ = 0,
int expected_client_value_ = 0)
{
curve_client_data_t curve_client_data = {server_public_, client_public_,
client_secret_};
expect_new_client_bounce_fail (
my_endpoint_, server_, socket_config_curve_client, &curve_client_data,
client_mon_, expected_client_event_, expected_client_value_);
}
void test_null_key (void *server_,
void *server_mon_,
char *my_endpoint_,
char *server_public_,
char *client_public_,
char *client_secret_)
{
expect_new_client_curve_bounce_fail (server_public_, client_public_,
client_secret_, my_endpoint_, server_);
int handshake_failed_encryption_event_count =
expect_monitor_event_multiple (server_mon_,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
// handshake_failed_encryption_event_count should be at least two because
// expect_bounce_fail involves two exchanges
// however, with valgrind we see only one event (maybe the next one takes
// very long, or does not happen at all because something else takes very
// long)
fprintf (stderr,
"count of "
"ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL/"
"ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC events: %i\n",
handshake_failed_encryption_event_count);
}
void test_curve_security_with_valid_credentials ()
{
curve_client_data_t curve_client_data = {
valid_server_public, valid_client_public, valid_client_secret};
void *client_mon;
void *client = create_and_connect_client (
my_endpoint, socket_config_curve_client, &curve_client_data, &client_mon);
bounce (server, client);
test_context_socket_close (client);
int event = get_monitor_event_with_timeout (server_mon, NULL, NULL, -1);
assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
assert_no_more_monitor_events_with_timeout (server_mon, timeout);
event = get_monitor_event_with_timeout (client_mon, NULL, NULL, -1);
assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
assert_no_more_monitor_events_with_timeout (client_mon, timeout);
test_context_socket_close (client_mon);
}
void test_curve_security_with_bogus_client_credentials ()
{
// This must be caught by the ZAP handler
char bogus_public[41];
char bogus_secret[41];
zmq_curve_keypair (bogus_public, bogus_secret);
expect_new_client_curve_bounce_fail (
valid_server_public, bogus_public, bogus_secret, my_endpoint, server,
NULL, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
int server_event_count = 0;
server_event_count = expect_monitor_event_multiple (
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 400);
TEST_ASSERT_LESS_OR_EQUAL_INT (1, server_event_count);
// there may be more than one ZAP request due to repeated attempts by the client
TEST_ASSERT (0 == server_event_count
|| 1 <= zmq_atomic_counter_value (zap_requests_handled));
}
void expect_zmtp_mechanism_mismatch (void *client_,
char *my_endpoint_,
void *server_,
void *server_mon_)
{
// This must be caught by the curve_server class, not passed to ZAP
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client_, my_endpoint_));
expect_bounce_fail (server_, client_);
test_context_socket_close_zero_linger (client_);
expect_monitor_event_multiple (server_mon_,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH);
TEST_ASSERT_EQUAL_INT (0, zmq_atomic_counter_value (zap_requests_handled));
}
void test_curve_security_with_null_client_credentials ()
{
void *client = test_context_socket (ZMQ_DEALER);
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
}
void test_curve_security_with_plain_client_credentials ()
{
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8));
expect_zmtp_mechanism_mismatch (client, my_endpoint, server, server_mon);
}
void test_curve_security_unauthenticated_message ()
{
// Unauthenticated messages from a vanilla socket shouldn't be received
fd_t s = connect_socket (my_endpoint);
// send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received
send (s, "\x08\x00sneaky\0", 9, 0);
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
char *buf = s_recv (server);
TEST_ASSERT_NULL_MESSAGE (buf, "Received unauthenticated message");
close (s);
}
void send_all (fd_t fd_, const char *data_, socket_size_t size_)
{
while (size_ > 0) {
int res = send (fd_, data_, size_, 0);
TEST_ASSERT_GREATER_THAN_INT (0, res);
size_ -= res;
data_ += res;
}
}
template <size_t N> void send (fd_t fd_, const char (&data_)[N])
{
send_all (fd_, data_, N - 1);
}
template <size_t N> void send (fd_t fd_, const uint8_t (&data_)[N])
{
send_all (fd_, reinterpret_cast<const char *> (&data_), N);
}
void test_curve_security_invalid_hello_wrong_length ()
{
fd_t s = connect_socket (my_endpoint);
send (s, zmtp_greeting_curve);
// send CURVE HELLO of wrong size
send (s, "\x04\x06\x05HELLO");
expect_monitor_event_multiple (
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
close (s);
}
const size_t hello_length = 200;
const size_t welcome_length = 168;
zmq::curve_client_tools_t make_curve_client_tools ()
{
uint8_t valid_client_secret_decoded[32];
uint8_t valid_client_public_decoded[32];
zmq_z85_decode (valid_client_public_decoded, valid_client_public);
zmq_z85_decode (valid_client_secret_decoded, valid_client_secret);
uint8_t valid_server_public_decoded[32];
zmq_z85_decode (valid_server_public_decoded, valid_server_public);
return zmq::curve_client_tools_t (valid_client_public_decoded,
valid_client_secret_decoded,
valid_server_public_decoded);
}
// same as htonll, which is only available on few platforms (recent Windows, but not on Linux, e.g.(
static uint64_t host_to_network (uint64_t value_)
{
// The answer is 42
static const int num = 42;
// Check the endianness
if (*reinterpret_cast<const char *> (&num) == num) {
const uint32_t high_part = htonl (static_cast<uint32_t> (value_ >> 32));
const uint32_t low_part =
htonl (static_cast<uint32_t> (value_ & 0xFFFFFFFFLL));
return (static_cast<uint64_t> (low_part) << 32) | high_part;
}
return value_;
}
template <size_t N> void send_command (fd_t s_, char (&command_)[N])
{
if (N < 256) {
send (s_, "\x04");
char len = (char) N;
send_all (s_, &len, 1);
} else {
send (s_, "\x06");
uint64_t len = host_to_network (N);
send_all (s_, reinterpret_cast<char *> (&len), 8);
}
send_all (s_, command_, N);
}
void test_curve_security_invalid_hello_command_name ()
{
fd_t s = connect_socket (my_endpoint);
send (s, zmtp_greeting_curve);
zmq::curve_client_tools_t tools = make_curve_client_tools ();
// send CURVE HELLO with a misspelled command name (but otherwise correct)
char hello[hello_length];
TEST_ASSERT_SUCCESS_ERRNO (tools.produce_hello (hello, 0));
hello[5] = 'X';
send_command (s, hello);
expect_monitor_event_multiple (server_mon,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
close (s);
}
void test_curve_security_invalid_hello_version ()
{
fd_t s = connect_socket (my_endpoint);
send (s, zmtp_greeting_curve);
zmq::curve_client_tools_t tools = make_curve_client_tools ();
// send CURVE HELLO with a wrong version number (but otherwise correct)
char hello[hello_length];
TEST_ASSERT_SUCCESS_ERRNO (tools.produce_hello (hello, 0));
hello[6] = 2;
send_command (s, hello);
expect_monitor_event_multiple (
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO);
close (s);
}
void flush_read (fd_t fd_)
{
int res;
char buf[256];
while ((res = recv (fd_, buf, 256, 0)) == 256) {
}
TEST_ASSERT_NOT_EQUAL (-1, res);
}
void recv_all (fd_t fd_, uint8_t *data_, socket_size_t len_)
{
socket_size_t received = 0;
while (received < len_) {
int res = recv (fd_, reinterpret_cast<char *> (data_), len_, 0);
TEST_ASSERT_GREATER_THAN_INT (0, res);
data_ += res;
received += res;
}
}
void recv_greeting (fd_t fd_)
{
uint8_t greeting[64];
recv_all (fd_, greeting, 64);
// TODO assert anything about the greeting received from the server?
}
fd_t connect_exchange_greeting_and_send_hello (
char *my_endpoint_, zmq::curve_client_tools_t &tools_)
{
fd_t s = connect_socket (my_endpoint_);
send (s, zmtp_greeting_curve);
recv_greeting (s);
// send valid CURVE HELLO
char hello[hello_length];
TEST_ASSERT_SUCCESS_ERRNO (tools_.produce_hello (hello, 0));
send_command (s, hello);
return s;
}
void test_curve_security_invalid_initiate_wrong_length ()
{
zmq::curve_client_tools_t tools = make_curve_client_tools ();
fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint, tools);
// receive but ignore WELCOME
flush_read (s);
int res = get_monitor_event_with_timeout (server_mon, NULL, NULL, timeout);
TEST_ASSERT_EQUAL_INT (-1, res);
send (s, "\x04\x09\x08INITIATE");
expect_monitor_event_multiple (
server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE);
close (s);
}
fd_t connect_exchange_greeting_and_hello_welcome (
char *my_endpoint_,
void *server_mon_,
int timeout_,
zmq::curve_client_tools_t &tools_)
{
fd_t s = connect_exchange_greeting_and_send_hello (my_endpoint_, tools_);
// receive but ignore WELCOME
uint8_t welcome[welcome_length + 2];
recv_all (s, welcome, welcome_length + 2);
uint8_t cn_precom[crypto_box_BEFORENMBYTES];
TEST_ASSERT_SUCCESS_ERRNO (
tools_.process_welcome (welcome + 2, welcome_length, cn_precom));
const int res =
get_monitor_event_with_timeout (server_mon_, NULL, NULL, timeout_);
TEST_ASSERT_EQUAL_INT (-1, res);
return s;
}
void test_curve_security_invalid_initiate_command_name ()
{
zmq::curve_client_tools_t tools = make_curve_client_tools ();
fd_t s = connect_exchange_greeting_and_hello_welcome (
my_endpoint, server_mon, timeout, tools);
char initiate[257];
tools.produce_initiate (initiate, 257, 1, NULL, 0);
// modify command name
initiate[5] = 'X';
send_command (s, initiate);
expect_monitor_event_multiple (server_mon,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
close (s);
}
void test_curve_security_invalid_initiate_command_encrypted_cookie ()
{
zmq::curve_client_tools_t tools = make_curve_client_tools ();
fd_t s = connect_exchange_greeting_and_hello_welcome (
my_endpoint, server_mon, timeout, tools);
char initiate[257];
tools.produce_initiate (initiate, 257, 1, NULL, 0);
// make garbage from encrypted cookie
initiate[30] = !initiate[30];
send_command (s, initiate);
expect_monitor_event_multiple (server_mon,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
close (s);
}
void test_curve_security_invalid_initiate_command_encrypted_content ()
{
zmq::curve_client_tools_t tools = make_curve_client_tools ();
fd_t s = connect_exchange_greeting_and_hello_welcome (
my_endpoint, server_mon, timeout, tools);
char initiate[257];
tools.produce_initiate (initiate, 257, 1, NULL, 0);
// make garbage from encrypted content
initiate[150] = !initiate[150];
send_command (s, initiate);
expect_monitor_event_multiple (server_mon,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL,
ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC);
close (s);
}
void test_curve_security_invalid_keysize (void *ctx_)
{
// Check return codes for invalid buffer sizes
void *client = zmq_socket (ctx_, ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (client);
errno = 0;
int rc =
zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, valid_server_public, 123);
assert (rc == -1 && errno == EINVAL);
errno = 0;
rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, valid_client_public, 123);
assert (rc == -1 && errno == EINVAL);
errno = 0;
rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, valid_client_secret, 123);
assert (rc == -1 && errno == EINVAL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (client));
}
// TODO why isn't this const?
char null_key[] = "0000000000000000000000000000000000000000";
void test_null_server_key ()
{
// Check CURVE security with a null server key
// This will be caught by the curve_server class, not passed to ZAP
test_null_key (server, server_mon, my_endpoint, null_key,
valid_client_public, valid_client_secret);
}
void test_null_client_public_key ()
{
// Check CURVE security with a null client public key
// This will be caught by the curve_server class, not passed to ZAP
test_null_key (server, server_mon, my_endpoint, valid_server_public,
null_key, valid_client_secret);
}
void test_null_client_secret_key ()
{
// Check CURVE security with a null client public key
// This will be caught by the curve_server class, not passed to ZAP
test_null_key (server, server_mon, my_endpoint, valid_server_public,
valid_client_public, null_key);
}
int main (void)
{
if (!zmq_has ("curve")) {
printf ("CURVE encryption not installed, skipping test\n");
return 0;
}
zmq::random_open ();
setup_testutil_security_curve ();
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_curve_security_with_valid_credentials);
RUN_TEST (test_null_server_key);
RUN_TEST (test_null_client_public_key);
RUN_TEST (test_null_client_secret_key);
RUN_TEST (test_curve_security_with_bogus_client_credentials);
RUN_TEST (test_curve_security_with_null_client_credentials);
RUN_TEST (test_curve_security_with_plain_client_credentials);
RUN_TEST (test_curve_security_unauthenticated_message);
// tests with misbehaving CURVE client
RUN_TEST (test_curve_security_invalid_hello_wrong_length);
RUN_TEST (test_curve_security_invalid_hello_command_name);
RUN_TEST (test_curve_security_invalid_hello_version);
RUN_TEST (test_curve_security_invalid_initiate_wrong_length);
RUN_TEST (test_curve_security_invalid_initiate_command_name);
RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_cookie);
RUN_TEST (test_curve_security_invalid_initiate_command_encrypted_content);
// TODO this requires a deviating test setup, must be moved to a separate executable/fixture
// test with a large routing id (resulting in large metadata)
fprintf (stderr,
"test_curve_security_with_valid_credentials (large routing id)\n");
setup_test_context ();
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
my_endpoint, &zap_handler_large_routing_id,
&socket_config_curve_server,
&valid_server_secret, large_routing_id);
test_curve_security_with_valid_credentials ();
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
teardown_test_context ();
void *ctx = zmq_ctx_new ();
test_curve_security_invalid_keysize (ctx);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
zmq::random_close ();
return UNITY_END ();
}

View File

@@ -0,0 +1,274 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_monitoring.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
// This test requires a KRB5 environment with the following
// service principal (substitute your host.domain and REALM):
//
// zmqtest2/host.domain@REALM (host.domain should be host running test)
//
// Export keys for this principal to a keytab file and set the environment
// variables KRB5_KTNAME and KRB5_CLIENT_KTNAME to FILE:/path/to/your/keytab.
// The test will use it both for client and server roles.
//
// The test is derived in large part from test_security_curve.cpp
const char *name = "zmqtest2";
static volatile int zap_deny_all = 0;
// --------------------------------------------------------------------------
// This methods receives and validates ZAP requestes (allowing or denying
// each client connection).
// N.B. on failure, each crypto type in keytab will be tried
static void zap_handler (void *handler_)
{
// Process ZAP requests forever
while (true) {
char *version = s_recv (handler_);
if (!version)
break; // Terminating
char *sequence = s_recv (handler_);
char *domain = s_recv (handler_);
char *address = s_recv (handler_);
char *routing_id = s_recv (handler_);
char *mechanism = s_recv (handler_);
char *principal = s_recv (handler_);
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("GSSAPI", mechanism);
send_string_expect_success (handler_, version, ZMQ_SNDMORE);
send_string_expect_success (handler_, sequence, ZMQ_SNDMORE);
if (!zap_deny_all) {
send_string_expect_success (handler_, "200", ZMQ_SNDMORE);
send_string_expect_success (handler_, "OK", ZMQ_SNDMORE);
send_string_expect_success (handler_, "anonymous", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", 0);
//fprintf (stderr, "ALLOW %s\n", principal);
} else {
send_string_expect_success (handler_, "400", ZMQ_SNDMORE);
send_string_expect_success (handler_, "Denied", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", 0);
//fprintf (stderr, "DENY %s\n", principal);
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
free (principal);
}
zmq_close (handler_);
}
static char my_endpoint[MAX_SOCKET_STRING];
static void *zap_thread;
static void *server;
static void *server_mon;
void check_krb_available ()
{
if (!getenv ("KRB5_KTNAME") || !getenv ("KRB5_CLIENT_KTNAME")) {
TEST_IGNORE_MESSAGE ("KRB5 environment unavailable, skipping test");
}
}
void setUp ()
{
setup_test_context ();
zap_thread = 0;
server = NULL;
server_mon = NULL;
check_krb_available ();
// Spawn ZAP handler
// We create and bind ZAP socket in main thread to avoid case
// where child thread does not start up fast enough.
void *handler = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
zap_thread = zmq_threadstart (&zap_handler, handler);
// Server socket will accept connections
server = test_context_socket (ZMQ_DEALER);
int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_GSSAPI_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1));
int name_type = ZMQ_GSSAPI_NT_HOSTBASED;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type, sizeof (name_type)));
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
// Monitor handshake events on the server
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
server, "inproc://monitor-server",
ZMQ_EVENT_HANDSHAKE_SUCCEEDED | ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
| ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL));
// Create socket for collecting monitor events
server_mon = test_context_socket (ZMQ_PAIR);
// Connect it to the inproc endpoints so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (server_mon, "inproc://monitor-server"));
}
void tearDown ()
{
// Shutdown
if (server_mon)
test_context_socket_close_zero_linger (server_mon);
if (server)
test_context_socket_close (server);
teardown_test_context ();
// Wait until ZAP handler terminates
if (zap_thread)
zmq_threadclose (zap_thread);
}
void test_valid_creds ()
{
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_GSSAPI_SERVICE_PRINCIPAL, name, strlen (name) + 1));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1));
int name_type = ZMQ_GSSAPI_NT_HOSTBASED;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type, sizeof (name_type)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
test_context_socket_close (client);
int event = get_monitor_event (server_mon, NULL, NULL);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_HANDSHAKE_SUCCEEDED, event);
}
// Check security with valid but unauthorized credentials
// Note: ZAP may see multiple requests - after a failure, client will
// fall back to other crypto types for principal, if available.
void test_unauth_creds ()
{
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_GSSAPI_SERVICE_PRINCIPAL, name, strlen (name) + 1));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1));
int name_type = ZMQ_GSSAPI_NT_HOSTBASED;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type, sizeof (name_type)));
zap_deny_all = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
int event = get_monitor_event (server_mon, NULL, NULL);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, event);
}
// Check GSSAPI security with NULL client credentials
// This must be caught by the gssapi_server class, not passed to ZAP
void test_null_creds ()
{
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
int error;
int event = get_monitor_event (server_mon, &error, NULL);
TEST_ASSERT_EQUAL_INT (ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL, event);
TEST_ASSERT_EQUAL_INT (ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH, error);
}
// Check GSSAPI security with PLAIN client credentials
// This must be caught by the curve_server class, not passed to ZAP
void test_plain_creds ()
{
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
}
// Unauthenticated messages from a vanilla socket shouldn't be received
void test_vanilla_socket ()
{
fd_t s = connect_socket (my_endpoint);
// send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received
send (s, "\x08\x00sneaky\0", 9, 0);
int timeout = 250;
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
char *buf = s_recv (server);
if (buf != NULL) {
printf ("Received unauthenticated message: %s\n", buf);
TEST_ASSERT_NULL (buf);
}
close (s);
}
int main (void)
{
// Avoid entanglements with user's credential cache
setenv ("KRB5CCNAME", "MEMORY", 1);
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_valid_creds);
RUN_TEST (test_null_creds);
RUN_TEST (test_plain_creds);
RUN_TEST (test_vanilla_socket);
RUN_TEST (test_unauth_creds);
return UNITY_END ();
}

View File

@@ -0,0 +1,82 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
void test_no_zap_handler ()
{
// We first test client/server with a ZAP domain but with no handler
// If there is no handler, libzmq should ignore the ZAP option unless
// ZMQ_ZAP_ENFORCE_DOMAIN is set
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 5));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
}
void test_no_zap_handler_enforce_domain ()
{
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
// Now set ZMQ_ZAP_ENFORCE_DOMAIN which strictly enforces the ZAP
// RFC but is backward-incompatible, now it should fail
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
int required = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_ENFORCE_DOMAIN, &required, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 5));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
#endif
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_no_zap_handler);
RUN_TEST (test_no_zap_handler_enforce_domain);
return UNITY_END ();
}

199
vendor/ZMQ/tests/test_security_null.cpp vendored Normal file
View File

@@ -0,0 +1,199 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#if defined(ZMQ_HAVE_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdexcept>
#define close closesocket
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdlib.h>
static void zap_handler (void *handler_)
{
// Process ZAP requests forever
while (true) {
char *version = s_recv (handler_);
if (!version)
break; // Terminating
char *sequence = s_recv (handler_);
char *domain = s_recv (handler_);
char *address = s_recv (handler_);
char *routing_id = s_recv (handler_);
char *mechanism = s_recv (handler_);
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("NULL", mechanism);
send_string_expect_success (handler_, version, ZMQ_SNDMORE);
send_string_expect_success (handler_, sequence, ZMQ_SNDMORE);
if (streq (domain, "TEST")) {
send_string_expect_success (handler_, "200", ZMQ_SNDMORE);
send_string_expect_success (handler_, "OK", ZMQ_SNDMORE);
send_string_expect_success (handler_, "anonymous", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", 0);
} else {
send_string_expect_success (handler_, "400", ZMQ_SNDMORE);
send_string_expect_success (handler_, "BAD DOMAIN", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", ZMQ_SNDMORE);
send_string_expect_success (handler_, "", 0);
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
}
close_zero_linger (handler_);
}
void *zap_thread;
static void setup_zap_handler ()
{
// Spawn ZAP handler
// We create and bind ZAP socket in main thread to avoid case
// where child thread does not start up fast enough.
void *handler = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
zap_thread = zmq_threadstart (&zap_handler, handler);
}
static void teardown_zap_handler ()
{
// Wait until ZAP handler terminates
zmq_threadclose (zap_thread);
}
void setUp ()
{
setup_test_context ();
setup_zap_handler ();
}
void tearDown ()
{
teardown_test_context ();
teardown_zap_handler ();
}
void test_no_domain ()
{
// We first test client/server with no ZAP domain
// Libzmq does not call our ZAP handler, the connect must succeed
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
}
void test_wrong_domain_fails ()
{
// Now define a ZAP domain for the server; this enables
// authentication. We're using the wrong domain so this test
// must fail.
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
}
void test_success ()
{
// Now use the right domain, the test must pass
void *server = test_context_socket (ZMQ_DEALER);
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 4));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
test_context_socket_close_zero_linger (client);
test_context_socket_close_zero_linger (server);
}
void test_vanilla_socket ()
{
// Unauthenticated messages from a vanilla socket shouldn't be received
void *server = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5));
char my_endpoint[MAX_SOCKET_STRING];
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
fd_t s = connect_socket (my_endpoint);
// send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received
send (s, "\x08\x00sneaky\0", 9, 0);
int timeout = 250;
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
char *buf = s_recv (server);
if (buf != NULL) {
printf ("Received unauthenticated message: %s\n", buf);
TEST_ASSERT_NULL (buf);
}
close (s);
test_context_socket_close_zero_linger (server);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_no_domain);
RUN_TEST (test_wrong_domain_fails);
RUN_TEST (test_success);
RUN_TEST (test_vanilla_socket);
return UNITY_END ();
}

211
vendor/ZMQ/tests/test_security_plain.cpp vendored Normal file
View File

@@ -0,0 +1,211 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
static void zap_handler (void *zap_)
{
// Process ZAP requests forever
while (true) {
char *version = s_recv (zap_);
if (!version)
break; // Terminating
char *sequence = s_recv (zap_);
char *domain = s_recv (zap_);
char *address = s_recv (zap_);
char *routing_id = s_recv (zap_);
char *mechanism = s_recv (zap_);
char *username = s_recv (zap_);
char *password = s_recv (zap_);
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("PLAIN", mechanism);
TEST_ASSERT_EQUAL_STRING ("IDENT", routing_id);
send_string_expect_success (zap_, version, ZMQ_SNDMORE);
send_string_expect_success (zap_, sequence, ZMQ_SNDMORE);
if (streq (username, "admin") && streq (password, "password")) {
send_string_expect_success (zap_, "200", ZMQ_SNDMORE);
send_string_expect_success (zap_, "OK", ZMQ_SNDMORE);
send_string_expect_success (zap_, "anonymous", ZMQ_SNDMORE);
send_string_expect_success (zap_, "", 0);
} else {
send_string_expect_success (zap_, "400", ZMQ_SNDMORE);
send_string_expect_success (zap_, "Invalid username or password",
ZMQ_SNDMORE);
send_string_expect_success (zap_, "", ZMQ_SNDMORE);
send_string_expect_success (zap_, "", 0);
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
free (username);
free (password);
}
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (zap_));
}
void *zap_thread;
char my_endpoint[MAX_SOCKET_STRING];
static void setup_zap_handler ()
{
// Spawn ZAP handler
// We create and bind ZAP socket in main thread to avoid case
// where child thread does not start up fast enough.
void *handler = zmq_socket (get_test_context (), ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01"));
zap_thread = zmq_threadstart (&zap_handler, handler);
}
static void teardown_zap_handler ()
{
// Wait until ZAP handler terminates
zmq_threadclose (zap_thread);
}
const char domain[] = "test";
void *server;
static void setup_server ()
{
// Server socket will accept connections
server = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ROUTING_ID, "IDENT", 6));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, domain, strlen (domain)));
const int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
bind_loopback_ipv4 (server, my_endpoint, sizeof my_endpoint);
}
static void teardown_server ()
{
test_context_socket_close (server);
}
void setUp ()
{
setup_test_context ();
setup_zap_handler ();
setup_server ();
}
void tearDown ()
{
teardown_server ();
teardown_test_context ();
teardown_zap_handler ();
}
void test_plain_success ()
{
// Check PLAIN security with correct username/password
void *client = test_context_socket (ZMQ_DEALER);
const char username[] = "admin";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)));
const char password[] = "password";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
bounce (server, client);
test_context_socket_close (client);
}
void test_plain_client_as_server_fails ()
{
// Check PLAIN security with badly configured client (as_server)
// This will be caught by the plain_server class, not passed to ZAP
void *client = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_ZAP_DOMAIN, domain, strlen (domain)));
const int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
}
void test_plain_wrong_credentials_fails ()
{
// Check PLAIN security -- failed authentication
void *client = test_context_socket (ZMQ_DEALER);
const char username[] = "wronguser";
const char password[] = "wrongpass";
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
}
void test_plain_vanilla_socket ()
{
// Unauthenticated messages from a vanilla socket shouldn't be received
fd_t s = connect_socket (my_endpoint);
// send anonymous ZMTP/1.0 greeting
send (s, "\x01\x00", 2, 0);
// send sneaky message that shouldn't be received
send (s, "\x08\x00sneaky\0", 9, 0);
int timeout = 250;
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
char *buf = s_recv (server);
if (buf != NULL) {
printf ("Received unauthenticated message: %s\n", buf);
TEST_ASSERT_NULL (buf);
}
close (s);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_plain_success);
RUN_TEST (test_plain_client_as_server_fails);
RUN_TEST (test_plain_wrong_credentials_fails);
RUN_TEST (test_plain_vanilla_socket);
return UNITY_END ();
}

472
vendor/ZMQ/tests/test_security_zap.cpp vendored Normal file
View File

@@ -0,0 +1,472 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil_security.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
static void zap_handler_wrong_version (void * /*unused_*/)
{
zap_handler_generic (zap_wrong_version);
}
static void zap_handler_wrong_request_id (void * /*unused_*/)
{
zap_handler_generic (zap_wrong_request_id);
}
static void zap_handler_wrong_status_invalid (void * /*unused_*/)
{
zap_handler_generic (zap_status_invalid);
}
static void zap_handler_wrong_status_temporary_failure (void * /*unused_*/)
{
zap_handler_generic (zap_status_temporary_failure);
}
static void zap_handler_wrong_status_internal_error (void * /*unused_*/)
{
zap_handler_generic (zap_status_internal_error);
}
static void zap_handler_too_many_parts (void * /*unused_*/)
{
zap_handler_generic (zap_too_many_parts);
}
static void zap_handler_disconnect (void * /*unused_*/)
{
zap_handler_generic (zap_disconnect);
}
static void zap_handler_do_not_recv (void * /*unused_*/)
{
zap_handler_generic (zap_do_not_recv);
}
static void zap_handler_do_not_send (void * /*unused_*/)
{
zap_handler_generic (zap_do_not_send);
}
int expect_new_client_bounce_fail_and_count_monitor_events (
char *my_endpoint_,
void *server_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_,
void *server_mon_,
int expected_server_event_,
int expected_server_value_,
int expected_client_event_ = 0,
int expected_client_value_ = 0)
{
expect_new_client_bounce_fail (
my_endpoint_, server_, socket_config_, socket_config_data_, client_mon_,
expected_client_event_, expected_client_value_);
int events_received = 0;
events_received = expect_monitor_event_multiple (
server_mon_, expected_server_event_, expected_server_value_);
return events_received;
}
void test_zap_unsuccessful (char *my_endpoint_,
void *server_,
void *server_mon_,
int expected_server_event_,
int expected_server_value_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_ = NULL,
int expected_client_event_ = 0,
int expected_client_value_ = 0)
{
int server_events_received =
expect_new_client_bounce_fail_and_count_monitor_events (
my_endpoint_, server_, socket_config_, socket_config_data_, client_mon_,
server_mon_, expected_server_event_, expected_server_value_,
expected_client_event_, expected_client_value_);
// there may be more than one ZAP request due to repeated attempts by the
// client (actually only in case if ZAP status code 300)
TEST_ASSERT_TRUE (server_events_received == 0
|| 1 <= zmq_atomic_counter_value (zap_requests_handled));
}
void test_zap_unsuccessful_no_handler (char *my_endpoint_,
void *server_,
void *server_mon_,
int expected_event_,
int expected_err_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_ = NULL)
{
const int events_received =
expect_new_client_bounce_fail_and_count_monitor_events (
my_endpoint_, server_, socket_config_, socket_config_data_, client_mon_,
server_mon_, expected_event_, expected_err_);
// there may be more than one ZAP request due to repeated attempts by the
// client
TEST_ASSERT_GREATER_THAN_INT (0, events_received);
}
void test_zap_protocol_error (char *my_endpoint_,
void *server_,
void *server_mon_,
socket_config_fn socket_config_,
void *socket_config_data_,
int expected_error_)
{
test_zap_unsuccessful (my_endpoint_, server_, server_mon_,
ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL, expected_error_,
socket_config_, socket_config_data_);
}
void test_zap_unsuccessful_status_300 (char *my_endpoint_,
void *server_,
void *server_mon_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
void *client_mon;
test_zap_unsuccessful (
my_endpoint_, server_, server_mon_, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 300,
client_socket_config_, client_socket_config_data_, &client_mon);
// we can use a 0 timeout here, since the client socket is already closed
assert_no_more_monitor_events_with_timeout (client_mon, 0);
test_context_socket_close (client_mon);
}
void test_zap_unsuccessful_status_500 (char *my_endpoint_,
void *server_,
void *server_mon_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
test_zap_unsuccessful (my_endpoint_, server_, server_mon_,
ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 500,
client_socket_config_, client_socket_config_data_,
NULL, ZMQ_EVENT_HANDSHAKE_FAILED_AUTH, 500);
}
static void
test_zap_protocol_error_closure (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_,
zmq_thread_fn zap_handler_,
int expected_failure_)
{
void *handler, *zap_thread, *server, *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
setup_context_and_server_side (
&handler, &zap_thread, &server, &server_mon, my_endpoint, zap_handler_,
server_socket_config_, server_socket_config_data_);
test_zap_protocol_error (my_endpoint, server, server_mon,
client_socket_config_, client_socket_config_data_,
expected_failure_);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
}
static void
test_zap_protocol_error_wrong_version (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
test_zap_protocol_error_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
server_socket_config_data_, &zap_handler_wrong_version,
ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION);
}
static void test_zap_protocol_error_wrong_request_id (
socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
test_zap_protocol_error_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
server_socket_config_data_, &zap_handler_wrong_request_id,
ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID);
}
static void test_zap_protocol_error_wrong_status_invalid (
socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
test_zap_protocol_error_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
server_socket_config_data_, &zap_handler_wrong_status_invalid,
ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE);
}
static void
test_zap_protocol_error_too_many_parts (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
test_zap_protocol_error_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
server_socket_config_data_, &zap_handler_too_many_parts,
ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY);
}
// TODO the failed status (300/500) should be observable as monitoring events on the client side as well (they are
// already transmitted as an ERROR message)
static void
test_zap_wrong_status_temporary_failure (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
void *handler, *zap_thread, *server, *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
setup_context_and_server_side (
&handler, &zap_thread, &server, &server_mon, my_endpoint,
&zap_handler_wrong_status_temporary_failure, server_socket_config_,
server_socket_config_data_);
test_zap_unsuccessful_status_300 (my_endpoint, server, server_mon,
client_socket_config_,
client_socket_config_data_);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
}
static void
test_zap_wrong_status_internal_error (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
void *handler, *zap_thread, *server, *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
setup_context_and_server_side (
&handler, &zap_thread, &server, &server_mon, my_endpoint,
&zap_handler_wrong_status_internal_error, server_socket_config_);
test_zap_unsuccessful_status_500 (my_endpoint, server, server_mon,
client_socket_config_,
client_socket_config_data_);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
}
static void
test_zap_unsuccesful_no_handler_started (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
void *server_socket_config_data_)
{
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
void *handler, *zap_thread, *server, *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
// TODO this looks wrong, where will the enforce value be used?
// no ZAP handler
int enforce = 1;
setup_context_and_server_side (
&handler, &zap_thread, &server, &server_mon, my_endpoint, NULL,
server_socket_config_,
server_socket_config_data_ ? server_socket_config_data_ : &enforce);
test_zap_unsuccessful_no_handler (
my_endpoint, server, server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
EFAULT, client_socket_config_, client_socket_config_data_);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler);
#endif
}
static void
test_zap_unsuccesful_no_handler_closure (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_,
zmq_thread_fn zap_handler_func_,
bool zap_handler_disconnected_ = false)
{
void *handler, *zap_thread, *server, *server_mon;
char my_endpoint[MAX_SOCKET_STRING];
setup_context_and_server_side (&handler, &zap_thread, &server, &server_mon,
my_endpoint, zap_handler_func_,
server_socket_config_);
test_zap_unsuccessful_no_handler (
my_endpoint, server, server_mon, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL,
EPIPE, client_socket_config_, client_socket_config_data_);
shutdown_context_and_server_side (zap_thread, server, server_mon, handler,
zap_handler_disconnected_);
}
static void
test_zap_unsuccesful_disconnect (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
test_zap_unsuccesful_no_handler_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
&zap_handler_disconnect, true);
}
static void
test_zap_unsuccesful_do_not_recv (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
test_zap_unsuccesful_no_handler_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
&zap_handler_do_not_recv);
}
static void
test_zap_unsuccesful_do_not_send (socket_config_fn server_socket_config_,
socket_config_fn client_socket_config_,
void *client_socket_config_data_)
{
test_zap_unsuccesful_no_handler_closure (
server_socket_config_, client_socket_config_, client_socket_config_data_,
&zap_handler_do_not_send);
}
#define DEFINE_ZAP_ERROR_TESTS( \
name_, server_socket_config_, server_socket_config_data_, \
client_socket_config_, client_socket_config_data_) \
void test_zap_protocol_error_wrong_version_##name_ () \
{ \
test_zap_protocol_error_wrong_version ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_protocol_error_wrong_request_id_##name_ () \
{ \
test_zap_protocol_error_wrong_request_id ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_protocol_error_wrong_status_invalid_##name_ () \
{ \
test_zap_protocol_error_wrong_status_invalid ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_protocol_error_too_many_parts_##name_ () \
{ \
test_zap_protocol_error_too_many_parts ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_wrong_status_temporary_failure_##name_ () \
{ \
test_zap_wrong_status_temporary_failure ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_wrong_status_internal_error_##name_ () \
{ \
test_zap_wrong_status_internal_error (server_socket_config_, \
client_socket_config_, \
client_socket_config_data_); \
} \
void test_zap_unsuccessful_no_handler_started_##name_ () \
{ \
test_zap_unsuccesful_no_handler_started ( \
server_socket_config_, client_socket_config_, \
client_socket_config_data_, server_socket_config_data_); \
} \
void test_zap_unsuccessful_disconnect_##name_ () \
{ \
test_zap_unsuccesful_disconnect (server_socket_config_, \
client_socket_config_, \
client_socket_config_data_); \
} \
void test_zap_unsuccessful_do_not_recv_##name_ () \
{ \
test_zap_unsuccesful_do_not_recv (server_socket_config_, \
client_socket_config_, \
client_socket_config_data_); \
} \
void test_zap_unsuccessful_do_not_send_##name_ () \
{ \
test_zap_unsuccesful_do_not_send (server_socket_config_, \
client_socket_config_, \
client_socket_config_data_); \
}
DEFINE_ZAP_ERROR_TESTS (
null, &socket_config_null_server, NULL, &socket_config_null_client, NULL)
DEFINE_ZAP_ERROR_TESTS (
plain, &socket_config_plain_server, NULL, &socket_config_plain_client, NULL)
static curve_client_data_t curve_client_data = {
valid_server_public, valid_client_public, valid_client_secret};
DEFINE_ZAP_ERROR_TESTS (curve,
&socket_config_curve_server,
valid_server_secret,
&socket_config_curve_client,
&curve_client_data)
#define RUN_ZAP_ERROR_TESTS(name_) \
{ \
RUN_TEST (test_zap_protocol_error_wrong_version_##name_); \
RUN_TEST (test_zap_protocol_error_wrong_request_id_##name_); \
RUN_TEST (test_zap_protocol_error_wrong_status_invalid_##name_); \
RUN_TEST (test_zap_protocol_error_too_many_parts_##name_); \
RUN_TEST (test_zap_wrong_status_temporary_failure_##name_); \
RUN_TEST (test_zap_wrong_status_internal_error_##name_); \
RUN_TEST (test_zap_unsuccessful_no_handler_started_##name_); \
RUN_TEST (test_zap_unsuccessful_disconnect_##name_); \
RUN_TEST (test_zap_unsuccessful_do_not_recv_##name_); \
RUN_TEST (test_zap_unsuccessful_do_not_send_##name_); \
}
int main ()
{
setup_test_environment ();
if (zmq_has ("curve")) {
setup_testutil_security_curve ();
}
UNITY_BEGIN ();
RUN_ZAP_ERROR_TESTS (null);
RUN_ZAP_ERROR_TESTS (plain);
if (zmq_has ("curve")) {
RUN_ZAP_ERROR_TESTS (curve);
}
return UNITY_END ();
}

185
vendor/ZMQ/tests/test_setsockopt.cpp vendored Normal file
View File

@@ -0,0 +1,185 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
SETUP_TEARDOWN_TESTCONTEXT
void test_setsockopt_tcp_recv_buffer ()
{
void *socket = test_context_socket (ZMQ_PUSH);
int val = 0;
size_t placeholder = sizeof (val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_RCVBUF, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (-1, val);
val = 16384;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_RCVBUF, &val, sizeof (val)));
TEST_ASSERT_EQUAL_INT (16384, val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_RCVBUF, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (16384, val);
test_context_socket_close (socket);
}
void test_setsockopt_tcp_send_buffer ()
{
void *socket = test_context_socket (ZMQ_PUSH);
int val = 0;
size_t placeholder = sizeof (val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_SNDBUF, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (-1, val);
val = 16384;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_SNDBUF, &val, sizeof (val)));
TEST_ASSERT_EQUAL_INT (16384, val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_SNDBUF, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (16384, val);
test_context_socket_close (socket);
}
void test_setsockopt_use_fd ()
{
void *socket = test_context_socket (ZMQ_PUSH);
int val = 0;
size_t placeholder = sizeof (val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_USE_FD, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (-1, val);
val = 3;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_USE_FD, &val, sizeof (val)));
TEST_ASSERT_EQUAL_INT (3, val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_USE_FD, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (3, val);
test_context_socket_close (socket);
}
#define BOUNDDEVBUFSZ 16
void test_setsockopt_bindtodevice ()
{
void *socket = test_context_socket (ZMQ_PUSH);
#ifdef ZMQ_BINDTODEVICE
char devname[BOUNDDEVBUFSZ];
size_t buflen = BOUNDDEVBUFSZ;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_BINDTODEVICE, devname, &buflen));
TEST_ASSERT_EQUAL_INT8 ('\0', devname[0]);
TEST_ASSERT_EQUAL_UINT (1, buflen);
sprintf (devname, "testdev");
buflen = strlen (devname);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_BINDTODEVICE, devname, buflen));
buflen = BOUNDDEVBUFSZ;
memset (devname, 0, buflen);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_BINDTODEVICE, devname, &buflen));
TEST_ASSERT_EQUAL_STRING_LEN ("testdev", devname, buflen);
#endif
test_context_socket_close (socket);
}
void test_setsockopt_priority ()
{
#ifdef ZMQ_BUILD_DRAFT_API
#ifdef ZMQ_HAVE_SO_PRIORITY
void *socket = test_context_socket (ZMQ_PUSH);
int val = 5;
size_t placeholder = sizeof (val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_PRIORITY, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (0, val);
val = 3;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_PRIORITY, &val, sizeof (val)));
TEST_ASSERT_EQUAL_INT (3, val);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket, ZMQ_PRIORITY, &val, &placeholder));
TEST_ASSERT_EQUAL_INT (3, val);
test_context_socket_close (socket);
#else
TEST_IGNORE_MESSAGE ("libzmq without ZMQ_PRIORITY support, "
"ignoring setsockopt_priority test");
#endif
#else
TEST_IGNORE_MESSAGE ("libzmq without DRAFT support, ignoring "
"setsockopt_priority test");
#endif
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_setsockopt_tcp_recv_buffer);
RUN_TEST (test_setsockopt_tcp_send_buffer);
RUN_TEST (test_setsockopt_use_fd);
RUN_TEST (test_setsockopt_bindtodevice);
RUN_TEST (test_setsockopt_priority);
return UNITY_END ();
}

View File

@@ -0,0 +1,97 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
}
void tearDown ()
{
}
#define THREAD_COUNT 100
struct thread_data
{
char endpoint[MAX_SOCKET_STRING];
};
extern "C" {
static void worker (void *data_)
{
const thread_data *const tdata = static_cast<const thread_data *> (data_);
void *socket = zmq_socket (get_test_context (), ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (socket, tdata->endpoint));
// Start closing the socket while the connecting process is underway.
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
}
}
void test_shutdown_stress ()
{
void *threads[THREAD_COUNT];
for (int j = 0; j != 10; j++) {
// Check the shutdown with many parallel I/O threads.
struct thread_data tdata;
setup_test_context ();
zmq_ctx_set (get_test_context (), ZMQ_IO_THREADS, 7);
void *socket = test_context_socket (ZMQ_PUB);
bind_loopback_ipv4 (socket, tdata.endpoint, sizeof (tdata.endpoint));
for (int i = 0; i != THREAD_COUNT; i++) {
threads[i] = zmq_threadstart (&worker, &tdata);
}
for (int i = 0; i != THREAD_COUNT; i++) {
zmq_threadclose (threads[i]);
}
test_context_socket_close (socket);
teardown_test_context ();
}
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_shutdown_stress);
return UNITY_END ();
}

View File

@@ -0,0 +1,99 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <pthread.h>
void setUp ()
{
}
void tearDown ()
{
}
#define THREAD_COUNT 100
extern "C" {
static void *worker (void *ctx)
{
void *s = zmq_socket (ctx, ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (s, "tipc://{5560,0}@0.0.0"));
// Start closing the socket while the connecting process is underway.
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (s));
return NULL;
}
}
void test_shutdown_stress_tipc ()
{
void *s1;
int i;
int j;
pthread_t threads[THREAD_COUNT];
for (j = 0; j != 10; j++) {
// Check the shutdown with many parallel I/O threads.
setup_test_context ();
zmq_ctx_set (get_test_context (), ZMQ_IO_THREADS, 7);
s1 = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s1, "tipc://{5560,0,0}"));
for (i = 0; i != THREAD_COUNT; i++) {
TEST_ASSERT_SUCCESS_RAW_ERRNO (
pthread_create (&threads[i], NULL, worker, get_test_context ()));
}
for (i = 0; i != THREAD_COUNT; i++) {
TEST_ASSERT_SUCCESS_RAW_ERRNO (pthread_join (threads[i], NULL));
}
test_context_socket_close (s1);
teardown_test_context ();
}
}
int main ()
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
}
UNITY_BEGIN ();
RUN_TEST (test_shutdown_stress_tipc);
return UNITY_END ();
}

145
vendor/ZMQ/tests/test_socket_null.cpp vendored Normal file
View File

@@ -0,0 +1,145 @@
/*
Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include <unity.h>
void setUp ()
{
}
void tearDown ()
{
}
// tests all socket-related functions with a NULL socket argument
void test_zmq_socket_null_context ()
{
TEST_ASSERT_NULL (zmq_socket (NULL, ZMQ_PAIR));
TEST_ASSERT_EQUAL_INT (EFAULT, errno); // TODO use EINVAL instead?
}
void test_zmq_close_null_socket ()
{
int rc = zmq_close (NULL);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_setsockopt_null_socket ()
{
int hwm = 100;
size_t hwm_size = sizeof hwm;
int rc = zmq_setsockopt (NULL, ZMQ_SNDHWM, &hwm, hwm_size);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_getsockopt_null_socket ()
{
int hwm;
size_t hwm_size = sizeof hwm;
int rc = zmq_getsockopt (NULL, ZMQ_SNDHWM, &hwm, &hwm_size);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_socket_monitor_null_socket ()
{
int rc = zmq_socket_monitor (NULL, "inproc://monitor", ZMQ_EVENT_ALL);
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
#ifdef ZMQ_BUILD_DRAFT_API
void test_zmq_join_null_socket ()
{
int rc = zmq_join (NULL, "group");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_leave_null_socket ()
{
int rc = zmq_leave (NULL, "group");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
#endif
void test_zmq_bind_null_socket ()
{
int rc = zmq_bind (NULL, "inproc://socket");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_connect_null_socket ()
{
int rc = zmq_connect (NULL, "inproc://socket");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_unbind_null_socket ()
{
int rc = zmq_unbind (NULL, "inproc://socket");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
void test_zmq_disconnect_null_socket ()
{
int rc = zmq_disconnect (NULL, "inproc://socket");
TEST_ASSERT_EQUAL_INT (-1, rc);
TEST_ASSERT_EQUAL_INT (ENOTSOCK, errno); // TODO use EINVAL instead?
}
int main (void)
{
UNITY_BEGIN ();
RUN_TEST (test_zmq_socket_null_context);
RUN_TEST (test_zmq_close_null_socket);
RUN_TEST (test_zmq_setsockopt_null_socket);
RUN_TEST (test_zmq_getsockopt_null_socket);
RUN_TEST (test_zmq_socket_monitor_null_socket);
RUN_TEST (test_zmq_bind_null_socket);
RUN_TEST (test_zmq_connect_null_socket);
RUN_TEST (test_zmq_unbind_null_socket);
RUN_TEST (test_zmq_disconnect_null_socket);
#ifdef ZMQ_BUILD_DRAFT_API
RUN_TEST (test_zmq_join_null_socket);
RUN_TEST (test_zmq_leave_null_socket);
#endif
return UNITY_END ();
}

View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2020 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ZMQ_USE_FUZZING_ENGINE
#include <fuzzer/FuzzedDataProvider.h>
#endif
#include "testutil.hpp"
#include "testutil_unity.hpp"
#ifdef ZMQ_DISCONNECT_MSG
#define LAST_OPTION ZMQ_DISCONNECT_MSG
#else
#define LAST_OPTION ZMQ_BINDTODEVICE
#endif
extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
{
int option;
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
void *server = zmq_socket (ctx, ZMQ_XPUB);
TEST_ASSERT_NOT_NULL (server);
if (!size)
return 0;
for (option = ZMQ_AFFINITY; option <= LAST_OPTION; ++option) {
uint8_t out[8192];
size_t out_size = 8192;
zmq_setsockopt (server, option, data, size);
zmq_getsockopt (server, option, out, &out_size);
}
zmq_close (server);
zmq_ctx_term (ctx);
return 0;
}
#ifndef ZMQ_USE_FUZZING_ENGINE
void test_socket_options_fuzzer ()
{
uint8_t **data;
size_t *len, num_cases = 0;
if (fuzzer_corpus_encode (
"tests/libzmq-fuzz-corpora/test_socket_options_fuzzer_seed_corpus",
&data, &len, &num_cases)
!= 0)
exit (77);
while (num_cases-- > 0) {
TEST_ASSERT_SUCCESS_ERRNO (
LLVMFuzzerTestOneInput (data[num_cases], len[num_cases]));
free (data[num_cases]);
}
free (data);
free (len);
}
int main (int argc, char **argv)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_socket_options_fuzzer);
return UNITY_END ();
}
#endif

200
vendor/ZMQ/tests/test_sockopt_hwm.cpp vendored Normal file
View File

@@ -0,0 +1,200 @@
/*
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
This file is part of libzmq, the ZeroMQ core engine in C++.
libzmq is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
As a special exception, the Contributors give you permission to link
this library with independent modules to produce an executable,
regardless of the license terms of these independent modules, and to
copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the
terms and conditions of the license of that module. An independent
module is a module which is not derived from or based on this library.
If you modify this library, you must extend this exception to your
version of the library.
libzmq is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
SETUP_TEARDOWN_TESTCONTEXT
const int MAX_SENDS = 10000;
void test_change_before_connected ()
{
int rc;
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));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &val, sizeof (val));
TEST_ASSERT_EQUAL_INT (0, rc);
zmq_connect (connect_socket, "inproc://a");
zmq_bind (bind_socket, "inproc://a");
size_t placeholder = sizeof (val);
val = 0;
rc = zmq_getsockopt (bind_socket, ZMQ_SNDHWM, &val, &placeholder);
TEST_ASSERT_EQUAL_INT (0, rc);
TEST_ASSERT_EQUAL_INT (2, val);
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
TEST_ASSERT_EQUAL_INT (4, send_count);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}
void test_change_after_connected ()
{
int rc;
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));
TEST_ASSERT_EQUAL_INT (0, rc);
rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &val, sizeof (val));
TEST_ASSERT_EQUAL_INT (0, rc);
zmq_connect (connect_socket, "inproc://a");
zmq_bind (bind_socket, "inproc://a");
val = 5;
rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &val, sizeof (val));
TEST_ASSERT_EQUAL_INT (0, rc);
size_t placeholder = sizeof (val);
val = 0;
rc = zmq_getsockopt (bind_socket, ZMQ_SNDHWM, &val, &placeholder);
TEST_ASSERT_EQUAL_INT (0, rc);
TEST_ASSERT_EQUAL_INT (5, val);
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
++send_count;
TEST_ASSERT_EQUAL_INT (6, send_count);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}
int send_until_wouldblock (void *socket_)
{
int send_count = 0;
while (send_count < MAX_SENDS
&& zmq_send (socket_, &send_count, sizeof (send_count), ZMQ_DONTWAIT)
== sizeof (send_count)) {
++send_count;
}
return send_count;
}
int test_fill_up_to_hwm (void *socket_, int sndhwm_)
{
int send_count = send_until_wouldblock (socket_);
fprintf (stderr, "sndhwm==%i, send_count==%i\n", sndhwm_, send_count);
TEST_ASSERT_LESS_OR_EQUAL_INT (sndhwm_ + 1, send_count);
TEST_ASSERT_GREATER_THAN_INT (sndhwm_ / 10, send_count);
return send_count;
}
void test_decrease_when_full ()
{
int rc;
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));
TEST_ASSERT_EQUAL_INT (0, rc);
int sndhwm = 100;
rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &sndhwm, sizeof (sndhwm));
TEST_ASSERT_EQUAL_INT (0, rc);
zmq_bind (bind_socket, "inproc://a");
zmq_connect (connect_socket, "inproc://a");
// we must wait for the connect to succeed here, unfortunately we don't
// have monitoring events for inproc, so we just hope SETTLE_TIME suffices
msleep (SETTLE_TIME);
// Fill up to hwm
int send_count = test_fill_up_to_hwm (bind_socket, sndhwm);
// Decrease snd hwm
sndhwm = 70;
rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &sndhwm, sizeof (sndhwm));
TEST_ASSERT_EQUAL_INT (0, rc);
int sndhwm_read = 0;
size_t sndhwm_read_size = sizeof (sndhwm_read);
rc =
zmq_getsockopt (bind_socket, ZMQ_SNDHWM, &sndhwm_read, &sndhwm_read_size);
TEST_ASSERT_EQUAL_INT (0, rc);
TEST_ASSERT_EQUAL_INT (sndhwm, sndhwm_read);
msleep (SETTLE_TIME);
// Read out all data (should get up to previous hwm worth so none were dropped)
int read_count = 0;
int read_data = 0;
while (
read_count < MAX_SENDS
&& zmq_recv (connect_socket, &read_data, sizeof (read_data), ZMQ_DONTWAIT)
== sizeof (read_data)) {
TEST_ASSERT_EQUAL_INT (read_data, read_count);
++read_count;
}
TEST_ASSERT_EQUAL_INT (send_count, read_count);
// Give io thread some time to catch up
msleep (SETTLE_TIME);
// Fill up to new hwm
test_fill_up_to_hwm (bind_socket, sndhwm);
test_context_socket_close (bind_socket);
test_context_socket_close (connect_socket);
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_change_before_connected);
RUN_TEST (test_change_after_connected);
RUN_TEST (test_decrease_when_full);
return UNITY_END ();
}

Some files were not shown because too many files have changed in this diff Show More