Merge pull request #3459 from sigiesec/migrate-testutil

Migrate testutil* to Unity, and build testutil as separate library
This commit is contained in:
Luca Boccassi 2019-03-23 22:40:41 +00:00 committed by GitHub
commit 6d77558c77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 3161 additions and 2616 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ doc/Makefile
Makefile.in
configure
libtool
libtestutil.a
libunity.a
config
config.status

View File

@ -463,304 +463,316 @@ test_apps = \
UNITY_CPPFLAGS = -I$(top_srcdir)/external/unity -DUNITY_USE_COMMAND_LINE_ARGS -DUNITY_EXCLUDE_FLOAT
UNITY_LIBS = $(top_builddir)/external/unity/libunity.a
noinst_LIBRARIES = external/unity/libunity.a
external_unity_libunity_a_SOURCES = external/unity/unity.c \
external/unity/unity.h \
external/unity/unity_internals.h
TESTUTIL_CPPFLAGS = ${UNITY_CPPFLAGS}
TESTUTIL_LIBS = $(top_builddir)/tests/libtestutil.a ${UNITY_LIBS}
tests_libtestutil_a_SOURCES = \
tests/testutil.cpp \
tests/testutil.hpp \
tests/testutil_monitoring.cpp \
tests/testutil_monitoring.hpp \
tests/testutil_security.cpp \
tests/testutil_security.hpp \
tests/testutil_unity.cpp \
tests/testutil_unity.hpp
tests_libtestutil_a_CPPFLAGS = ${UNITY_CPPFLAGS}
noinst_LIBRARIES = external/unity/libunity.a tests/libtestutil.a
tests_test_ancillaries_SOURCES = tests/test_ancillaries.cpp
tests_test_ancillaries_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_ancillaries_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_ancillaries_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_ancillaries_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_system_SOURCES = tests/test_system.cpp
tests_test_system_LDADD = src/libzmq.la
tests_test_system_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_system_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pair_inproc_SOURCES = \
tests/test_pair_inproc.cpp \
tests/testutil.hpp
tests_test_pair_inproc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_pair_inproc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_pair_inproc_SOURCES = tests/test_pair_inproc.cpp
tests_test_pair_inproc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_pair_inproc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pair_tcp_SOURCES = \
tests/test_pair_tcp.cpp \
tests/testutil.hpp
tests_test_pair_tcp_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_pair_tcp_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_pair_tcp_SOURCES = tests/test_pair_tcp.cpp
tests_test_pair_tcp_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_pair_tcp_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_inproc_SOURCES = \
tests/test_reqrep_inproc.cpp \
tests/testutil.hpp
tests_test_reqrep_inproc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_inproc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_inproc_SOURCES = tests/test_reqrep_inproc.cpp
tests_test_reqrep_inproc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_inproc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_tcp_SOURCES = \
tests/test_reqrep_tcp.cpp \
tests/testutil.hpp
tests_test_reqrep_tcp_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_tcp_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_tcp_SOURCES = tests/test_reqrep_tcp.cpp
tests_test_reqrep_tcp_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_tcp_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_hwm_SOURCES = tests/test_hwm.cpp tests/testutil_unity.hpp
tests_test_hwm_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_hwm_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_hwm_SOURCES = tests/test_hwm.cpp
tests_test_hwm_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_hwm_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_hwm_pubsub_SOURCES = tests/test_hwm_pubsub.cpp
tests_test_hwm_pubsub_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_hwm_pubsub_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_hwm_pubsub_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_hwm_pubsub_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_device_SOURCES = tests/test_reqrep_device.cpp
tests_test_reqrep_device_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_device_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_device_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_device_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_sub_forward_SOURCES = tests/test_sub_forward.cpp
tests_test_sub_forward_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_sub_forward_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_sub_forward_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_sub_forward_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_invalid_rep_SOURCES = tests/test_invalid_rep.cpp
tests_test_invalid_rep_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_invalid_rep_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_invalid_rep_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_invalid_rep_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_msg_flags_SOURCES = tests/test_msg_flags.cpp
tests_test_msg_flags_LDADD = src/libzmq.la
tests_test_msg_flags_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_msg_flags_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_msg_ffn_SOURCES = tests/test_msg_ffn.cpp
tests_test_msg_ffn_LDADD = src/libzmq.la
tests_test_msg_ffn_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_msg_ffn_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_connect_resolve_SOURCES = tests/test_connect_resolve.cpp
tests_test_connect_resolve_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_connect_resolve_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_connect_resolve_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_connect_resolve_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_immediate_SOURCES = tests/test_immediate.cpp
tests_test_immediate_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_immediate_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_immediate_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_immediate_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_last_endpoint_SOURCES = tests/test_last_endpoint.cpp
tests_test_last_endpoint_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_last_endpoint_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_last_endpoint_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_last_endpoint_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_term_endpoint_SOURCES = tests/test_term_endpoint.cpp
tests_test_term_endpoint_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_term_endpoint_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_term_endpoint_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_term_endpoint_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_srcfd_SOURCES = tests/test_srcfd.cpp
tests_test_srcfd_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_srcfd_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_srcfd_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_srcfd_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_monitor_SOURCES = tests/test_monitor.cpp
tests_test_monitor_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_monitor_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_monitor_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_monitor_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_router_mandatory_SOURCES = tests/test_router_mandatory.cpp tests/testutil_unity.hpp
tests_test_router_mandatory_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_router_mandatory_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_router_mandatory_SOURCES = tests/test_router_mandatory.cpp
tests_test_router_mandatory_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_router_mandatory_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_router_mandatory_hwm_SOURCES = tests/test_router_mandatory_hwm.cpp
tests_test_router_mandatory_hwm_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_router_mandatory_hwm_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_router_mandatory_hwm_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_router_mandatory_hwm_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_router_handover_SOURCES = tests/test_router_handover.cpp
tests_test_router_handover_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_router_handover_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_router_handover_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_router_handover_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_probe_router_SOURCES = tests/test_probe_router.cpp
tests_test_probe_router_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_probe_router_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_probe_router_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_probe_router_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_stream_SOURCES = tests/test_stream.cpp
tests_test_stream_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_stream_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_stream_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_stream_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_stream_empty_SOURCES = tests/test_stream_empty.cpp
tests_test_stream_empty_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_stream_empty_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_stream_empty_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_stream_empty_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_stream_timeout_SOURCES = tests/test_stream_timeout.cpp
tests_test_stream_timeout_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_stream_timeout_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_stream_timeout_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_stream_timeout_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_stream_disconnect_SOURCES = tests/test_stream_disconnect.cpp
tests_test_stream_disconnect_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_stream_disconnect_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_stream_disconnect_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_stream_disconnect_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_disconnect_inproc_SOURCES = tests/test_disconnect_inproc.cpp
tests_test_disconnect_inproc_LDADD = src/libzmq.la
tests_test_disconnect_inproc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_disconnect_inproc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_unbind_wildcard_SOURCES = tests/test_unbind_wildcard.cpp
tests_test_unbind_wildcard_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_unbind_wildcard_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_unbind_wildcard_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_unbind_wildcard_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_ctx_options_SOURCES = tests/test_ctx_options.cpp
tests_test_ctx_options_LDADD = src/libzmq.la
tests_test_ctx_options_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_ctx_options_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_iov_SOURCES = tests/test_iov.cpp
tests_test_iov_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_iov_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_iov_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_iov_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_ctx_destroy_SOURCES = tests/test_ctx_destroy.cpp
tests_test_ctx_destroy_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_ctx_destroy_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_ctx_destroy_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_ctx_destroy_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_security_no_zap_handler_SOURCES = tests/test_security_no_zap_handler.cpp
tests_test_security_no_zap_handler_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_security_no_zap_handler_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_security_no_zap_handler_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_security_no_zap_handler_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_security_null_SOURCES = tests/test_security_null.cpp
tests_test_security_null_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_security_null_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_security_null_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_security_null_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_security_plain_SOURCES = tests/test_security_plain.cpp
tests_test_security_plain_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_security_plain_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_security_plain_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_security_plain_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_security_zap_SOURCES = \
tests/test_security_zap.cpp \
tests/testutil_monitoring.hpp \
tests/testutil_security.hpp \
tests/testutil.hpp
tests_test_security_zap_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_security_zap_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_security_zap_SOURCES = tests/test_security_zap.cpp
tests_test_security_zap_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_security_zap_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_spec_req_SOURCES = tests/test_spec_req.cpp
tests_test_spec_req_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_spec_req_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_spec_req_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_spec_req_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_spec_rep_SOURCES = tests/test_spec_rep.cpp
tests_test_spec_rep_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_spec_rep_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_spec_rep_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_spec_rep_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_spec_dealer_SOURCES = tests/test_spec_dealer.cpp
tests_test_spec_dealer_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_spec_dealer_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_spec_dealer_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_spec_dealer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_spec_router_SOURCES = tests/test_spec_router.cpp
tests_test_spec_router_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_spec_router_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_spec_router_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_spec_router_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_spec_pushpull_SOURCES = tests/test_spec_pushpull.cpp
tests_test_spec_pushpull_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_spec_pushpull_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_spec_pushpull_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_spec_pushpull_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_req_correlate_SOURCES = tests/test_req_correlate.cpp
tests_test_req_correlate_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_req_correlate_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_req_correlate_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_req_correlate_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_req_relaxed_SOURCES = tests/test_req_relaxed.cpp
tests_test_req_relaxed_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_req_relaxed_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_req_relaxed_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_req_relaxed_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_conflate_SOURCES = tests/test_conflate.cpp
tests_test_conflate_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_conflate_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_conflate_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_conflate_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_inproc_connect_SOURCES = tests/test_inproc_connect.cpp
tests_test_inproc_connect_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_inproc_connect_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_inproc_connect_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_inproc_connect_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_issue_566_SOURCES = tests/test_issue_566.cpp
tests_test_issue_566_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_issue_566_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_issue_566_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_issue_566_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_proxy_SOURCES = tests/test_proxy.cpp
tests_test_proxy_LDADD = src/libzmq.la
tests_test_proxy_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_proxy_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_proxy_hwm_SOURCES = tests/test_proxy_hwm.cpp
tests_test_proxy_hwm_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_proxy_hwm_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_proxy_hwm_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_proxy_hwm_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_proxy_single_socket_SOURCES = tests/test_proxy_single_socket.cpp
tests_test_proxy_single_socket_LDADD = src/libzmq.la
tests_test_proxy_single_socket_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_proxy_single_socket_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_proxy_terminate_SOURCES = tests/test_proxy_terminate.cpp
tests_test_proxy_terminate_LDADD = src/libzmq.la
tests_test_proxy_terminate_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_proxy_terminate_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_getsockopt_memset_SOURCES = tests/test_getsockopt_memset.cpp
tests_test_getsockopt_memset_LDADD = src/libzmq.la
tests_test_getsockopt_memset_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_getsockopt_memset_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_many_sockets_SOURCES = tests/test_many_sockets.cpp
tests_test_many_sockets_LDADD = src/libzmq.la
tests_test_many_sockets_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_many_sockets_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_diffserv_SOURCES = tests/test_diffserv.cpp
tests_test_diffserv_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_diffserv_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_diffserv_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_diffserv_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_connect_rid_SOURCES = tests/test_connect_rid.cpp
tests_test_connect_rid_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_connect_rid_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_connect_rid_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_connect_rid_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_bind_src_address_SOURCES = tests/test_bind_src_address.cpp
tests_test_bind_src_address_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_bind_src_address_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_bind_src_address_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_bind_src_address_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_metadata_SOURCES = tests/test_metadata.cpp
tests_test_metadata_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_metadata_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_metadata_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_metadata_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_capabilities_SOURCES = tests/test_capabilities.cpp
tests_test_capabilities_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_capabilities_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_capabilities_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_capabilities_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_xpub_nodrop_SOURCES = tests/test_xpub_nodrop.cpp
tests_test_xpub_nodrop_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_xpub_nodrop_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_xpub_nodrop_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_xpub_nodrop_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_xpub_manual_SOURCES = tests/test_xpub_manual.cpp
tests_test_xpub_manual_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_xpub_manual_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_xpub_manual_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_xpub_manual_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_xpub_welcome_msg_SOURCES = tests/test_xpub_welcome_msg.cpp
tests_test_xpub_welcome_msg_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_xpub_welcome_msg_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_xpub_welcome_msg_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_xpub_welcome_msg_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_xpub_verbose_SOURCES = tests/test_xpub_verbose.cpp
tests_test_xpub_verbose_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_xpub_verbose_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_xpub_verbose_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_xpub_verbose_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_atomics_SOURCES = tests/test_atomics.cpp
tests_test_atomics_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_atomics_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_atomics_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_atomics_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_sockopt_hwm_SOURCES = tests/test_sockopt_hwm.cpp
tests_test_sockopt_hwm_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_sockopt_hwm_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_sockopt_hwm_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_sockopt_hwm_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_setsockopt_SOURCES = tests/test_setsockopt.cpp
tests_test_setsockopt_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_setsockopt_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_setsockopt_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_setsockopt_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_heartbeats_SOURCES = tests/test_heartbeats.cpp
tests_test_heartbeats_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_heartbeats_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_heartbeats_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_heartbeats_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_stream_exceeds_buffer_SOURCES = tests/test_stream_exceeds_buffer.cpp
tests_test_stream_exceeds_buffer_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_stream_exceeds_buffer_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_stream_exceeds_buffer_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_stream_exceeds_buffer_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pub_invert_matching_SOURCES = tests/test_pub_invert_matching.cpp
tests_test_pub_invert_matching_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_pub_invert_matching_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_pub_invert_matching_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_pub_invert_matching_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_bind_after_connect_tcp_SOURCES = tests/test_bind_after_connect_tcp.cpp
tests_test_bind_after_connect_tcp_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_bind_after_connect_tcp_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_bind_after_connect_tcp_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_bind_after_connect_tcp_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_base85_SOURCES = tests/test_base85.cpp
tests_test_base85_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_base85_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_base85_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_base85_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_sodium_SOURCES = tests/test_sodium.cpp
tests_test_sodium_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_sodium_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_sodium_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_sodium_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_socket_null_SOURCES = tests/test_socket_null.cpp
tests_test_socket_null_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_socket_null_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_socket_null_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_socket_null_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reconnect_ivl_SOURCES = tests/test_reconnect_ivl.cpp
tests_test_reconnect_ivl_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reconnect_ivl_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reconnect_ivl_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reconnect_ivl_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_mock_pub_sub_SOURCES = tests/test_mock_pub_sub.cpp
tests_test_mock_pub_sub_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_mock_pub_sub_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_mock_pub_sub_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_mock_pub_sub_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
if HAVE_CURVE
@ -769,9 +781,7 @@ test_apps += \
tests_test_security_curve_SOURCES = \
tests/test_security_curve.cpp \
tests/testutil_security.hpp \
tests/testutil.hpp \
src/curve_client_tools.hpp \
src/curve_client_tools.hpp \
src/clock.hpp \
src/clock.cpp \
src/random.hpp \
@ -785,9 +795,9 @@ tests_test_security_curve_SOURCES += \
endif
tests_test_security_curve_LDADD = \
src/libzmq.la ${UNITY_LIBS} $(LIBUNWIND_LIBS)
src/libzmq.la ${TESTUTIL_LIBS} $(LIBUNWIND_LIBS)
tests_test_security_curve_CPPFLAGS = \
${UNITY_CPPFLAGS} \
${TESTUTIL_CPPFLAGS} \
${LIBUNWIND_CFLAGS}
if USE_LIBSODIUM
@ -813,53 +823,48 @@ test_apps += \
tests/test_filter_ipc
tests_test_shutdown_stress_SOURCES = tests/test_shutdown_stress.cpp
tests_test_shutdown_stress_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_shutdown_stress_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_shutdown_stress_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_shutdown_stress_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_ipc_wildcard_SOURCES = tests/test_ipc_wildcard.cpp
tests_test_ipc_wildcard_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_ipc_wildcard_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_ipc_wildcard_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_ipc_wildcard_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pair_ipc_SOURCES = \
tests/test_pair_ipc.cpp \
tests/testutil.hpp
tests_test_pair_ipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_pair_ipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_pair_ipc_SOURCES = tests/test_pair_ipc.cpp
tests_test_pair_ipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_pair_ipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_rebind_ipc_SOURCES = tests/test_rebind_ipc.cpp
tests_test_rebind_ipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_rebind_ipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_rebind_ipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_rebind_ipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_ipc_SOURCES = \
tests/test_reqrep_ipc.cpp \
tests/testutil.hpp
tests_test_reqrep_ipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_ipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_ipc_SOURCES = tests/test_reqrep_ipc.cpp
tests_test_reqrep_ipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_ipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_timeo_SOURCES = tests/test_timeo.cpp
tests_test_timeo_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_timeo_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_timeo_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_timeo_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_filter_ipc_SOURCES = tests/test_filter_ipc.cpp
tests_test_filter_ipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_filter_ipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_filter_ipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_filter_ipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_use_fd_SOURCES = \
tests/test_use_fd.cpp \
tests/testutil.hpp
tests_test_use_fd_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_use_fd_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_use_fd_SOURCES = tests/test_use_fd.cpp
tests_test_use_fd_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_use_fd_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_zmq_poll_fd_SOURCES = tests/test_zmq_poll_fd.cpp
tests_test_zmq_poll_fd_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_zmq_poll_fd_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_zmq_poll_fd_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_zmq_poll_fd_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
if HAVE_FORK
if !VALGRIND_ENABLED
test_apps += tests/test_fork
tests_test_fork_SOURCES = tests/test_fork.cpp
tests_test_fork_LDADD = src/libzmq.la
tests_test_fork_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_fork_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif
endif
@ -879,38 +884,40 @@ test_apps += \
tests/test_address_tipc
tests_test_connect_delay_tipc_SOURCES = tests/test_connect_delay_tipc.cpp
tests_test_connect_delay_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_connect_delay_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_connect_delay_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_connect_delay_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_pair_tipc_SOURCES = tests/test_pair_tipc.cpp
tests_test_pair_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_pair_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_pair_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_pair_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_device_tipc_SOURCES = tests/test_reqrep_device_tipc.cpp
tests_test_reqrep_device_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_device_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_device_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_device_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_reqrep_tipc_SOURCES = tests/test_reqrep_tipc.cpp
tests_test_reqrep_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_reqrep_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_reqrep_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_reqrep_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_router_mandatory_tipc_SOURCES = tests/test_router_mandatory_tipc.cpp
tests_test_router_mandatory_tipc_LDADD = src/libzmq.la
tests_test_router_mandatory_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_router_mandatory_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_shutdown_stress_tipc_SOURCES = tests/test_shutdown_stress_tipc.cpp
tests_test_shutdown_stress_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_shutdown_stress_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_shutdown_stress_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_shutdown_stress_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_sub_forward_tipc_SOURCES = tests/test_sub_forward_tipc.cpp
tests_test_sub_forward_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_sub_forward_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_sub_forward_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_sub_forward_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_term_endpoint_tipc_SOURCES = tests/test_term_endpoint_tipc.cpp
tests_test_term_endpoint_tipc_LDADD = src/libzmq.la
tests_test_term_endpoint_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_term_endpoint_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_address_tipc_SOURCES = tests/test_address_tipc.cpp
tests_test_address_tipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_address_tipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_address_tipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_address_tipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif
@ -918,7 +925,8 @@ if BUILD_GSSAPI
test_apps += tests/test_security_gssapi
tests_test_security_gssapi_SOURCES = tests/test_security_gssapi.cpp
tests_test_security_gssapi_LDADD = src/libzmq.la
tests_test_security_gssapi_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_security_gssapi_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif
@ -927,8 +935,8 @@ test_apps += tests/test_abstract_ipc \
tests/test_many_sockets
tests_test_abstract_ipc_SOURCES = tests/test_abstract_ipc.cpp
tests_test_abstract_ipc_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_abstract_ipc_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_abstract_ipc_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_abstract_ipc_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif
@ -936,12 +944,14 @@ if HAVE_VMCI
test_apps += test_pair_vmci test_reqrep_vmci
test_pair_vmci_SOURCES = tests/test_pair_vmci.cpp
test_pair_vmci_LDADD = src/libzmq.la
test_pair_vmci_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
test_pair_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_pair_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_pair_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
test_reqrep_vmci_SOURCES = tests/test_reqrep_vmci.cpp
test_reqrep_vmci_LDADD = src/libzmq.la
test_reqrep_vmci_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
test_reqrep_vmci_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
test_reqrep_vmci_LDFLAGS = @LIBZMQ_VMCI_LDFLAGS@
test_reqrep_vmci_CXXFLAGS = @LIBZMQ_VMCI_CXXFLAGS@
@ -959,40 +969,40 @@ test_apps += tests/test_poller \
tests/test_router_notify
tests_test_poller_SOURCES = tests/test_poller.cpp
tests_test_poller_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_poller_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_poller_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_poller_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_client_server_SOURCES = tests/test_client_server.cpp
tests_test_client_server_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_client_server_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_client_server_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_client_server_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_thread_safe_SOURCES = tests/test_thread_safe.cpp
tests_test_thread_safe_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_thread_safe_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_thread_safe_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_thread_safe_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_timers_SOURCES = tests/test_timers.cpp
tests_test_timers_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_timers_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_timers_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_timers_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_radio_dish_SOURCES = tests/test_radio_dish.cpp
tests_test_radio_dish_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_radio_dish_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_radio_dish_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_radio_dish_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_scatter_gather_SOURCES = tests/test_scatter_gather.cpp
tests_test_scatter_gather_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_scatter_gather_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_scatter_gather_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_scatter_gather_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_dgram_SOURCES = tests/test_dgram.cpp
tests_test_dgram_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_dgram_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_dgram_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_dgram_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_app_meta_SOURCES = tests/test_app_meta.cpp
tests_test_app_meta_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_app_meta_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_app_meta_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_app_meta_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
tests_test_router_notify_SOURCES = tests/test_router_notify.cpp
tests_test_router_notify_LDADD = src/libzmq.la ${UNITY_LIBS}
tests_test_router_notify_CPPFLAGS = ${UNITY_CPPFLAGS}
tests_test_router_notify_LDADD = src/libzmq.la ${TESTUTIL_LIBS}
tests_test_router_notify_CPPFLAGS = ${TESTUTIL_CPPFLAGS}
endif
if ENABLE_STATIC
@ -1006,52 +1016,58 @@ test_apps += \
unittests/unittest_radix_tree
unittests_unittest_poller_SOURCES = unittests/unittest_poller.cpp
unittests_unittest_poller_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_poller_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_poller_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_poller_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_poller_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_ypipe_SOURCES = unittests/unittest_ypipe.cpp
unittests_unittest_ypipe_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_ypipe_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_ypipe_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_ypipe_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_ypipe_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_mtrie_SOURCES = unittests/unittest_mtrie.cpp
unittests_unittest_mtrie_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_mtrie_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_mtrie_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_mtrie_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_mtrie_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_ip_resolver_SOURCES = unittests/unittest_ip_resolver.cpp unittests/unittest_resolver_common.hpp
unittests_unittest_ip_resolver_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_ip_resolver_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_ip_resolver_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_ip_resolver_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_ip_resolver_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_udp_address_SOURCES = unittests/unittest_udp_address.cpp unittests/unittest_resolver_common.hpp
unittests_unittest_udp_address_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_udp_address_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_udp_address_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_udp_address_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_udp_address_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_radix_tree_SOURCES = unittests/unittest_radix_tree.cpp
unittests_unittest_radix_tree_CPPFLAGS = -I$(top_srcdir)/src ${UNITY_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_radix_tree_CPPFLAGS = -I$(top_srcdir)/src ${TESTUTIL_CPPFLAGS} $(CODE_COVERAGE_CPPFLAGS)
unittests_unittest_radix_tree_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
unittests_unittest_radix_tree_LDADD = $(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
${UNITY_LIBS} \
$(CODE_COVERAGE_LDFLAGS)
unittests_unittest_radix_tree_LDADD = \
${TESTUTIL_LIBS} \
$(top_builddir)/src/.libs/libzmq.a \
${src_libzmq_la_LIBADD} \
$(CODE_COVERAGE_LDFLAGS)
endif
check_PROGRAMS = ${test_apps}

View File

@ -33,6 +33,7 @@
#if !defined ZMQ_HAVE_WINDOWS
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include "address.hpp"

View File

@ -136,7 +136,7 @@ zmq::socks_request_t::socks_request_t (uint8_t command_,
hostname (ZMQ_MOVE (hostname_)),
port (port_)
{
zmq_assert (hostname_.size () <= UINT8_MAX);
zmq_assert (hostname.size () <= UINT8_MAX);
}
zmq::socks_request_encoder_t::socks_request_encoder_t () :

View File

@ -297,13 +297,20 @@ void zmq::stream_engine_t::terminate ()
}
void zmq::stream_engine_t::in_event ()
{
// ignore errors
const bool res = in_event_internal ();
LIBZMQ_UNUSED (res);
}
bool zmq::stream_engine_t::in_event_internal ()
{
zmq_assert (!_io_error);
// If still handshaking, receive and process the greeting message.
if (unlikely (_handshaking))
if (!handshake ())
return;
return false;
zmq_assert (_decoder);
@ -311,7 +318,7 @@ void zmq::stream_engine_t::in_event ()
if (_input_stopped) {
rm_fd (_handle);
_io_error = true;
return;
return true; // TODO or return false in this case too?
}
// If there's no data to process in the buffer...
@ -329,12 +336,14 @@ void zmq::stream_engine_t::in_event ()
// connection closed by peer
errno = EPIPE;
error (connection_error);
return;
return false;
}
if (rc == -1) {
if (errno != EAGAIN)
if (errno != EAGAIN) {
error (connection_error);
return;
return false;
}
return true;
}
// Adjust input size
@ -363,13 +372,14 @@ void zmq::stream_engine_t::in_event ()
if (rc == -1) {
if (errno != EAGAIN) {
error (protocol_error);
return;
return false;
}
_input_stopped = true;
reset_pollin (_handle);
}
_session->flush ();
return true;
}
void zmq::stream_engine_t::out_event ()
@ -497,7 +507,8 @@ bool zmq::stream_engine_t::restart_input ()
_session->flush ();
// Speculative read.
in_event ();
if (!in_event_internal ())
return false;
}
return true;

View File

@ -87,6 +87,8 @@ class stream_engine_t : public io_object_t, public i_engine
void timer_event (int id_);
private:
bool in_event_internal ();
// Unplug the engine from the session.
void unplug ();

View File

@ -75,6 +75,11 @@ set(tests
test_mock_pub_sub
)
if(NOT WIN32)
list(APPEND tests
test_security_gssapi)
endif()
if(ZMQ_HAVE_CURVE)
list(APPEND tests
test_security_curve)
@ -168,6 +173,32 @@ set_target_properties(unity PROPERTIES
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()
@ -176,13 +207,11 @@ if(MSVC_VERSION LESS 1600)
target_compile_definitions(unity PUBLIC "UNITY_EXCLUDE_STDINT_H")
endif()
# add library and include dirs for all targets
if(BUILD_SHARED)
link_libraries(libzmq ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} unity)
else()
link_libraries(libzmq-static ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} unity)
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()
foreach(test ${tests})
# target_sources not supported before CMake 3.1
@ -191,14 +220,11 @@ foreach(test ${tests})
"../src/tweetnacl.c"
"../src/err.cpp"
"../src/random.cpp"
"../src/clock.cpp"
"testutil_security.hpp")
elseif(${test} MATCHES test_security_zap)
add_executable(${test} ${test}.cpp
"testutil_security.hpp")
"../src/clock.cpp")
else()
add_executable(${test} ${test}.cpp "testutil.hpp" "testutil_unity.hpp" "testutil_monitoring.hpp")
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

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -57,7 +57,7 @@ void test_version ()
void test_strerrror ()
{
assert (zmq_strerror (EINVAL));
TEST_ASSERT_NOT_NULL (zmq_strerror (EINVAL));
}
int main ()

View File

@ -31,6 +31,7 @@
#include "testutil_unity.hpp"
#include <unity.h>
#include <string.h>
void setUp ()
{

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -44,7 +44,8 @@ static void receiver (void *socket_)
{
char buffer[16];
int rc = zmq_recv (socket_, &buffer, sizeof (buffer), 0);
assert (rc == -1);
// TODO which error is expected here? use TEST_ASSERT_FAILURE_ERRNO instead
TEST_ASSERT_EQUAL_INT (-1, rc);
}
void test_ctx_destroy ()

View File

@ -29,6 +29,17 @@
#include <limits>
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
#define WAIT_FOR_BACKGROUND_THREAD_INSPECTION (0)
@ -36,6 +47,7 @@
#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
@ -74,27 +86,25 @@ bool is_allowed_to_raise_priority ()
#endif
void test_ctx_thread_opts (void *ctx_)
void test_ctx_thread_opts ()
{
int rc;
// verify that setting negative values (e.g., default values) fail:
rc =
zmq_ctx_set (ctx_, ZMQ_THREAD_SCHED_POLICY, ZMQ_THREAD_SCHED_POLICY_DFLT);
assert (rc == -1 && errno == EINVAL);
rc = zmq_ctx_set (ctx_, ZMQ_THREAD_PRIORITY, ZMQ_THREAD_PRIORITY_DFLT);
assert (rc == -1 && errno == EINVAL);
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):
rc = zmq_ctx_set (ctx_, ZMQ_THREAD_SCHED_POLICY, TEST_POLICY);
assert (rc == 0);
rc = zmq_ctx_get (ctx_, ZMQ_THREAD_SCHED_POLICY);
assert (rc == TEST_POLICY);
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:
@ -108,10 +118,9 @@ void test_ctx_thread_opts (void *ctx_)
// 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 ()) {
rc = zmq_ctx_set (
ctx_, ZMQ_THREAD_PRIORITY,
1 /* any positive value different than the default will be ok */);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_set (
get_test_context (), ZMQ_THREAD_PRIORITY,
1 /* any positive value different than the default will be ok */));
}
@ -125,17 +134,17 @@ void test_ctx_thread_opts (void *ctx_)
int cpus_add[] = {0, 1};
for (unsigned int idx = 0; idx < sizeof (cpus_add) / sizeof (cpus_add[0]);
idx++) {
rc = zmq_ctx_set (ctx_, ZMQ_THREAD_AFFINITY_CPU_ADD, cpus_add[idx]);
assert (rc == 0);
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++) {
rc =
zmq_ctx_set (ctx_, ZMQ_THREAD_AFFINITY_CPU_REMOVE, cpus_remove[idx]);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_set (get_test_context (),
ZMQ_THREAD_AFFINITY_CPU_REMOVE,
cpus_remove[idx]));
}
#endif
@ -143,103 +152,116 @@ void test_ctx_thread_opts (void *ctx_)
#ifdef ZMQ_THREAD_NAME_PREFIX
// test thread name prefix:
rc = zmq_ctx_set (ctx_, ZMQ_THREAD_NAME_PREFIX, 1234);
assert (rc == 0);
rc = zmq_ctx_get (ctx_, ZMQ_THREAD_NAME_PREFIX);
assert (rc == 1234);
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));
#endif
}
void test_ctx_zero_copy (void *ctx_)
void test_ctx_zero_copy ()
{
#ifdef ZMQ_ZERO_COPY_RECV
int zero_copy;
// Default value is 1.
zero_copy = zmq_ctx_get (ctx_, ZMQ_ZERO_COPY_RECV);
assert (zero_copy == 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.
assert (0 == zmq_ctx_set (ctx_, ZMQ_ZERO_COPY_RECV, 0));
zero_copy = zmq_ctx_get (ctx_, ZMQ_ZERO_COPY_RECV);
assert (zero_copy == 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 (ctx_, ZMQ_PULL);
assert (0 == zmq_bind (pull, "tcp://127.0.0.1:*"));
void *pull = zmq_socket (get_test_context (), ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pull, "tcp://127.0.0.1:*"));
void *push = zmq_socket (ctx_, ZMQ_PUSH);
void *push = zmq_socket (get_test_context (), ZMQ_PUSH);
size_t endpoint_len = MAX_SOCKET_STRING;
char endpoint[MAX_SOCKET_STRING];
assert (
0 == zmq_getsockopt (pull, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len));
assert (0 == zmq_connect (push, endpoint));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (pull, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_len));
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (push, endpoint));
const char *small_str = "abcd";
const char *large_str =
"01234567890123456789012345678901234567890123456789";
assert (4 == zmq_send (push, (void *) small_str, 4, 0));
assert (40 == zmq_send (push, (void *) large_str, 40, 0));
send_string_expect_success (push, small_str, 0);
send_string_expect_success (push, large_str, 0);
zmq_msg_t small_msg, large_msg;
zmq_msg_init (&small_msg);
zmq_msg_init (&large_msg);
assert (4 == zmq_msg_recv (&small_msg, pull, 0));
assert (40 == zmq_msg_recv (&large_msg, pull, 0));
assert (!strncmp (small_str, (const char *) zmq_msg_data (&small_msg), 4));
assert (!strncmp (large_str, (const char *) zmq_msg_data (&large_msg), 40));
recv_string_expect_success (pull, small_str, 0);
recv_string_expect_success (pull, large_str, 0);
// Clean up.
assert (0 == zmq_close (push));
assert (0 == zmq_close (pull));
assert (0 == zmq_msg_close (&small_msg));
assert (0 == zmq_msg_close (&large_msg));
assert (0 == zmq_ctx_set (ctx_, ZMQ_ZERO_COPY_RECV, 1));
zero_copy = zmq_ctx_get (ctx_, ZMQ_ZERO_COPY_RECV);
assert (zero_copy == 1);
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
}
int main (void)
void test_ctx_option_max_sockets ()
{
setup_test_environment ();
int rc;
TEST_ASSERT_EQUAL_INT (ZMQ_MAX_SOCKETS_DFLT,
zmq_ctx_get (get_test_context (), ZMQ_MAX_SOCKETS));
}
// Set up our context and sockets
void *ctx = zmq_ctx_new ();
assert (ctx);
assert (zmq_ctx_get (ctx, ZMQ_MAX_SOCKETS) == ZMQ_MAX_SOCKETS_DFLT);
void test_ctx_option_socket_limit ()
{
#if defined(ZMQ_USE_SELECT)
assert (zmq_ctx_get (ctx, ZMQ_SOCKET_LIMIT) == FD_SETSIZE - 1);
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)
assert (zmq_ctx_get (ctx, ZMQ_SOCKET_LIMIT) == 65535);
TEST_ASSERT_EQUAL_INT (65535, zmq_ctx_get (ctx, ZMQ_SOCKET_LIMIT));
#endif
assert (zmq_ctx_get (ctx, ZMQ_IO_THREADS) == ZMQ_IO_THREADS_DFLT);
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 0);
}
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)
assert (zmq_ctx_get (ctx, ZMQ_MSG_T_SIZE) == sizeof (zmq_msg_t));
TEST_ASSERT_EQUAL_INT (sizeof (zmq_msg_t),
zmq_ctx_get (get_test_context (), ZMQ_MSG_T_SIZE));
#endif
}
rc = zmq_ctx_set (ctx, ZMQ_IPV6, true);
assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 1);
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));
}
test_ctx_thread_opts (ctx);
test_ctx_zero_copy (ctx);
void test_ctx_option_blocky ()
{
TEST_ASSERT_SUCCESS_ERRNO (
zmq_ctx_set (get_test_context (), ZMQ_IPV6, true));
void *router = zmq_socket (ctx, ZMQ_ROUTER);
void *router = test_context_socket (ZMQ_ROUTER);
int value;
size_t optsize = sizeof (int);
rc = zmq_getsockopt (router, ZMQ_IPV6, &value, &optsize);
assert (rc == 0);
assert (value == 1);
rc = zmq_getsockopt (router, ZMQ_LINGER, &value, &optsize);
assert (rc == 0);
assert (value == -1);
rc = zmq_close (router);
assert (rc == 0);
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
@ -250,17 +272,30 @@ int main (void)
sleep (100);
#endif
rc = zmq_ctx_set (ctx, ZMQ_BLOCKY, false);
assert (zmq_ctx_get (ctx, ZMQ_BLOCKY) == 0);
router = zmq_socket (ctx, ZMQ_ROUTER);
rc = zmq_getsockopt (router, ZMQ_LINGER, &value, &optsize);
assert (rc == 0);
assert (value == 0);
rc = zmq_close (router);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
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);
}
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);
return UNITY_END ();
}

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -28,46 +28,43 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
/// Initialize a zeromq message with a given null-terminated string
#define ZMQ_PREPARE_STRING(msg, data, size) \
\
zmq_msg_init (&msg) \
&& printf ("zmq_msg_init: %s\n", zmq_strerror (errno)); \
\
zmq_msg_init_size (&msg, size + 1) \
&& printf ("zmq_msg_init_size: %s\n", zmq_strerror (errno)); \
\
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);
// TODO: this code fails to meet our style guidelines, and needs rewriting
static int publicationsReceived = 0;
static bool isSubscribed = false;
int main (int, char **)
void test_disconnect_inproc ()
{
setup_test_environment ();
void *context = zmq_ctx_new ();
void *pub_socket;
void *sub_socket;
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));
(pub_socket = zmq_socket (context, ZMQ_XPUB))
|| printf ("zmq_socket: %s\n", zmq_strerror (errno));
(sub_socket = zmq_socket (context, ZMQ_SUB))
|| printf ("zmq_socket: %s\n", zmq_strerror (errno));
zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, "foo", 3)
&& printf ("zmq_setsockopt: %s\n", zmq_strerror (errno));
zmq_bind (pub_socket, "inproc://someInProcDescriptor")
&& printf ("zmq_bind: %s\n", zmq_strerror (errno));
//zmq_bind(pubSocket, "tcp://127.0.0.1:30010") && printf("zmq_bind: %s\n", zmq_strerror(errno));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (pub_socket, "inproc://someInProcDescriptor"));
int more;
size_t more_size = sizeof (more);
int iteration = 0;
while (1) {
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
@ -75,77 +72,73 @@ int main (int, char **)
int rc = zmq_poll (items, 2, 100);
if (items[1].revents & ZMQ_POLLIN) {
while (1) {
for (more = 1; more;) {
zmq_msg_t msg;
zmq_msg_init (&msg);
zmq_msg_recv (&msg, pub_socket, 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, pub_socket, 0));
char *buffer = (char *) zmq_msg_data (&msg);
if (buffer[0] == 0) {
assert (isSubscribed);
TEST_ASSERT_TRUE (isSubscribed);
isSubscribed = false;
} else {
assert (!isSubscribed);
TEST_ASSERT_FALSE (isSubscribed);
isSubscribed = true;
}
zmq_getsockopt (pub_socket, ZMQ_RCVMORE, &more, &more_size);
zmq_msg_close (&msg);
if (!more)
break; // Last message part
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) {
while (1) {
more = 1;
for (more = 1; more;) {
zmq_msg_t msg;
zmq_msg_init (&msg);
zmq_msg_recv (&msg, sub_socket, 0);
zmq_getsockopt (sub_socket, ZMQ_RCVMORE, &more, &more_size);
zmq_msg_close (&msg);
if (!more) {
publicationsReceived++;
break; // Last message part
}
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) {
zmq_connect (sub_socket, "inproc://someInProcDescriptor")
&& printf ("zmq_connect: %s\n", zmq_strerror (errno));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (sub_socket, "inproc://someInProcDescriptor"));
msleep (SETTLE_TIME);
}
if (iteration == 4) {
zmq_disconnect (sub_socket, "inproc://someInProcDescriptor")
&& printf ("zmq_disconnect(%d): %s\n", errno,
zmq_strerror (errno));
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);
zmq_msg_send (&channel_envlp, pub_socket, ZMQ_SNDMORE) >= 0
|| printf ("zmq_msg_send: %s\n", zmq_strerror (errno));
zmq_msg_close (&channel_envlp)
&& printf ("zmq_msg_close: %s\n", zmq_strerror (errno));
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);
zmq_msg_send (&message, pub_socket, 0) >= 0
|| printf ("zmq_msg_send: %s\n", zmq_strerror (errno));
zmq_msg_close (&message)
&& printf ("zmq_msg_close: %s\n", zmq_strerror (errno));
iteration++;
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&message, pub_socket, 0));
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&message));
}
assert (publicationsReceived == 3);
assert (!isSubscribed);
TEST_ASSERT_EQUAL_INT (3, publicationsReceived);
TEST_ASSERT_FALSE (isSubscribed);
zmq_close (pub_socket) && printf ("zmq_close: %s", zmq_strerror (errno));
zmq_close (sub_socket) && printf ("zmq_close: %s", zmq_strerror (errno));
zmq_ctx_term (context);
return 0;
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 ();
}

View File

@ -30,6 +30,9 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <unistd.h>
#include <grp.h>
void setUp ()
{
setup_test_context ();
@ -117,7 +120,7 @@ void init_groups ()
// Get the group and supplemental groups of the process owner
gid_t groups[100];
int ngroups = getgroups (100, groups);
assert (ngroups != -1);
TEST_ASSERT_NOT_EQUAL (-1, ngroups);
group = getgid ();
supgroup = group;
notgroup = group + 1;

View File

@ -28,41 +28,50 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
const char *address = "tcp://127.0.0.1:*";
char connect_address[MAX_SOCKET_STRING];
#define NUM_MESSAGES 5
int main (void)
void test_fork ()
{
#if !defined(ZMQ_HAVE_WINDOWS)
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
// Create and bind pull socket to receive messages
void *pull = zmq_socket (ctx, ZMQ_PULL);
assert (pull);
int rc = zmq_bind (pull, address);
assert (rc == 0);
size_t len = MAX_SOCKET_STRING;
rc = zmq_getsockopt (pull, ZMQ_LAST_ENDPOINT, connect_address, &len);
assert (rc == 0);
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 (ctx);
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);
rc = zmq_connect (push, connect_address);
int rc = zmq_connect (push, connect_address);
assert (rc == 0);
int count;
for (count = 0; count < NUM_MESSAGES; count++)
@ -75,24 +84,28 @@ int main (void)
// Parent process
int count;
for (count = 0; count < NUM_MESSAGES; count++) {
char buffer[5];
int num_bytes = zmq_recv (pull, buffer, 5, 0);
assert (num_bytes == 5);
recv_string_expect_success (pull, "Hello", 0);
}
int child_status;
while (true) {
rc = waitpid (pid, &child_status, 0);
int rc = waitpid (pid, &child_status, 0);
if (rc == -1 && errno == EINTR)
continue;
assert (rc > 0);
TEST_ASSERT_GREATER_THAN (0, rc);
// Verify the status code of the child was zero
assert (WEXITSTATUS (child_status) == 0);
TEST_ASSERT_EQUAL (0, WEXITSTATUS (child_status));
break;
}
zmq_close (pull);
zmq_ctx_term (ctx);
exit (0);
test_context_socket_close (pull);
}
#endif
return 0;
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_fork);
return UNITY_END ();
}

View File

@ -23,42 +23,46 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
int main (void)
#include <string.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_getsockopt_memset ()
{
int64_t more;
size_t more_size = sizeof (more);
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
void *sb = test_context_socket (ZMQ_PUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
void *sb = zmq_socket (ctx, ZMQ_PUB);
assert (sb);
int rc = zmq_bind (sb, "inproc://a");
assert (rc == 0);
void *sc = zmq_socket (ctx, ZMQ_SUB);
assert (sc);
rc = zmq_connect (sc, "inproc://a");
assert (rc == 0);
void *sc = test_context_socket (ZMQ_SUB);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
memset (&more, 0xFF, sizeof (int64_t));
zmq_getsockopt (sc, ZMQ_RCVMORE, &more, &more_size);
assert (more_size == sizeof (int));
assert (more == 0);
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
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
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 ();
}

View File

@ -26,10 +26,13 @@
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

View File

@ -191,12 +191,8 @@ int test_inproc_connect_and_close_first (int send_hwm_, int recv_hwm_)
int test_inproc_bind_and_close_first (int send_hwm_, int /* recv_hwm */)
{
void *ctx = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (ctx);
// Set up bind socket
void *bind_socket = zmq_socket (ctx, ZMQ_PUSH);
TEST_ASSERT_NOT_NULL (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"));
@ -208,12 +204,11 @@ int test_inproc_bind_and_close_first (int send_hwm_, int /* recv_hwm */)
++send_count;
// Close bind
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (bind_socket));
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 = zmq_socket (ctx, ZMQ_PULL);
TEST_ASSERT_NOT_NULL(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"));
@ -226,9 +221,7 @@ int test_inproc_bind_and_close_first (int send_hwm_, int /* recv_hwm */)
*/
// Clean up
//TEST_ASSERT_SUCCESS_ERRNO (zmq_close (connect_socket));
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (ctx));
//test_context_socket_close (connect_socket);
return send_count;
}

View File

@ -30,6 +30,8 @@
#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)

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
#include <unity.h>
void setUp ()
@ -55,7 +57,9 @@ struct iovec
static void do_check (void *sb_, void *sc_, size_t msg_size_)
{
assert (sb_ && sc_ && msg_size_ > 0);
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;
@ -76,8 +80,8 @@ static void do_check (void *sb_, void *sc_, size_t 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?
assert (memcmp (ref_msg, send_iov[i].iov_base, msg_size_) == 0);
// 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

View File

@ -44,12 +44,12 @@ void tearDown ()
static void do_bind_and_verify (void *s_, const char *endpoint_)
{
int rc = zmq_bind (s_, endpoint_);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (s_, endpoint_));
char reported[255];
size_t size = 255;
rc = zmq_getsockopt (s_, ZMQ_LAST_ENDPOINT, reported, &size);
assert (rc == 0 && strcmp (reported, endpoint_) == 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (s_, ZMQ_LAST_ENDPOINT, reported, &size));
TEST_ASSERT_EQUAL_STRING (endpoint_, reported);
}
void test_last_endpoint ()

View File

@ -28,75 +28,81 @@
*/
#include "testutil.hpp"
#include <zmq.h>
#include "testutil_unity.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_system_max ()
{
// Keep allocating sockets until we run out of system resources
const int no_of_sockets = 2 * 65536;
void *ctx = zmq_ctx_new ();
zmq_ctx_set (ctx, ZMQ_MAX_SOCKETS, no_of_sockets);
zmq_ctx_set (get_test_context (), ZMQ_MAX_SOCKETS, no_of_sockets);
std::vector<void *> sockets;
while (true) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
void *socket = zmq_socket (get_test_context (), ZMQ_PAIR);
if (!socket)
break;
sockets.push_back (socket);
}
assert (static_cast<int> (sockets.size ()) <= no_of_sockets);
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) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
assert (socket == NULL);
void *socket = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_NULL (socket);
}
// Clean up.
for (unsigned int i = 0; i < sockets.size (); ++i)
zmq_close (sockets[i]);
zmq_ctx_destroy (ctx);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (sockets[i]));
}
void test_zmq_default_max ()
{
// Keep allocating sockets until we hit the default limit
void *ctx = zmq_ctx_new ();
std::vector<void *> sockets;
while (true) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
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
assert (sockets.size () <= ZMQ_MAX_SOCKETS_DFLT);
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) {
void *socket = zmq_socket (ctx, ZMQ_PAIR);
assert (socket == NULL);
void *socket = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_NULL (socket);
}
// Clean up
for (unsigned int i = 0; i < sockets.size (); ++i)
zmq_close (sockets[i]);
zmq_ctx_destroy (ctx);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (sockets[i]));
}
int main (void)
{
setup_test_environment ();
test_system_max ();
test_zmq_default_max ();
return 0;
UNITY_BEGIN ();
RUN_TEST (test_system_max);
RUN_TEST (test_zmq_default_max);
return UNITY_END ();
}

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <unity.h>
void setUp ()
@ -57,8 +58,8 @@ static void zap_handler (void *handler_)
char *routing_id = s_recv (handler_);
char *mechanism = s_recv (handler_);
assert (streq (version, "1.0"));
assert (streq (mechanism, "NULL"));
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("NULL", mechanism);
s_sendmore (handler_, version);
s_sendmore (handler_, sequence);

View File

@ -27,9 +27,12 @@
typedef SOCKET raw_socket;
#else
#include <arpa/inet.h>
#include <unistd.h>
typedef int raw_socket;
#endif
#include <stdlib.h>
#include <string.h>
void setUp ()
{

View File

@ -32,6 +32,9 @@
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
void setUp ()
{
setup_test_context ();
@ -99,7 +102,7 @@ void test_monitor_basic ()
int event = get_monitor_event (client_mon, NULL, NULL);
if (event == ZMQ_EVENT_CONNECT_DELAYED)
event = get_monitor_event (client_mon, NULL, NULL);
assert (event == ZMQ_EVENT_CONNECTED);
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) {

View File

@ -28,6 +28,19 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void ffn (void *data_, void *hint_)
{
@ -36,29 +49,16 @@ void ffn (void *data_, void *hint_)
memcpy (hint_, (void *) "freed", 5);
}
int main (void)
void test_msg_ffn ()
{
setup_test_environment ();
// Create the infrastructure
void *ctx = zmq_ctx_new ();
assert (ctx);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *router = zmq_socket (ctx, ZMQ_ROUTER);
assert (router);
void *router = test_context_socket (ZMQ_ROUTER);
bind_loopback_ipv4 (router, my_endpoint, sizeof my_endpoint);
int rc = zmq_bind (router, "tcp://127.0.0.1:*");
assert (rc == 0);
rc = zmq_getsockopt (router, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
assert (rc == 0);
void *dealer = zmq_socket (ctx, ZMQ_DEALER);
assert (dealer);
rc = zmq_connect (dealer, my_endpoint);
assert (rc == 0);
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;
@ -67,80 +67,68 @@ int main (void)
memset (data, 0, 255);
memcpy (data, (void *) "data", 4);
memcpy (hint, (void *) "hint", 4);
rc = zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint);
assert (rc == 0);
rc = zmq_msg_close (&msg);
assert (rc == 0);
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);
assert (memcmp (hint, "freed", 5) == 0);
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);
rc = zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint);
assert (rc == 0);
rc = zmq_msg_copy (&msg2, &msg);
assert (rc == 0);
rc = zmq_msg_close (&msg2);
assert (rc == 0);
rc = zmq_msg_close (&msg);
assert (rc == 0);
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);
assert (memcmp (hint, "freed", 5) == 0);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
memcpy (hint, (void *) "hint", 4);
// Test that sending a message triggers ffn
rc = zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint));
zmq_msg_send (&msg, dealer, 0);
char buf[255];
rc = zmq_recv (router, buf, 255, 0);
assert (rc > -1);
rc = zmq_recv (router, buf, 255, 0);
assert (rc == 255);
assert (memcmp (data, buf, 4) == 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);
msleep (SETTLE_TIME);
assert (memcmp (hint, "freed", 5) == 0);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
memcpy (hint, (void *) "hint", 4);
rc = zmq_msg_close (&msg);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&msg));
// Sending a copy of a message triggers ffn
rc = zmq_msg_init (&msg2);
assert (rc == 0);
rc = zmq_msg_init_data (&msg, (void *) data, 255, ffn, (void *) hint);
assert (rc == 0);
rc = zmq_msg_copy (&msg2, &msg);
assert (rc == 0);
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);
rc = zmq_recv (router, buf, 255, 0);
assert (rc > -1);
rc = zmq_recv (router, buf, 255, 0);
assert (rc == 255);
assert (memcmp (data, buf, 4) == 0);
rc = zmq_msg_close (&msg2);
assert (rc == 0);
rc = zmq_msg_close (&msg);
assert (rc == 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);
assert (memcmp (hint, "freed", 5) == 0);
memcpy (hint, (void *) "hint", 4);
TEST_ASSERT_EQUAL_STRING_LEN ("freed", hint, 5);
// Deallocate the infrastructure.
rc = zmq_close (router);
assert (rc == 0);
rc = zmq_close (dealer);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
test_context_socket_close (router);
test_context_socket_close (dealer);
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_msg_ffn);
return UNITY_END ();
}

View File

@ -28,99 +28,98 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
int main (void)
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_more ()
{
setup_test_environment ();
// Create the infrastructure
void *ctx = zmq_ctx_new ();
assert (ctx);
void *sb = test_context_socket (ZMQ_ROUTER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "inproc://a"));
void *sb = zmq_socket (ctx, ZMQ_ROUTER);
assert (sb);
int rc = zmq_bind (sb, "inproc://a");
assert (rc == 0);
void *sc = zmq_socket (ctx, ZMQ_DEALER);
assert (sc);
rc = zmq_connect (sc, "inproc://a");
assert (rc == 0);
void *sc = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "inproc://a"));
// Send 2-part message.
rc = zmq_send (sc, "A", 1, ZMQ_SNDMORE);
assert (rc == 1);
rc = zmq_send (sc, "B", 1, 0);
assert (rc == 1);
send_string_expect_success (sc, "A", ZMQ_SNDMORE);
send_string_expect_success (sc, "B", 0);
// Routing id comes first.
zmq_msg_t msg;
rc = zmq_msg_init (&msg);
assert (rc == 0);
rc = zmq_msg_recv (&msg, sb, 0);
assert (rc >= 0);
int more = zmq_msg_more (&msg);
assert (more == 1);
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.
rc = zmq_msg_recv (&msg, sb, 0);
assert (rc == 1);
more = zmq_msg_more (&msg);
assert (more == 1);
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.
rc = zmq_msg_recv (&msg, sb, 0);
assert (rc == 1);
more = zmq_msg_more (&msg);
assert (more == 0);
// Test ZMQ_SHARED property (case 1, refcounted messages)
zmq_msg_t msg_a;
rc = zmq_msg_init_size (&msg_a, 1024); // large enough to be a type_lmsg
assert (rc == 0);
// Message is not shared
rc = zmq_msg_get (&msg_a, ZMQ_SHARED);
assert (rc == 0);
zmq_msg_t msg_b;
rc = zmq_msg_init (&msg_b);
assert (rc == 0);
rc = zmq_msg_copy (&msg_b, &msg_a);
assert (rc == 0);
// Message is now shared
rc = zmq_msg_get (&msg_b, ZMQ_SHARED);
assert (rc == 1);
// cleanup
rc = zmq_msg_close (&msg_a);
assert (rc == 0);
rc = zmq_msg_close (&msg_b);
assert (rc == 0);
// Test ZMQ_SHARED property (case 2, constant data messages)
rc = zmq_msg_init_data (&msg_a, (void *) "TEST", 5, 0, 0);
assert (rc == 0);
// Message reports as shared
rc = zmq_msg_get (&msg_a, ZMQ_SHARED);
assert (rc == 1);
// cleanup
rc = zmq_msg_close (&msg_a);
assert (rc == 0);
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.
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
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 ();
}

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -45,9 +45,8 @@ typedef void (*extra_func_t) (void *socket_);
void set_sockopt_bind_to_device (void *socket)
{
const char device[] = "lo";
int rc =
zmq_setsockopt (socket, ZMQ_BINDTODEVICE, &device, sizeof (device) - 1);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket, ZMQ_BINDTODEVICE, &device, sizeof (device) - 1));
}
// TODO this is duplicated from test_pair_tcp

View File

@ -32,37 +32,41 @@
#include <vmci_sockets.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
int main (void)
void setUp ()
{
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_pair_vmci ()
{
std::stringstream s;
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
std::string endpoint = s.str ();
void *sb = zmq_socket (ctx, ZMQ_PAIR);
assert (sb);
int rc = zmq_bind (sb, endpoint.c_str ());
assert (rc == 0);
void *sb = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ()));
void *sc = zmq_socket (ctx, ZMQ_PAIR);
assert (sc);
rc = zmq_connect (sc, endpoint.c_str ());
assert (rc == 0);
void *sc = test_context_socket (ZMQ_PAIR);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc);
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
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 ();
}

View File

@ -33,6 +33,13 @@
#include <unity.h>
#include <limits.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
void setUp ()
{
setup_test_context ();

View File

@ -28,19 +28,20 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
// 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.
#include <stdlib.h>
#include <string.h>
// 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.
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
#define CONTENT_SIZE 13
#define CONTENT_SIZE_MAX 32
@ -52,7 +53,6 @@
struct thread_data
{
void *ctx;
int id;
};
@ -73,49 +73,56 @@ typedef struct
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_)
{
struct thread_data *databag = (struct thread_data *) db_;
// Endpoint socket gets random port to avoid test failing when port in use
void *endpoint = zmq_socket (databag->ctx, ZMQ_PAIR);
assert (endpoint);
void *endpoint = zmq_socket (get_test_context (), ZMQ_PAIR);
TEST_ASSERT_NOT_NULL (endpoint);
int linger = 0;
int rc = zmq_setsockopt (endpoint, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 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);
rc = zmq_connect (endpoint, endpoint_source);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (endpoint, endpoint_source));
char *my_endpoint = s_recv (endpoint);
assert (my_endpoint);
TEST_ASSERT_NOT_NULL (my_endpoint);
void *client = zmq_socket (databag->ctx, ZMQ_DEALER);
assert (client);
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 (databag->ctx, ZMQ_SUB);
assert (control);
rc = zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0);
assert (rc == 0);
rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_connect (control, "inproc://control");
assert (rc == 0);
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);
rc =
zmq_setsockopt (client, ZMQ_ROUTING_ID, routing_id,
ROUTING_ID_SIZE); // includes '\0' as an helper for printf
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_ROUTING_ID, routing_id,
ROUTING_ID_SIZE)); // includes '\0' as an helper for printf
linger = 0;
rc = zmq_setsockopt (client, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_connect (client, my_endpoint);
assert (rc == 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}};
@ -130,20 +137,21 @@ static void client_task (void *db_)
if (items[0].revents & ZMQ_POLLIN) {
int rcvmore;
size_t sz = sizeof (rcvmore);
rc = zmq_recv (client, content, CONTENT_SIZE_MAX, 0);
assert (rc == CONTENT_SIZE);
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
assert (memcmp (content, "request #", 9) == 0);
rc = zmq_getsockopt (client, ZMQ_RCVMORE, &rcvmore, &sz);
assert (rc == 0);
assert (!rcvmore);
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) {
rc = zmq_recv (control, content, CONTENT_SIZE_MAX, 0);
int rc = zmq_recv (control, content, CONTENT_SIZE_MAX, 0);
if (rc > 0) {
content[rc] = 0; // NULL-terminate the command string
@ -170,17 +178,14 @@ static void client_task (void *db_)
routing_id, request_nbr);
zmq_atomic_counter_inc (g_clients_pkts_out);
rc = zmq_send (client, content, CONTENT_SIZE, 0);
assert (rc == CONTENT_SIZE);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE,
zmq_send (client, content, CONTENT_SIZE, 0));
}
}
rc = zmq_close (client);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
rc = zmq_close (endpoint);
assert (rc == 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);
}
@ -190,80 +195,68 @@ static void client_task (void *db_)
// one request at a time but one client can talk to multiple workers at
// once.
static void server_worker (void *ctx_);
static void server_worker (void * /*unused_*/);
void server_task (void *ctx_)
void server_task (void * /*unused_*/)
{
// Frontend socket talks to clients over TCP
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *frontend = zmq_socket (ctx_, ZMQ_ROUTER);
assert (frontend);
void *frontend = zmq_socket (get_test_context (), ZMQ_ROUTER);
TEST_ASSERT_NOT_NULL (frontend);
int linger = 0;
int rc = zmq_setsockopt (frontend, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_bind (frontend, "tcp://127.0.0.1:*");
assert (rc == 0);
rc = zmq_getsockopt (frontend, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
assert (rc == 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 (ctx_, ZMQ_DEALER);
assert (backend);
rc = zmq_setsockopt (backend, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_bind (backend, "inproc://backend");
assert (rc == 0);
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 (ctx_, ZMQ_REP);
assert (control);
rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_connect (control, "inproc://control_proxy");
assert (rc == 0);
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, ctx_);
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 (ctx_, ZMQ_PAIR);
assert (endpoint_receivers[i]);
rc = zmq_setsockopt (endpoint_receivers[i], ZMQ_LINGER, &linger,
sizeof (linger));
assert (rc == 0);
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);
rc = zmq_bind (endpoint_receivers[i], endpoint_source);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (endpoint_receivers[i], endpoint_source));
}
for (int i = 0; i < QT_CLIENTS; ++i) {
rc = s_send (endpoint_receivers[i], my_endpoint);
assert (rc > 0);
TEST_ASSERT_SUCCESS_ERRNO (s_send (endpoint_receivers[i], my_endpoint));
}
// Connect backend to frontend via a proxy
rc = zmq_proxy_steerable (frontend, backend, NULL, control);
assert (rc == 0);
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]);
rc = zmq_close (frontend);
assert (rc == 0);
rc = zmq_close (backend);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
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) {
rc = zmq_close (endpoint_receivers[i]);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (endpoint_receivers[i]));
}
}
@ -271,25 +264,22 @@ void server_task (void *ctx_)
// 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 *ctx_)
static void server_worker (void * /*unused_*/)
{
void *worker = zmq_socket (ctx_, ZMQ_DEALER);
assert (worker);
void *worker = zmq_socket (get_test_context (), ZMQ_DEALER);
TEST_ASSERT_NOT_NULL (worker);
int linger = 0;
int rc = zmq_setsockopt (worker, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_connect (worker, "inproc://backend");
assert (rc == 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 (ctx_, ZMQ_SUB);
assert (control);
rc = zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0);
assert (rc == 0);
rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_connect (control, "inproc://control");
assert (rc == 0);
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
@ -299,8 +289,8 @@ static void server_worker (void *ctx_)
bool run = true;
bool keep_sending = true;
while (run) {
rc = zmq_recv (control, content, CONTENT_SIZE_MAX,
ZMQ_DONTWAIT); // usually, rc == -1 (no message)
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)
@ -315,7 +305,7 @@ static void server_worker (void *ctx_)
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);
assert (rc == CONTENT_SIZE);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE, rc);
if (is_verbose)
printf ("server receive - routing_id = %s content = %s\n",
routing_id, content);
@ -335,17 +325,15 @@ static void server_worker (void *ctx_)
rc = zmq_send (worker, routing_id, ROUTING_ID_SIZE,
ZMQ_SNDMORE);
assert (rc == ROUTING_ID_SIZE);
TEST_ASSERT_EQUAL_INT (ROUTING_ID_SIZE, rc);
rc = zmq_send (worker, content, CONTENT_SIZE, 0);
assert (rc == CONTENT_SIZE);
TEST_ASSERT_EQUAL_INT (CONTENT_SIZE, rc);
}
}
}
}
rc = zmq_close (worker);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (worker));
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (control));
}
uint64_t recv_stat (void *sock_, bool last_)
@ -353,19 +341,17 @@ uint64_t 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_recvmsg (sock_, &stats_msg, 0);
assert (rc == sizeof (uint64_t));
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));
rc = zmq_msg_close (&stats_msg);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_close (&stats_msg));
int more;
size_t moresz = sizeof more;
rc = zmq_getsockopt (sock_, ZMQ_RCVMORE, &more, &moresz);
assert (rc == 0);
assert ((last_ && !more) || (!last_ && more));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (sock_, ZMQ_RCVMORE, &more, &moresz));
TEST_ASSERT_TRUE ((last_ && !more) || (!last_ && more));
return res;
}
@ -375,10 +361,8 @@ uint64_t recv_stat (void *sock_, bool last_)
void check_proxy_stats (void *control_proxy_)
{
zmq_proxy_stats_t total_stats;
int rc;
rc = zmq_send (control_proxy_, "STATISTICS", 10, 0);
assert (rc == 10);
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);
@ -413,91 +397,82 @@ void check_proxy_stats (void *control_proxy_)
printf ("workers sent out %d replies\n",
zmq_atomic_counter_value (g_workers_pkts_out));
}
assert (total_stats.frontend.msg_in
== (unsigned) zmq_atomic_counter_value (g_clients_pkts_out));
assert (total_stats.frontend.msg_out
== (unsigned) zmq_atomic_counter_value (g_workers_pkts_out));
assert (total_stats.backend.msg_in
== (unsigned) zmq_atomic_counter_value (g_workers_pkts_out));
assert (total_stats.backend.msg_out
== (unsigned) zmq_atomic_counter_value (g_clients_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.
int main (void)
void test_proxy ()
{
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
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 = zmq_socket (ctx, ZMQ_PUB);
assert (control);
void *control = test_context_socket (ZMQ_PUB);
int linger = 0;
int rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_bind (control, "inproc://control");
assert (rc == 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 = zmq_socket (ctx, ZMQ_REQ);
assert (control_proxy);
rc = zmq_setsockopt (control_proxy, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0);
rc = zmq_bind (control_proxy, "inproc://control_proxy");
assert (rc == 0);
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].ctx = ctx;
databags[i].id = i;
threads[i] = zmq_threadstart (&client_task, &databags[i]);
}
threads[QT_CLIENTS] = zmq_threadstart (&server_task, ctx);
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");
rc = zmq_send (control, "STOP", 4, 0);
assert (rc == 4);
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");
rc = zmq_send (control, "TERMINATE", 9, 0);
assert (rc == 9);
send_string_expect_success (control, "TERMINATE", 0);
if (is_verbose)
printf ("shutting down the proxy\n");
rc = zmq_send (control_proxy, "TERMINATE", 9, 0);
assert (rc == 9);
send_string_expect_success (control_proxy, "TERMINATE", 0);
rc = zmq_close (control);
assert (rc == 0);
rc = zmq_close (control_proxy);
assert (rc == 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]);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
}
int main (void)
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_proxy);
return UNITY_END ();
}

View File

@ -29,7 +29,10 @@
#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:

View File

@ -28,92 +28,83 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
// This is our server task.
// It runs a proxy with a single REP socket as both frontend and backend.
void server_task (void *ctx_)
void server_task (void * /*unused_*/)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
void *rep = zmq_socket (ctx_, ZMQ_REP);
assert (rep);
int rc = zmq_bind (rep, "tcp://127.0.0.1:*");
assert (rc == 0);
rc = zmq_getsockopt (rep, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
assert (rc == 0);
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 (ctx_, ZMQ_REQ);
assert (control);
rc = zmq_connect (control, "inproc://control");
assert (rc == 0);
rc = s_send (control, my_endpoint);
assert (rc > 0);
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
TEST_ASSERT_GREATER_THAN_INT (
0, TEST_ASSERT_SUCCESS_ERRNO (s_send (control, my_endpoint)));
// Use rep as both frontend and backend
rc = zmq_proxy_steerable (rep, rep, NULL, control);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_proxy_steerable (rep, rep, NULL, control));
rc = zmq_close (rep);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
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 ();
void *ctx = zmq_ctx_new ();
assert (ctx);
void *server_thread = zmq_threadstart (&server_task, ctx);
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (ctx, ZMQ_REP);
assert (control);
int rc = zmq_bind (control, "inproc://control");
assert (rc == 0);
char *my_endpoint = s_recv (control);
assert (my_endpoint);
// client socket pings proxy over tcp
void *req = zmq_socket (ctx, ZMQ_REQ);
assert (req);
rc = zmq_connect (req, my_endpoint);
assert (rc == 0);
char buf[255];
rc = zmq_send (req, "msg1", 4, 0);
assert (rc == 4);
rc = zmq_recv (req, buf, 255, 0);
assert (rc == 4);
assert (memcmp (buf, "msg1", 4) == 0);
rc = zmq_send (req, "msg22", 5, 0);
assert (rc == 5);
rc = zmq_recv (req, buf, 255, 0);
assert (rc == 5);
assert (memcmp (buf, "msg22", 5) == 0);
rc = zmq_send (control, "TERMINATE", 9, 0);
assert (rc == 9);
rc = zmq_close (control);
assert (rc == 0);
rc = zmq_close (req);
assert (rc == 0);
free (my_endpoint);
zmq_threadclose (server_thread);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
UNITY_BEGIN ();
RUN_TEST (test_proxy_single_socket);
return UNITY_END ();
}

View File

@ -28,104 +28,98 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
// 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 *ctx_)
void server_task (void * /*unused_*/)
{
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
// Frontend socket talks to main process
void *frontend = zmq_socket (ctx_, ZMQ_SUB);
assert (frontend);
int rc = zmq_setsockopt (frontend, ZMQ_SUBSCRIBE, "", 0);
assert (rc == 0);
rc = zmq_bind (frontend, "tcp://127.0.0.1:*");
assert (rc == 0);
rc = zmq_getsockopt (frontend, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
assert (rc == 0);
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 (ctx_, ZMQ_PUSH);
assert (backend);
rc = zmq_bind (backend, "tcp://127.0.0.1:*");
assert (rc == 0);
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 (ctx_, ZMQ_REQ);
assert (control);
rc = zmq_connect (control, "inproc://control");
assert (rc == 0);
rc = s_send (control, my_endpoint);
assert (rc > 0);
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (control, "inproc://control"));
TEST_ASSERT_GREATER_THAN_INT (
0, TEST_ASSERT_SUCCESS_ERRNO (s_send (control, my_endpoint)));
// Connect backend to frontend via a proxy
rc = zmq_proxy_steerable (frontend, backend, NULL, control);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_proxy_steerable (frontend, backend, NULL, control));
rc = zmq_close (frontend);
assert (rc == 0);
rc = zmq_close (backend);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
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 ();
void *ctx = zmq_ctx_new ();
assert (ctx);
void *thread = zmq_threadstart (&server_task, ctx);
// Control socket receives terminate command from main over inproc
void *control = zmq_socket (ctx, ZMQ_REP);
assert (control);
int rc = zmq_bind (control, "inproc://control");
assert (rc == 0);
char *my_endpoint = s_recv (control);
assert (my_endpoint);
msleep (500); // Run for 500 ms
// Start a secondary publisher which writes data to the SUB-PUSH server socket
void *publisher = zmq_socket (ctx, ZMQ_PUB);
assert (publisher);
rc = zmq_connect (publisher, my_endpoint);
assert (rc == 0);
msleep (SETTLE_TIME);
rc = zmq_send (publisher, "This is a test", 14, 0);
assert (rc == 14);
msleep (50);
rc = zmq_send (publisher, "This is a test", 14, 0);
assert (rc == 14);
msleep (50);
rc = zmq_send (publisher, "This is a test", 14, 0);
assert (rc == 14);
rc = zmq_send (control, "TERMINATE", 9, 0);
assert (rc == 9);
rc = zmq_close (publisher);
assert (rc == 0);
rc = zmq_close (control);
assert (rc == 0);
free (my_endpoint);
zmq_threadclose (thread);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
UNITY_BEGIN ();
RUN_TEST (test_proxy_terminate);
return UNITY_END ();
}

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -32,6 +32,15 @@
#include <unity.h>
#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); } \

View File

@ -79,7 +79,7 @@ void test_req_correlate ()
// Receive request id 1
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, router, 0));
assert (zmq_msg_size (&msg) == sizeof (uint32_t));
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);

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <unity.h>
void setUp ()

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -32,37 +32,41 @@
#include <vmci_sockets.h>
#include "testutil.hpp"
#include "testutil_unity.hpp"
int main (void)
void setUp ()
{
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_reqrep_vmci ()
{
std::stringstream s;
s << "vmci://" << VMCISock_GetLocalCID () << ":" << 5560;
std::string endpoint = s.str ();
void *sb = zmq_socket (ctx, ZMQ_REP);
assert (sb);
int rc = zmq_bind (sb, endpoint.c_str ());
assert (rc == 0);
void *sb = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, endpoint.c_str ()));
void *sc = zmq_socket (ctx, ZMQ_REQ);
assert (sc);
rc = zmq_connect (sc, endpoint.c_str ());
assert (rc == 0);
void *sc = test_context_socket (ZMQ_REQ);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, endpoint.c_str ()));
bounce (sb, sc);
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
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

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -30,47 +30,49 @@
#include <stdio.h>
#include "testutil.hpp"
int main (void)
#include "testutil_unity.hpp"
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
void test_router_mandatory_tipc ()
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
TEST_IGNORE_MESSAGE ("TIPC environment unavailable, skipping test");
}
fprintf (stderr, "test_router_mandatory_tipc running...\n");
void *ctx = zmq_init (1);
assert (ctx);
// Creating the first socket.
void *sa = zmq_socket (ctx, ZMQ_ROUTER);
assert (sa);
void *sa = test_context_socket (ZMQ_ROUTER);
int rc = zmq_bind (sa, "tipc://{15560,0,0}");
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sa, "tipc://{15560,0,0}"));
// Sending a message to an unknown peer with the default setting
rc = zmq_send (sa, "UNKNOWN", 7, ZMQ_SNDMORE);
assert (rc == 7);
rc = zmq_send (sa, "DATA", 4, 0);
assert (rc == 4);
send_string_expect_success (sa, "UNKNOWN", ZMQ_SNDMORE);
send_string_expect_success (sa, "DATA", 0);
int mandatory = 1;
// Set mandatory routing on socket
rc =
zmq_setsockopt (sa, ZMQ_ROUTER_MANDATORY, &mandatory, sizeof (mandatory));
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sa, ZMQ_ROUTER_MANDATORY,
&mandatory, sizeof (mandatory)));
// Send a message and check that it fails
rc = zmq_send (sa, "UNKNOWN", 7, ZMQ_SNDMORE | ZMQ_DONTWAIT);
assert (rc == -1 && errno == EHOSTUNREACH);
TEST_ASSERT_FAILURE_ERRNO (
EHOSTUNREACH, zmq_send (sa, "UNKNOWN", 7, ZMQ_SNDMORE | ZMQ_DONTWAIT));
rc = zmq_close (sa);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
test_context_socket_close (sa);
}
int main (void)
{
UNITY_BEGIN ();
RUN_TEST (test_router_mandatory_tipc);
return UNITY_END ();
}

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -28,6 +28,7 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#if defined(ZMQ_HAVE_WINDOWS)
#include <winsock2.h>
#include <ws2tcpip.h>
@ -40,6 +41,9 @@
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
// This test requires a KRB5 environment with the following
// service principal (substitute your host.domain and REALM):
//
@ -55,42 +59,6 @@ const char *name = "zmqtest2";
static volatile int zap_deny_all = 0;
// 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_, int *value_, char **address_)
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, 0) == -1)
return -1; // Interruped, presumably
assert (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value_)
*value_ = *(uint32_t *) (data + 2);
zmq_msg_close (&msg);
// Second frame in message contains event address
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, 0) == -1)
return -1; // Interruped, presumably
assert (!zmq_msg_more (&msg));
if (address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address_ = (char *) malloc (size + 1);
memcpy (*address_, data, size);
*address_[size] = 0;
}
zmq_msg_close (&msg);
return event;
}
// --------------------------------------------------------------------------
// This methods receives and validates ZAP requestes (allowing or denying
// each client connection).
@ -111,8 +79,8 @@ static void zap_handler (void *handler_)
char *mechanism = s_recv (handler_);
char *principal = s_recv (handler_);
assert (streq (version, "1.0"));
assert (streq (mechanism, "GSSAPI"));
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("GSSAPI", mechanism);
s_sendmore (handler_, version);
s_sendmore (handler_, sequence);
@ -141,113 +109,190 @@ static void zap_handler (void *handler_)
zmq_close (handler_);
}
void test_valid_creds (void *ctx_,
void *server_,
void *server_mon_,
char *endpoint_)
static char my_endpoint[MAX_SOCKET_STRING];
static void *zap_thread;
static void *server;
static void *server_mon;
void check_krb_available ()
{
void *client = zmq_socket (ctx_, ZMQ_DEALER);
assert (client);
int rc = zmq_setsockopt (client, ZMQ_GSSAPI_SERVICE_PRINCIPAL, name,
strlen (name) + 1);
assert (rc == 0);
rc = zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1);
assert (rc == 0);
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;
rc = zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type,
sizeof (name_type));
assert (rc == 0);
rc = zmq_connect (client, endpoint_);
assert (rc == 0);
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);
bounce (server_, client);
rc = zmq_close (client);
assert (rc == 0);
// 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));
int event = get_monitor_event (server_mon_, NULL, NULL);
assert (event == ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
// 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);
}
// 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_, int *value_, char **address_)
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, 0) == -1)
return -1; // Interruped, presumably
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value_)
*value_ = *(uint32_t *) (data + 2);
zmq_msg_close (&msg);
// Second frame in message contains event address
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, 0) == -1)
return -1; // Interruped, presumably
TEST_ASSERT_FALSE (zmq_msg_more (&msg));
if (address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address_ = (char *) malloc (size + 1);
memcpy (*address_, data, size);
*address_[size] = 0;
}
zmq_msg_close (&msg);
return event;
}
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 *ctx_,
void *server_,
void *server_mon_,
char *endpoint_)
void test_unauth_creds ()
{
void *client = zmq_socket (ctx_, ZMQ_DEALER);
assert (client);
int rc = zmq_setsockopt (client, ZMQ_GSSAPI_SERVICE_PRINCIPAL, name,
strlen (name) + 1);
assert (rc == 0);
rc = zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1);
assert (rc == 0);
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;
rc = zmq_setsockopt (client, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type,
sizeof (name_type));
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type, sizeof (name_type)));
zap_deny_all = 1;
rc = zmq_connect (client, endpoint_);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint));
expect_bounce_fail (server_, client);
close_zero_linger (client);
expect_bounce_fail (server, client);
test_context_socket_close_zero_linger (client);
int event = get_monitor_event (server_mon_, NULL, NULL);
assert (event == ZMQ_EVENT_HANDSHAKE_FAILED_AUTH);
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 *ctx_,
void *server_,
void *server_mon_,
char *endpoint_)
void test_null_creds ()
{
void *client = zmq_socket (ctx_, ZMQ_DEALER);
assert (client);
int rc = zmq_connect (client, endpoint_);
assert (rc == 0);
expect_bounce_fail (server_, client);
close_zero_linger (client);
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);
assert (event == ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL);
assert (error == ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH);
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 *ctx_,
void *server_,
void *server_mon_,
char *endpoint_)
void test_plain_creds ()
{
void *client = zmq_socket (ctx_, ZMQ_DEALER);
assert (client);
int rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5);
assert (rc == 0);
rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8);
assert (rc == 0);
rc = zmq_connect (client, endpoint_);
assert (rc == 0);
expect_bounce_fail (server_, client);
close_zero_linger (client);
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 (void *ctx_,
void *server_,
void *server_mon_,
char *endpoint_)
void test_vanilla_socket ()
{
struct sockaddr_in ip4addr;
int s;
unsigned short int port;
int rc = sscanf (endpoint_, "tcp://127.0.0.1:%hu", &port);
assert (rc == 1);
int rc = sscanf (my_endpoint, "tcp://127.0.0.1:%hu", &port);
TEST_ASSERT_EQUAL_INT (1, rc);
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons (port);
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
@ -258,95 +303,34 @@ void test_vanilla_socket (void *ctx_,
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
rc = connect (s, (struct sockaddr *) &ip4addr, sizeof (ip4addr));
assert (rc > -1);
TEST_ASSERT_GREATER_THAN (-1, rc);
// 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_);
zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
char *buf = s_recv (server);
if (buf != NULL) {
printf ("Received unauthenticated message: %s\n", buf);
assert (buf == NULL);
TEST_ASSERT_NULL (buf);
}
close (s);
}
int main (void)
{
if (!getenv ("KRB5_KTNAME") || !getenv ("KRB5_CLIENT_KTNAME")) {
printf ("KRB5 environment unavailable, skipping test\n");
return 77; // SKIP
}
// Avoid entanglements with user's credential cache
setenv ("KRB5CCNAME", "MEMORY", 1);
setup_test_environment ();
void *ctx = zmq_ctx_new ();
assert (ctx);
size_t len = MAX_SOCKET_STRING;
char my_endpoint[MAX_SOCKET_STRING];
// 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 (ctx, ZMQ_REP);
assert (handler);
int rc = zmq_bind (handler, "inproc://zeromq.zap.01");
assert (rc == 0);
void *zap_thread = zmq_threadstart (&zap_handler, handler);
// Server socket will accept connections
void *server = zmq_socket (ctx, ZMQ_DEALER);
assert (server);
int as_server = 1;
rc = zmq_setsockopt (server, ZMQ_GSSAPI_SERVER, &as_server, sizeof (int));
assert (rc == 0);
rc = zmq_setsockopt (server, ZMQ_GSSAPI_PRINCIPAL, name, strlen (name) + 1);
assert (rc == 0);
int name_type = ZMQ_GSSAPI_NT_HOSTBASED;
rc = zmq_setsockopt (server, ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, &name_type,
sizeof (name_type));
assert (rc == 0);
rc = zmq_bind (server, "tcp://127.0.0.1:*");
assert (rc == 0);
rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
assert (rc == 0);
// Monitor handshake events on the server
rc = zmq_socket_monitor (server, "inproc://monitor-server",
ZMQ_EVENT_HANDSHAKE_SUCCEEDED
| ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
| ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL);
assert (rc == 0);
// Create socket for collecting monitor events
void *server_mon = NULL;
server_mon = zmq_socket (ctx, ZMQ_PAIR);
assert (server_mon);
// Connect it to the inproc endpoints so they'll get events
rc = zmq_connect (server_mon, "inproc://monitor-server");
assert (rc == 0);
// Attempt various connections
test_valid_creds (ctx, server, server_mon, my_endpoint);
test_null_creds (ctx, server, server_mon, my_endpoint);
test_plain_creds (ctx, server, server_mon, my_endpoint);
test_vanilla_socket (ctx, server, server_mon, my_endpoint);
test_unauth_creds (ctx, server, server_mon, my_endpoint);
// Shutdown
close_zero_linger (server_mon);
rc = zmq_close (server);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
// Wait until ZAP handler terminates
zmq_threadclose (zap_thread);
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 ();
return 0;
}

View File

@ -42,6 +42,8 @@
#include <unistd.h>
#endif
#include <stdlib.h>
static void zap_handler (void *handler_)
{
// Process ZAP requests forever
@ -56,8 +58,8 @@ static void zap_handler (void *handler_)
char *routing_id = s_recv (handler_);
char *mechanism = s_recv (handler_);
assert (streq (version, "1.0"));
assert (streq (mechanism, "NULL"));
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("NULL", mechanism);
s_sendmore (handler_, version);
s_sendmore (handler_, sequence);

View File

@ -42,6 +42,9 @@
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
static void zap_handler (void *zap_)
{
// Process ZAP requests forever
@ -57,9 +60,9 @@ static void zap_handler (void *zap_)
char *username = s_recv (zap_);
char *password = s_recv (zap_);
assert (streq (version, "1.0"));
assert (streq (mechanism, "PLAIN"));
assert (streq (routing_id, "IDENT"));
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING ("PLAIN", mechanism);
TEST_ASSERT_EQUAL_STRING ("IDENT", routing_id);
s_sendmore (zap_, version);
s_sendmore (zap_, sequence);
@ -83,8 +86,7 @@ static void zap_handler (void *zap_)
free (username);
free (password);
}
int rc = zmq_close (zap_);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (zap_));
}
void *zap_thread;

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <pthread.h>
void setUp ()
{
}

View File

@ -30,6 +30,9 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <unity.h>
void setUp ()

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -30,6 +30,7 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#include <unity.h>
void setUp ()

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -30,6 +30,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -30,6 +30,14 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
void setUp ()
{
setup_test_context ();

View File

@ -30,6 +30,9 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -28,6 +28,7 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
#if defined(ZMQ_HAVE_WINDOWS)
#include <winsock2.h>
@ -38,6 +39,16 @@
#include <unistd.h>
#endif
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
// Solaris has a default of 256 max files per process
#ifdef ZMQ_HAVE_SOLARIS
#define MAX_SOCKETS 200
@ -62,6 +73,43 @@ void initialise_network (void)
#endif
void test_localhost ()
{
// Check that we have local networking via ZeroMQ
void *dealer = test_context_socket (ZMQ_DEALER);
if (zmq_bind (dealer, "tcp://127.0.0.1:*") == -1) {
TEST_FAIL_MESSAGE (
"E: Cannot find 127.0.0.1 -- your system does not have local\n"
"E: networking. Please fix this before running libzmq checks.\n");
}
test_context_socket_close (dealer);
}
void test_max_sockets ()
{
// Check that we can create 1,000 sockets
fd_t handle[MAX_SOCKETS];
int count;
for (count = 0; count < MAX_SOCKETS; count++) {
handle[count] = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (handle[count] == -1) {
printf ("W: Only able to create %d sockets on this box\n", count);
const char msg[] =
"I: Tune your system to increase maximum allowed file handles\n"
#if !defined(ZMQ_HAVE_WINDOWS)
"I: Run 'ulimit -n 1200' in bash\n"
#endif
;
TEST_FAIL_MESSAGE (msg);
}
}
// Release the socket handles
for (count = 0; count < MAX_SOCKETS; count++) {
close (handle[count]);
}
}
// This test case stresses the system to shake out known configuration
// problems. We're direct system calls when necessary. Some code may
// need wrapping to be properly portable.
@ -70,37 +118,8 @@ int main (void)
{
initialise_network ();
// Check that we have local networking via ZeroMQ
void *ctx = zmq_ctx_new ();
assert (ctx);
void *dealer = zmq_socket (ctx, ZMQ_DEALER);
if (zmq_bind (dealer, "tcp://127.0.0.1:*") == -1) {
printf (
"E: Cannot find 127.0.0.1 -- your system does not have local\n");
printf (
"E: networking. Please fix this before running libzmq checks.\n");
return -1;
}
// Check that we can create 1,000 sockets
fd_t handle[MAX_SOCKETS];
int count;
for (count = 0; count < MAX_SOCKETS; count++) {
handle[count] = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (handle[count] == -1) {
printf ("W: Only able to create %d sockets on this box\n", count);
printf (
"I: Tune your system to increase maximum allowed file handles\n");
#if !defined(ZMQ_HAVE_WINDOWS)
printf ("I: Run 'ulimit -n 1200' in bash\n");
#endif
return -1;
}
}
// Release the socket handles
for (count = 0; count < MAX_SOCKETS; count++) {
close (handle[count]);
}
zmq_close (dealer);
zmq_ctx_term (ctx);
UNITY_BEGIN ();
RUN_TEST (test_localhost);
RUN_TEST (test_max_sockets);
return UNITY_END ();
}

View File

@ -28,98 +28,84 @@
*/
#include "testutil.hpp"
#include "testutil_unity.hpp"
int main (void)
void setUp ()
{
setup_test_context ();
}
void tearDown ()
{
teardown_test_context ();
}
const char ep[] = "tipc://{5560,0,0}";
const char name[] = "tipc://{5560,0}@0.0.0";
void test_term_endpoint_unbind_tipc ()
{
if (!is_tipc_available ()) {
printf ("TIPC environment unavailable, skipping test\n");
return 77;
TEST_IGNORE_MESSAGE ("TIPC environment unavailable, skipping test\n");
}
int rc;
char buf[32];
const char *ep = "tipc://{5560,0,0}";
const char *name = "tipc://{5560,0}@0.0.0";
fprintf (stderr, "unbind endpoint test running...\n");
// Create infrastructure.
void *ctx = zmq_init (1);
assert (ctx);
void *push = zmq_socket (ctx, ZMQ_PUSH);
assert (push);
rc = zmq_bind (push, ep);
assert (rc == 0);
void *pull = zmq_socket (ctx, ZMQ_PULL);
assert (pull);
rc = zmq_connect (pull, name);
assert (rc == 0);
void *push = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (push, ep));
void *pull = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pull, name));
// Pass one message through to ensure the connection is established.
rc = zmq_send (push, "ABC", 3, 0);
assert (rc == 3);
rc = zmq_recv (pull, buf, sizeof (buf), 0);
assert (rc == 3);
send_string_expect_success (push, "ABC", 0);
recv_string_expect_success (pull, "ABC", 0);
// Unbind the lisnening endpoint
rc = zmq_unbind (push, ep);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (push, ep));
// Let events some time
msleep (SETTLE_TIME);
// Check that sending would block (there's no outbound connection).
rc = zmq_send (push, "ABC", 3, ZMQ_DONTWAIT);
assert (rc == -1 && zmq_errno () == EAGAIN);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_send (push, "ABC", 3, ZMQ_DONTWAIT));
// Clean up.
rc = zmq_close (pull);
assert (rc == 0);
rc = zmq_close (push);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
// Now the other way round.
fprintf (stderr, "disconnect endpoint test running...\n");
test_context_socket_close (pull);
test_context_socket_close (push);
}
void test_term_endpoint_disconnect_tipc ()
{
if (!is_tipc_available ()) {
TEST_IGNORE_MESSAGE ("TIPC environment unavailable, skipping test\n");
}
// Create infrastructure.
ctx = zmq_init (1);
assert (ctx);
push = zmq_socket (ctx, ZMQ_PUSH);
assert (push);
rc = zmq_connect (push, name);
assert (rc == 0);
pull = zmq_socket (ctx, ZMQ_PULL);
assert (pull);
rc = zmq_bind (pull, ep);
assert (rc == 0);
void *push = test_context_socket (ZMQ_PUSH);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (push, name));
void *pull = test_context_socket (ZMQ_PULL);
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pull, ep));
// Pass one message through to ensure the connection is established.
rc = zmq_send (push, "ABC", 3, 0);
assert (rc == 3);
rc = zmq_recv (pull, buf, sizeof (buf), 0);
assert (rc == 3);
send_string_expect_success (push, "ABC", 0);
recv_string_expect_success (pull, "ABC", 0);
// Disconnect the bound endpoint
rc = zmq_disconnect (push, name);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (push, name));
msleep (SETTLE_TIME);
// Check that sending would block (there's no inbound connections).
rc = zmq_send (push, "ABC", 3, ZMQ_DONTWAIT);
assert (rc == -1 && zmq_errno () == EAGAIN);
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_send (push, "ABC", 3, ZMQ_DONTWAIT));
// Clean up.
rc = zmq_close (pull);
assert (rc == 0);
rc = zmq_close (push);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0;
test_context_socket_close (pull);
test_context_socket_close (push);
}
int main (void)
{
UNITY_BEGIN ();
RUN_TEST (test_term_endpoint_unbind_tipc);
RUN_TEST (test_term_endpoint_disconnect_tipc);
return UNITY_END ();
}

View File

@ -20,6 +20,8 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <string.h>
void setUp ()
{
setup_test_context ();

View File

@ -30,7 +30,10 @@
#include "testutil.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
#include <unity.h>
#include <unistd.h>
void setUp ()
{
@ -47,6 +50,7 @@ void tearDown ()
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <unistd.h>
int setup_socket_and_set_fd (void *zmq_socket_,
int af_,

View File

@ -31,8 +31,13 @@
#include "testutil_unity.hpp"
#include <netdb.h>
#include <string.h>
#include <unity.h>
#ifndef _WIN32
#include <unistd.h>
#endif
void setUp ()
{
setup_test_context ();

389
tests/testutil.cpp Normal file
View File

@ -0,0 +1,389 @@
/*
Copyright (c) 2007-2019 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 <stdarg.h>
#include <string.h>
#if defined _WIN32
#include "../src/windows.hpp"
#if defined _MSC_VER
#include <crtdbg.h>
#pragma warning(disable : 4996)
// iphlpapi is needed for if_nametoindex (not on Windows XP)
#if !defined ZMQ_HAVE_WINDOWS_TARGET_XP
#pragma comment(lib, "iphlpapi")
#endif
#endif
#else
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <grp.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#if defined(ZMQ_HAVE_AIX)
#include <sys/types.h>
#include <sys/socketvar.h>
#endif
#endif
const char *SEQ_END = (const char *) 1;
const char bounce_content[] = "12345678ABCDEFGH12345678abcdefgh";
static void send_bounce_msg (void *socket_)
{
send_string_expect_success (socket_, bounce_content, ZMQ_SNDMORE);
send_string_expect_success (socket_, bounce_content, 0);
}
static void recv_bounce_msg (void *socket_)
{
recv_string_expect_success (socket_, bounce_content, 0);
int rcvmore;
size_t sz = sizeof (rcvmore);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_TRUE (rcvmore);
recv_string_expect_success (socket_, bounce_content, 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_RCVMORE, &rcvmore, &sz));
TEST_ASSERT_FALSE (rcvmore);
}
void bounce (void *server_, void *client_)
{
// Send message from client to server
send_bounce_msg (client_);
// Receive message at server side and
// check that message is still the same
recv_bounce_msg (server_);
// Send two parts back to client
send_bounce_msg (server_);
// Receive the two parts at the client side
recv_bounce_msg (client_);
}
static void send_bounce_msg_may_fail (void *socket_)
{
int timeout = 250;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket_, ZMQ_SNDTIMEO, &timeout, sizeof (int)));
int rc = zmq_send (socket_, bounce_content, 32, ZMQ_SNDMORE);
TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
rc = zmq_send (socket_, bounce_content, 32, 0);
TEST_ASSERT_TRUE ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
}
static void recv_bounce_msg_fail (void *socket_)
{
int timeout = 250;
char buffer[32];
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket_, ZMQ_RCVTIMEO, &timeout, sizeof (int)));
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (socket_, buffer, 32, 0));
}
void expect_bounce_fail (void *server_, void *client_)
{
// Send message from client to server
send_bounce_msg_may_fail (client_);
// Receive message at server side (should not succeed)
recv_bounce_msg_fail (server_);
// Send message from server to client to test other direction
// If connection failed, send may block, without a timeout
send_bounce_msg_may_fail (server_);
// Receive message at client side (should not succeed)
recv_bounce_msg_fail (client_);
}
char *s_recv (void *socket_)
{
char buffer[256];
int size = zmq_recv (socket_, buffer, 255, 0);
if (size == -1)
return NULL;
if (size > 255)
size = 255;
buffer[size] = 0;
return strdup (buffer);
}
int s_send (void *socket_, const char *string_)
{
int size = zmq_send (socket_, string_, strlen (string_), 0);
return size;
}
int s_sendmore (void *socket_, const char *string_)
{
int size = zmq_send (socket_, string_, strlen (string_), ZMQ_SNDMORE);
return size;
}
void s_send_seq (void *socket_, ...)
{
va_list ap;
va_start (ap, socket_);
const char *data = va_arg (ap, const char *);
while (true) {
const char *prev = data;
data = va_arg (ap, const char *);
bool end = data == SEQ_END;
if (!prev) {
TEST_ASSERT_SUCCESS_ERRNO (
zmq_send (socket_, 0, 0, end ? 0 : ZMQ_SNDMORE));
} else {
TEST_ASSERT_SUCCESS_ERRNO (zmq_send (
socket_, prev, strlen (prev) + 1, end ? 0 : ZMQ_SNDMORE));
}
if (end)
break;
}
va_end (ap);
}
void s_recv_seq (void *socket_, ...)
{
zmq_msg_t msg;
zmq_msg_init (&msg);
int more;
size_t more_size = sizeof (more);
va_list ap;
va_start (ap, socket_);
const char *data = va_arg (ap, const char *);
while (true) {
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, socket_, 0));
if (!data)
TEST_ASSERT_EQUAL_INT (0, zmq_msg_size (&msg));
else
TEST_ASSERT_EQUAL_STRING (data, (const char *) zmq_msg_data (&msg));
data = va_arg (ap, const char *);
bool end = data == SEQ_END;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size));
TEST_ASSERT_TRUE (!more == end);
if (end)
break;
}
va_end (ap);
zmq_msg_close (&msg);
}
void close_zero_linger (void *socket_)
{
int linger = 0;
int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
TEST_ASSERT_TRUE (rc == 0 || errno == ETERM);
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket_));
}
void setup_test_environment ()
{
#if defined _WIN32
#if defined _MSC_VER
_set_abort_behavior (0, _WRITE_ABORT_MSG);
_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif
#else
#if defined ZMQ_HAVE_CYGWIN
// abort test after 121 seconds
alarm (121);
#else
#if !defined ZMQ_DISABLE_TEST_TIMEOUT
// abort test after 60 seconds
alarm (60);
#endif
#endif
#endif
#if defined __MVS__
// z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
// workaround for no SO_NOGSIGPIPE socket option.
signal (SIGPIPE, SIG_IGN);
#endif
}
void msleep (int milliseconds_)
{
#ifdef ZMQ_HAVE_WINDOWS
Sleep (milliseconds_);
#else
usleep (static_cast<useconds_t> (milliseconds_) * 1000);
#endif
}
int is_ipv6_available ()
{
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
return 0;
#else
int rc, ipv6 = 1;
struct sockaddr_in6 test_addr;
memset (&test_addr, 0, sizeof (test_addr));
test_addr.sin6_family = AF_INET6;
inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr));
fd_t fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
if (fd == retired_fd)
ipv6 = 0;
else {
#ifdef ZMQ_HAVE_WINDOWS
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &ipv6,
sizeof (int));
rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6,
sizeof (int));
if (rc == SOCKET_ERROR)
ipv6 = 0;
else {
rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
if (rc == SOCKET_ERROR)
ipv6 = 0;
}
#else
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof (int));
rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof (int));
if (rc != 0)
ipv6 = 0;
else {
rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
if (rc != 0)
ipv6 = 0;
}
#endif
close (fd);
}
return ipv6;
#endif // _WIN32_WINNT < 0x0600
}
int is_tipc_available ()
{
#ifndef ZMQ_HAVE_TIPC
return 0;
#else
int tipc = 0;
void *ctx = zmq_init (1);
TEST_ASSERT_NOT_NULL (ctx);
void *rep = zmq_socket (ctx, ZMQ_REP);
TEST_ASSERT_NOT_NULL (rep);
tipc = zmq_bind (rep, "tipc://{5560,0,0}");
zmq_close (rep);
zmq_ctx_term (ctx);
return tipc == 0;
#endif // ZMQ_HAVE_TIPC
}
int test_inet_pton (int af_, const char *src_, void *dst_)
{
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
if (af_ == AF_INET) {
struct in_addr *ip4addr = (struct in_addr *) dst_;
ip4addr->s_addr = inet_addr (src_);
// INADDR_NONE is -1 which is also a valid representation for IP
// 255.255.255.255
if (ip4addr->s_addr == INADDR_NONE
&& strcmp (src_, "255.255.255.255") != 0) {
return 0;
}
// Success
return 1;
} else {
// Not supported.
return 0;
}
#else
return inet_pton (af_, src_, dst_);
#endif
}
sockaddr_in bind_bsd_socket (int socket)
{
struct sockaddr_in saddr;
memset (&saddr, 0, sizeof (saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
saddr.sin_port = 0;
#else
saddr.sin_port = htons (PORT_6);
#endif
TEST_ASSERT_SUCCESS_RAW_ERRNO (
bind (socket, (struct sockaddr *) &saddr, sizeof (saddr)));
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
socklen_t saddr_len = sizeof (saddr);
TEST_ASSERT_SUCCESS_RAW_ERRNO (
getsockname (socket, (struct sockaddr *) &saddr, &saddr_len));
#endif
return saddr;
}
bool streq (const char *lhs, const char *rhs)
{
return strcmp (lhs, rhs) == 0;
}
bool strneq (const char *lhs, const char *rhs)
{
return strcmp (lhs, rhs) != 0;
}

View File

@ -58,40 +58,6 @@
#define PORT_6 5561
#undef NDEBUG
#include <time.h>
#include <assert.h>
#include <stdarg.h>
#include <string>
#include <string.h>
#if defined _WIN32
#include "../src/windows.hpp"
#if defined _MSC_VER
#include <crtdbg.h>
#pragma warning(disable : 4996)
// iphlpapi is needed for if_nametoindex (not on Windows XP)
#if !defined ZMQ_HAVE_WINDOWS_TARGET_XP
#pragma comment(lib, "iphlpapi")
#endif
#endif
#else
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <grp.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#if defined(ZMQ_HAVE_AIX)
#include <sys/types.h>
#include <sys/socketvar.h>
#endif
#endif
// duplicated from fd.hpp
#ifdef ZMQ_HAVE_WINDOWS
@ -100,7 +66,7 @@
#include <stdexcept>
#define close closesocket
typedef int socket_size_t;
const char *as_setsockopt_opt_t (const void *opt)
inline const char *as_setsockopt_opt_t (const void *opt)
{
return static_cast<const char *> (opt);
}
@ -119,7 +85,7 @@ enum
#endif
#else
typedef size_t socket_size_t;
const void *as_setsockopt_opt_t (const void *opt_)
inline const void *as_setsockopt_opt_t (const void *opt_)
{
return opt_;
}
@ -134,373 +100,67 @@ enum
// Bounce a message from client to server and back
// For REQ/REP or DEALER/DEALER pairs only
void bounce (void *server_, void *client_)
{
const char *content = "12345678ABCDEFGH12345678abcdefgh";
// Send message from client to server
int rc = zmq_send (client_, content, 32, ZMQ_SNDMORE);
assert (rc == 32);
rc = zmq_send (client_, content, 32, 0);
assert (rc == 32);
// Receive message at server side
char buffer[32];
rc = zmq_recv (server_, buffer, 32, 0);
assert (rc == 32);
// Check that message is still the same
assert (memcmp (buffer, content, 32) == 0);
int rcvmore;
size_t sz = sizeof (rcvmore);
rc = zmq_getsockopt (server_, ZMQ_RCVMORE, &rcvmore, &sz);
assert (rc == 0);
assert (rcvmore);
rc = zmq_recv (server_, buffer, 32, 0);
assert (rc == 32);
// Check that message is still the same
assert (memcmp (buffer, content, 32) == 0);
rc = zmq_getsockopt (server_, ZMQ_RCVMORE, &rcvmore, &sz);
assert (rc == 0);
assert (!rcvmore);
// Send two parts back to client
rc = zmq_send (server_, buffer, 32, ZMQ_SNDMORE);
assert (rc == 32);
rc = zmq_send (server_, buffer, 32, 0);
assert (rc == 32);
// Receive the two parts at the client side
rc = zmq_recv (client_, buffer, 32, 0);
assert (rc == 32);
// Check that message is still the same
assert (memcmp (buffer, content, 32) == 0);
rc = zmq_getsockopt (client_, ZMQ_RCVMORE, &rcvmore, &sz);
assert (rc == 0);
assert (rcvmore);
rc = zmq_recv (client_, buffer, 32, 0);
assert (rc == 32);
// Check that message is still the same
assert (memcmp (buffer, content, 32) == 0);
rc = zmq_getsockopt (client_, ZMQ_RCVMORE, &rcvmore, &sz);
assert (rc == 0);
assert (!rcvmore);
}
void bounce (void *server_, void *client_);
// Same as bounce, but expect messages to never arrive
// for security or subscriber reasons.
void expect_bounce_fail (void *server_, void *client_)
{
const char *content = "12345678ABCDEFGH12345678abcdefgh";
char buffer[32];
int timeout = 250;
// Send message from client to server
int rc = zmq_setsockopt (client_, ZMQ_SNDTIMEO, &timeout, sizeof (int));
assert (rc == 0);
rc = zmq_send (client_, content, 32, ZMQ_SNDMORE);
assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
rc = zmq_send (client_, content, 32, 0);
assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
// Receive message at server side (should not succeed)
rc = zmq_setsockopt (server_, ZMQ_RCVTIMEO, &timeout, sizeof (int));
assert (rc == 0);
rc = zmq_recv (server_, buffer, 32, 0);
assert (rc == -1);
assert (zmq_errno () == EAGAIN);
// Send message from server to client to test other direction
// If connection failed, send may block, without a timeout
rc = zmq_setsockopt (server_, ZMQ_SNDTIMEO, &timeout, sizeof (int));
assert (rc == 0);
rc = zmq_send (server_, content, 32, ZMQ_SNDMORE);
assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
rc = zmq_send (server_, content, 32, 0);
assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
// Receive message at client side (should not succeed)
rc = zmq_setsockopt (client_, ZMQ_RCVTIMEO, &timeout, sizeof (int));
assert (rc == 0);
rc = zmq_recv (client_, buffer, 32, 0);
assert (rc == -1);
assert (zmq_errno () == EAGAIN);
}
void expect_bounce_fail (void *server_, void *client_);
// Receive 0MQ string from socket and convert into C string
// Caller must free returned string. Returns NULL if the context
// is being terminated.
char *s_recv (void *socket_)
{
char buffer[256];
int size = zmq_recv (socket_, buffer, 255, 0);
if (size == -1)
return NULL;
if (size > 255)
size = 255;
buffer[size] = 0;
return strdup (buffer);
}
char *s_recv (void *socket_);
// Convert C string to 0MQ string and send to socket
int s_send (void *socket_, const char *string_)
{
int size = zmq_send (socket_, string_, strlen (string_), 0);
return size;
}
int s_send (void *socket_, const char *string_);
// Sends string as 0MQ string, as multipart non-terminal
int s_sendmore (void *socket_, const char *string_)
{
int size = zmq_send (socket_, string_, strlen (string_), ZMQ_SNDMORE);
return size;
}
int s_sendmore (void *socket_, const char *string_);
#define streq(s1, s2) (!strcmp ((s1), (s2)))
#define strneq(s1, s2) (strcmp ((s1), (s2)))
bool streq (const char *lhs, const char *rhs);
bool strneq (const char *lhs, const char *rhs);
const char *SEQ_END = (const char *) 1;
extern const char *SEQ_END;
// Sends a message composed of frames that are C strings or null frames.
// The list must be terminated by SEQ_END.
// Example: s_send_seq (req, "ABC", 0, "DEF", SEQ_END);
void s_send_seq (void *socket_, ...)
{
va_list ap;
va_start (ap, socket_);
const char *data = va_arg (ap, const char *);
while (true) {
const char *prev = data;
data = va_arg (ap, const char *);
bool end = data == SEQ_END;
if (!prev) {
int rc = zmq_send (socket_, 0, 0, end ? 0 : ZMQ_SNDMORE);
assert (rc != -1);
} else {
int rc = zmq_send (socket_, prev, strlen (prev) + 1,
end ? 0 : ZMQ_SNDMORE);
assert (rc != -1);
}
if (end)
break;
}
va_end (ap);
}
void s_send_seq (void *socket_, ...);
// Receives message a number of frames long and checks that the frames have
// the given data which can be either C strings or 0 for a null frame.
// The list must be terminated by SEQ_END.
// Example: s_recv_seq (rep, "ABC", 0, "DEF", SEQ_END);
void s_recv_seq (void *socket_, ...)
{
zmq_msg_t msg;
zmq_msg_init (&msg);
int more;
size_t more_size = sizeof (more);
va_list ap;
va_start (ap, socket_);
const char *data = va_arg (ap, const char *);
while (true) {
int rc = zmq_msg_recv (&msg, socket_, 0);
assert (rc != -1);
if (!data)
assert (zmq_msg_size (&msg) == 0);
else
assert (strcmp (data, (const char *) zmq_msg_data (&msg)) == 0);
data = va_arg (ap, const char *);
bool end = data == SEQ_END;
rc = zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size);
assert (rc == 0);
assert (!more == end);
if (end)
break;
}
va_end (ap);
zmq_msg_close (&msg);
}
void s_recv_seq (void *socket_, ...);
// Sets a zero linger period on a socket and closes it.
void close_zero_linger (void *socket_)
{
int linger = 0;
int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
assert (rc == 0 || errno == ETERM);
rc = zmq_close (socket_);
assert (rc == 0);
}
void close_zero_linger (void *socket_);
void setup_test_environment (void)
{
#if defined _WIN32
#if defined _MSC_VER
_set_abort_behavior (0, _WRITE_ABORT_MSG);
_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif
#else
#if defined ZMQ_HAVE_CYGWIN
// abort test after 121 seconds
alarm (121);
#else
#if !defined ZMQ_DISABLE_TEST_TIMEOUT
// abort test after 60 seconds
alarm (60);
#endif
#endif
#endif
#if defined __MVS__
// z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
// workaround for no SO_NOGSIGPIPE socket option.
signal (SIGPIPE, SIG_IGN);
#endif
}
void setup_test_environment (void);
// Provide portable millisecond sleep
// http://www.cplusplus.com/forum/unices/60161/
// http://en.cppreference.com/w/cpp/thread/sleep_for
void msleep (int milliseconds_)
{
#ifdef ZMQ_HAVE_WINDOWS
Sleep (milliseconds_);
#else
usleep (static_cast<useconds_t> (milliseconds_) * 1000);
#endif
}
void msleep (int milliseconds_);
// check if IPv6 is available (0/false if not, 1/true if it is)
// only way to reliably check is to actually open a socket and try to bind it
int is_ipv6_available (void)
{
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
return 0;
#else
int rc, ipv6 = 1;
struct sockaddr_in6 test_addr;
memset (&test_addr, 0, sizeof (test_addr));
test_addr.sin6_family = AF_INET6;
inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr));
fd_t fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
if (fd == retired_fd)
ipv6 = 0;
else {
#ifdef ZMQ_HAVE_WINDOWS
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &ipv6,
sizeof (int));
rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6,
sizeof (int));
if (rc == SOCKET_ERROR)
ipv6 = 0;
else {
rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
if (rc == SOCKET_ERROR)
ipv6 = 0;
}
#else
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof (int));
rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof (int));
if (rc != 0)
ipv6 = 0;
else {
rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
if (rc != 0)
ipv6 = 0;
}
#endif
close (fd);
}
return ipv6;
#endif // _WIN32_WINNT < 0x0600
}
int is_ipv6_available (void);
// check if tipc is available (0/false if not, 1/true if it is)
// only way to reliably check is to actually open a socket and try to bind it
// as it depends on a non-default kernel module to be already loaded
int is_tipc_available (void)
{
#ifndef ZMQ_HAVE_TIPC
return 0;
#else
int tipc = 0;
void *ctx = zmq_init (1);
assert (ctx);
void *rep = zmq_socket (ctx, ZMQ_REP);
assert (rep);
tipc = zmq_bind (rep, "tipc://{5560,0,0}");
zmq_close (rep);
zmq_ctx_term (ctx);
return tipc == 0;
#endif // ZMQ_HAVE_TIPC
}
int is_tipc_available (void);
// Wrapper around 'inet_pton' for systems that don't support it (e.g. Windows
// XP)
int test_inet_pton (int af_, const char *src_, void *dst_)
{
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
if (af_ == AF_INET) {
struct in_addr *ip4addr = (struct in_addr *) dst_;
ip4addr->s_addr = inet_addr (src_);
// INADDR_NONE is -1 which is also a valid representation for IP
// 255.255.255.255
if (ip4addr->s_addr == INADDR_NONE
&& strcmp (src_, "255.255.255.255") != 0) {
return 0;
}
// Success
return 1;
} else {
// Not supported.
return 0;
}
#else
return inet_pton (af_, src_, dst_);
#endif
}
int test_inet_pton (int af_, const char *src_, void *dst_);
// Binds an ipv4 BSD socket to an ephemeral port, returns the compiled sockaddr
struct sockaddr_in bind_bsd_socket (int socket)
{
struct sockaddr_in saddr;
memset (&saddr, 0, sizeof (saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
saddr.sin_port = 0;
#else
saddr.sin_port = htons (PORT_6);
#endif
int rc = bind (socket, (struct sockaddr *) &saddr, sizeof (saddr));
assert (rc == 0);
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
socklen_t saddr_len = sizeof (saddr);
rc = getsockname (socket, (struct sockaddr *) &saddr, &saddr_len);
assert (rc == 0);
#endif
return saddr;
}
struct sockaddr_in bind_bsd_socket (int socket);
#endif

View File

@ -0,0 +1,349 @@
/*
Copyright (c) 2007-2019 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_monitoring.hpp"
#include "testutil_unity.hpp"
#include <stdlib.h>
#include <string.h>
// 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_internal (void *monitor_,
int *value_,
char **address_,
int recv_flag_)
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value_)
memcpy (value_, data + 2, sizeof (uint32_t));
// Second frame in message contains event address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_FALSE (zmq_msg_more (&msg));
if (address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address_ = (char *) malloc (size + 1);
memcpy (*address_, data, size);
(*address_)[size] = 0;
}
return event;
}
int get_monitor_event_with_timeout (void *monitor_,
int *value_,
char **address_,
int timeout_)
{
int res;
if (timeout_ == -1) {
// process infinite timeout in small steps to allow the user
// to see some information on the console
int timeout_step = 250;
int wait_time = 0;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_step,
sizeof (timeout_step));
while (
(res = get_monitor_event_internal (monitor_, value_, address_, 0))
== -1) {
wait_time += timeout_step;
fprintf (stderr, "Still waiting for monitor event after %i ms\n",
wait_time);
}
} else {
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_, sizeof (timeout_));
res = get_monitor_event_internal (monitor_, value_, address_, 0);
}
int timeout_infinite = -1;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_infinite,
sizeof (timeout_infinite));
return res;
}
int get_monitor_event (void *monitor_, int *value_, char **address_)
{
return get_monitor_event_with_timeout (monitor_, value_, address_, -1);
}
void expect_monitor_event (void *monitor_, int expected_event_)
{
TEST_ASSERT_EQUAL_HEX (expected_event_,
get_monitor_event (monitor_, NULL, NULL));
}
static void print_unexpected_event (char *buf_,
size_t buf_size_,
int event_,
int err_,
int expected_event_,
int expected_err_)
{
snprintf (buf_, buf_size_,
"Unexpected event: 0x%x, value = %i/0x%x (expected: 0x%x, value "
"= %i/0x%x)\n",
event_, err_, err_, expected_event_, expected_err_,
expected_err_);
}
void print_unexpected_event_stderr (int event_,
int err_,
int expected_event_,
int expected_err_)
{
char buf[256];
print_unexpected_event (buf, sizeof buf, event_, err_, expected_event_,
expected_err_);
fputs (buf, stderr);
}
int expect_monitor_event_multiple (void *server_mon_,
int expected_event_,
int expected_err_,
bool optional_)
{
int count_of_expected_events = 0;
int client_closed_connection = 0;
int timeout = 250;
int wait_time = 0;
int event;
int err;
while ((event =
get_monitor_event_with_timeout (server_mon_, &err, NULL, timeout))
!= -1
|| !count_of_expected_events) {
if (event == -1) {
if (optional_)
break;
wait_time += timeout;
fprintf (stderr,
"Still waiting for first event after %ims (expected event "
"%x (value %i/0x%x))\n",
wait_time, expected_event_, expected_err_, expected_err_);
continue;
}
// ignore errors with EPIPE/ECONNRESET/ECONNABORTED, which can happen
// ECONNRESET can happen on very slow machines, when the engine writes
// to the peer and then tries to read the socket before the peer reads
// ECONNABORTED happens when a client aborts a connection via RST/timeout
if (event == ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
&& ((err == EPIPE && expected_err_ != EPIPE) || err == ECONNRESET
|| err == ECONNABORTED)) {
fprintf (stderr,
"Ignored event (skipping any further events): %x (err = "
"%i == %s)\n",
event, err, zmq_strerror (err));
client_closed_connection = 1;
break;
}
if (event != expected_event_
|| (-1 != expected_err_ && err != expected_err_)) {
char buf[256];
print_unexpected_event (buf, sizeof buf, event, err,
expected_event_, expected_err_);
TEST_FAIL_MESSAGE (buf);
}
++count_of_expected_events;
}
TEST_ASSERT_TRUE (optional_ || count_of_expected_events > 0
|| client_closed_connection);
return count_of_expected_events;
}
static int64_t get_monitor_event_internal_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_,
int recv_flag_)
{
// First frame in message contains event number
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
uint64_t event;
memcpy (&event, zmq_msg_data (&msg), sizeof (event));
zmq_msg_close (&msg);
// Second frame in message contains the number of values
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
uint64_t value_count;
memcpy (&value_count, zmq_msg_data (&msg), sizeof (value_count));
zmq_msg_close (&msg);
for (uint64_t i = 0; i < value_count; ++i) {
// Subsequent frames in message contain event values
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
if (value_ && value_ + i)
memcpy (value_ + i, zmq_msg_data (&msg), sizeof (*value_));
zmq_msg_close (&msg);
}
// Second-to-last frame in message contains local address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
if (local_address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*local_address_ = (char *) malloc (size + 1);
memcpy (*local_address_, data, size);
(*local_address_)[size] = 0;
}
zmq_msg_close (&msg);
// Last frame in message contains remote address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_TRUE (!zmq_msg_more (&msg));
if (remote_address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*remote_address_ = (char *) malloc (size + 1);
memcpy (*remote_address_, data, size);
(*remote_address_)[size] = 0;
}
zmq_msg_close (&msg);
return event;
}
static int64_t get_monitor_event_with_timeout_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_,
int timeout_)
{
int64_t res;
if (timeout_ == -1) {
// process infinite timeout in small steps to allow the user
// to see some information on the console
int timeout_step = 250;
int wait_time = 0;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_step,
sizeof (timeout_step));
while ((res = get_monitor_event_internal_v2 (
monitor_, value_, local_address_, remote_address_, 0))
== -1) {
wait_time += timeout_step;
fprintf (stderr, "Still waiting for monitor event after %i ms\n",
wait_time);
}
} else {
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_, sizeof (timeout_));
res = get_monitor_event_internal_v2 (monitor_, value_, local_address_,
remote_address_, 0);
}
int timeout_infinite = -1;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_infinite,
sizeof (timeout_infinite));
return res;
}
int64_t get_monitor_event_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_)
{
return get_monitor_event_with_timeout_v2 (monitor_, value_, local_address_,
remote_address_, -1);
}
void expect_monitor_event_v2 (void *monitor_,
int64_t expected_event_,
const char *expected_local_address_,
const char *expected_remote_address_)
{
char *local_address = NULL;
char *remote_address = NULL;
int64_t event = get_monitor_event_v2 (
monitor_, NULL, expected_local_address_ ? &local_address : NULL,
expected_remote_address_ ? &remote_address : NULL);
bool failed = false;
char buf[256];
char *pos = buf;
if (event != expected_event_) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected monitor event %llx, but received %llx\n",
(long long) expected_event_, (long long) event);
failed = true;
}
if (expected_local_address_
&& 0 != strcmp (local_address, expected_local_address_)) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected local address %s, but received %s\n",
expected_local_address_, local_address);
}
if (expected_remote_address_
&& 0 != strcmp (remote_address, expected_remote_address_)) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected remote address %s, but received %s\n",
expected_remote_address_, remote_address);
}
free (local_address);
free (remote_address);
TEST_ASSERT_FALSE_MESSAGE (failed, buf);
}

View File

@ -30,114 +30,26 @@
#ifndef __TESTUTIL_MONITORING_HPP_INCLUDED__
#define __TESTUTIL_MONITORING_HPP_INCLUDED__
#include "testutil_unity.hpp"
#include "../include/zmq.h"
#include "../src/stdint.hpp"
#include <stddef.h>
// General, i.e. non-security specific, monitor utilities
// 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_internal (void *monitor_,
int *value_,
char **address_,
int recv_flag_)
{
// First frame in message contains event number and value
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
uint16_t event = *(uint16_t *) (data);
if (value_)
memcpy (value_, data + 2, sizeof (uint32_t));
// Second frame in message contains event address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_FALSE (zmq_msg_more (&msg));
if (address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*address_ = (char *) malloc (size + 1);
memcpy (*address_, data, size);
(*address_)[size] = 0;
}
return event;
}
int get_monitor_event_with_timeout (void *monitor_,
int *value_,
char **address_,
int timeout_)
{
int res;
if (timeout_ == -1) {
// process infinite timeout in small steps to allow the user
// to see some information on the console
int timeout_);
int timeout_step = 250;
int wait_time = 0;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_step,
sizeof (timeout_step));
while (
(res = get_monitor_event_internal (monitor_, value_, address_, 0))
== -1) {
wait_time += timeout_step;
fprintf (stderr, "Still waiting for monitor event after %i ms\n",
wait_time);
}
} else {
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_, sizeof (timeout_));
res = get_monitor_event_internal (monitor_, value_, address_, 0);
}
int timeout_infinite = -1;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_infinite,
sizeof (timeout_infinite));
return res;
}
int get_monitor_event (void *monitor_, int *value_, char **address_);
int get_monitor_event (void *monitor_, int *value_, char **address_)
{
return get_monitor_event_with_timeout (monitor_, value_, address_, -1);
}
void expect_monitor_event (void *monitor_, int expected_event_)
{
TEST_ASSERT_EQUAL_HEX (expected_event_,
get_monitor_event (monitor_, NULL, NULL));
}
void print_unexpected_event (char *buf_,
size_t buf_size_,
int event_,
int err_,
int expected_event_,
int expected_err_)
{
snprintf (buf_, buf_size_,
"Unexpected event: 0x%x, value = %i/0x%x (expected: 0x%x, value "
"= %i/0x%x)\n",
event_, err_, err_, expected_event_, expected_err_,
expected_err_);
}
void expect_monitor_event (void *monitor_, int expected_event_);
void print_unexpected_event_stderr (int event_,
int err_,
int expected_event_,
int expected_err_)
{
char buf[256];
print_unexpected_event (buf, sizeof buf, event_, err_, expected_event_,
expected_err_);
fputs (buf, stderr);
}
int expected_err_);
// expects that one or more occurrences of the expected event are received
// via the specified socket monitor
@ -149,216 +61,15 @@ void print_unexpected_event_stderr (int event_,
int expect_monitor_event_multiple (void *server_mon_,
int expected_event_,
int expected_err_ = -1,
bool optional_ = false)
{
int count_of_expected_events = 0;
int client_closed_connection = 0;
int timeout = 250;
int wait_time = 0;
int event;
int err;
while ((event =
get_monitor_event_with_timeout (server_mon_, &err, NULL, timeout))
!= -1
|| !count_of_expected_events) {
if (event == -1) {
if (optional_)
break;
wait_time += timeout;
fprintf (stderr,
"Still waiting for first event after %ims (expected event "
"%x (value %i/0x%x))\n",
wait_time, expected_event_, expected_err_, expected_err_);
continue;
}
// ignore errors with EPIPE/ECONNRESET/ECONNABORTED, which can happen
// ECONNRESET can happen on very slow machines, when the engine writes
// to the peer and then tries to read the socket before the peer reads
// ECONNABORTED happens when a client aborts a connection via RST/timeout
if (event == ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
&& ((err == EPIPE && expected_err_ != EPIPE) || err == ECONNRESET
|| err == ECONNABORTED)) {
fprintf (stderr,
"Ignored event (skipping any further events): %x (err = "
"%i == %s)\n",
event, err, zmq_strerror (err));
client_closed_connection = 1;
break;
}
if (event != expected_event_
|| (-1 != expected_err_ && err != expected_err_)) {
char buf[256];
print_unexpected_event (buf, sizeof buf, event, err,
expected_event_, expected_err_);
TEST_FAIL_MESSAGE (buf);
}
++count_of_expected_events;
}
TEST_ASSERT_TRUE (optional_ || count_of_expected_events > 0
|| client_closed_connection);
return count_of_expected_events;
}
#if (defined ZMQ_CURRENT_EVENT_VERSION && ZMQ_CURRENT_EVENT_VERSION >= 2) \
|| (defined ZMQ_CURRENT_EVENT_VERSION \
&& ZMQ_CURRENT_EVENT_VERSION_DRAFT >= 2)
static int64_t get_monitor_event_internal_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_,
int recv_flag_)
{
// First frame in message contains event number
zmq_msg_t msg;
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
uint64_t event;
memcpy (&event, zmq_msg_data (&msg), sizeof (event));
zmq_msg_close (&msg);
// Second frame in message contains the number of values
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
uint64_t value_count;
memcpy (&value_count, zmq_msg_data (&msg), sizeof (value_count));
zmq_msg_close (&msg);
for (uint64_t i = 0; i < value_count; ++i) {
// Subsequent frames in message contain event values
zmq_msg_init (&msg);
if (zmq_msg_recv (&msg, monitor_, recv_flag_) == -1) {
TEST_ASSERT_FAILURE_ERRNO (EAGAIN, -1);
return -1; // timed out or no message available
}
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
TEST_ASSERT_EQUAL_UINT (sizeof (uint64_t), zmq_msg_size (&msg));
if (value_ && value_ + i)
memcpy (value_ + i, zmq_msg_data (&msg), sizeof (*value_));
zmq_msg_close (&msg);
}
// Second-to-last frame in message contains local address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_TRUE (zmq_msg_more (&msg));
if (local_address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*local_address_ = (char *) malloc (size + 1);
memcpy (*local_address_, data, size);
(*local_address_)[size] = 0;
}
zmq_msg_close (&msg);
// Last frame in message contains remote address
zmq_msg_init (&msg);
TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, monitor_, recv_flag_));
TEST_ASSERT_TRUE (!zmq_msg_more (&msg));
if (remote_address_) {
uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
size_t size = zmq_msg_size (&msg);
*remote_address_ = (char *) malloc (size + 1);
memcpy (*remote_address_, data, size);
(*remote_address_)[size] = 0;
}
zmq_msg_close (&msg);
return event;
}
int64_t get_monitor_event_with_timeout_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_,
int timeout_)
{
int64_t res;
if (timeout_ == -1) {
// process infinite timeout in small steps to allow the user
// to see some information on the console
int timeout_step = 250;
int wait_time = 0;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_step,
sizeof (timeout_step));
while ((res = get_monitor_event_internal_v2 (
monitor_, value_, local_address_, remote_address_, 0))
== -1) {
wait_time += timeout_step;
fprintf (stderr, "Still waiting for monitor event after %i ms\n",
wait_time);
}
} else {
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_, sizeof (timeout_));
res = get_monitor_event_internal_v2 (monitor_, value_, local_address_,
remote_address_, 0);
}
int timeout_infinite = -1;
zmq_setsockopt (monitor_, ZMQ_RCVTIMEO, &timeout_infinite,
sizeof (timeout_infinite));
return res;
}
bool optional_ = false);
int64_t get_monitor_event_v2 (void *monitor_,
uint64_t *value_,
char **local_address_,
char **remote_address_)
{
return get_monitor_event_with_timeout_v2 (monitor_, value_, local_address_,
remote_address_, -1);
}
char **remote_address_);
void expect_monitor_event_v2 (void *monitor_,
int64_t expected_event_,
const char *expected_local_address_ = NULL,
const char *expected_remote_address_ = NULL)
{
char *local_address = NULL;
char *remote_address = NULL;
int64_t event = get_monitor_event_v2 (
monitor_, NULL, expected_local_address_ ? &local_address : NULL,
expected_remote_address_ ? &remote_address : NULL);
bool failed = false;
char buf[256];
char *pos = buf;
if (event != expected_event_) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected monitor event %llx, but received %llx\n",
(long long) expected_event_, (long long) event);
failed = true;
}
if (expected_local_address_
&& 0 != strcmp (local_address, expected_local_address_)) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected local address %s, but received %s\n",
expected_local_address_, local_address);
}
if (expected_remote_address_
&& 0 != strcmp (remote_address, expected_remote_address_)) {
pos += snprintf (pos, sizeof buf - (pos - buf),
"Expected remote address %s, but received %s\n",
expected_remote_address_, remote_address);
}
free (local_address);
free (remote_address);
TEST_ASSERT_FALSE_MESSAGE (failed, buf);
}
#endif
const char *expected_remote_address_ = NULL);
#endif

401
tests/testutil_security.cpp Normal file
View File

@ -0,0 +1,401 @@
/*
Copyright (c) 2007-2019 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 <stdlib.h>
#include <string.h>
const char *test_zap_domain = "ZAPTEST";
void socket_config_null_client (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_);
LIBZMQ_UNUSED (server_secret_);
}
void socket_config_null_server (void *server_, void *server_secret_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
int required = server_secret_ ? *(int *) server_secret_ : 0;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
&required, sizeof (int)));
#else
LIBZMQ_UNUSED (server_secret_);
#endif
}
static const char test_plain_username[] = "testuser";
static const char test_plain_password[] = "testpass";
void socket_config_plain_client (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_secret_);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_PASSWORD, test_plain_password, 8));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_USERNAME, test_plain_username, 8));
}
void socket_config_plain_server (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_secret_);
int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
}
char valid_client_public[41];
char valid_client_secret[41];
char valid_server_public[41];
char valid_server_secret[41];
void setup_testutil_security_curve ()
{
// Generate new keypairs for these tests
TEST_ASSERT_SUCCESS_ERRNO (
zmq_curve_keypair (valid_client_public, valid_client_secret));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_curve_keypair (valid_server_public, valid_server_secret));
}
void socket_config_curve_server (void *server_, void *server_secret_)
{
int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_CURVE_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_CURVE_SECRETKEY, server_secret_, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
int required = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
&required, sizeof (int)));
#endif
}
void socket_config_curve_client (void *client_, void *data_)
{
curve_client_data_t *curve_client_data =
static_cast<curve_client_data_t *> (data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_SERVERKEY, curve_client_data->server_public, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_PUBLICKEY, curve_client_data->client_public, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_SECRETKEY, curve_client_data->client_secret, 41));
}
void *zap_requests_handled;
void zap_handler_generic (zap_protocol_t zap_protocol_,
const char *expected_routing_id_)
{
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (control, "inproc://handler-control"));
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"));
// Signal main thread that we are ready
send_string_expect_success (control, "GO", 0);
zmq_pollitem_t items[] = {
{control, 0, ZMQ_POLLIN, 0},
{handler, 0, ZMQ_POLLIN, 0},
};
// if ordered not to receive the request, ignore the second poll item
const int numitems = (zap_protocol_ == zap_do_not_recv) ? 1 : 2;
// Process ZAP requests forever
while (zmq_poll (items, numitems, -1) >= 0) {
if (items[0].revents & ZMQ_POLLIN) {
recv_string_expect_success (control, "STOP", 0);
break; // Terminating - main thread signal
}
if (!(items[1].revents & ZMQ_POLLIN))
continue;
char *version = s_recv (handler);
if (!version)
break; // Terminating - peer's socket closed
if (zap_protocol_ == zap_disconnect) {
free (version);
break;
}
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);
bool authentication_succeeded = false;
if (streq (mechanism, "CURVE")) {
uint8_t client_key[32];
TEST_ASSERT_EQUAL_INT (32, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
handler, client_key, 32, 0)));
char client_key_text[41];
zmq_z85_encode (client_key_text, client_key, 32);
authentication_succeeded =
streq (client_key_text, valid_client_public);
} else if (streq (mechanism, "PLAIN")) {
char client_username[32];
int size = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (handler, client_username, 32, 0));
client_username[size] = 0;
char client_password[32];
size = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (handler, client_password, 32, 0));
client_password[size] = 0;
authentication_succeeded =
streq (test_plain_username, client_username)
&& streq (test_plain_password, client_password);
} else if (streq (mechanism, "NULL")) {
authentication_succeeded = true;
} else {
char msg[128];
printf ("Unsupported mechanism: %s\n", mechanism);
TEST_FAIL_MESSAGE (msg);
}
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING (expected_routing_id_, routing_id);
s_sendmore (handler, zap_protocol_ == zap_wrong_version
? "invalid_version"
: version);
s_sendmore (handler, zap_protocol_ == zap_wrong_request_id
? "invalid_request_id"
: sequence);
if (authentication_succeeded) {
const char *status_code;
switch (zap_protocol_) {
case zap_status_internal_error:
status_code = "500";
break;
case zap_status_temporary_failure:
status_code = "300";
break;
case zap_status_invalid:
status_code = "invalid_status";
break;
default:
status_code = "200";
}
s_sendmore (handler, status_code);
s_sendmore (handler, "OK");
s_sendmore (handler, "anonymous");
if (zap_protocol_ == zap_too_many_parts) {
s_sendmore (handler, "");
}
if (zap_protocol_ != zap_do_not_send)
s_send (handler, "");
} else {
s_sendmore (handler, "400");
s_sendmore (handler, "Invalid client public key");
s_sendmore (handler, "");
if (zap_protocol_ != zap_do_not_send)
s_send (handler, "");
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
zmq_atomic_counter_inc (zap_requests_handled);
}
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (handler, "inproc://zeromq.zap.01"));
close_zero_linger (handler);
if (zap_protocol_ != zap_disconnect) {
send_string_expect_success (control, "STOPPED", 0);
}
close_zero_linger (control);
}
void zap_handler (void *)
{
zap_handler_generic (zap_ok);
}
static void setup_handshake_socket_monitor (void *server_,
void **server_mon_,
const char *monitor_endpoint_)
{
// Monitor handshake events on the server
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
server_, monitor_endpoint_,
ZMQ_EVENT_HANDSHAKE_SUCCEEDED | ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
| ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
| ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL));
// Create socket for collecting monitor events
*server_mon_ = test_context_socket (ZMQ_PAIR);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*server_mon_, ZMQ_LINGER, &linger, sizeof (linger)));
// Connect it to the inproc endpoints so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (*server_mon_, monitor_endpoint_));
}
void setup_context_and_server_side (void **zap_control_,
void **zap_thread_,
void **server_,
void **server_mon_,
char *my_endpoint_,
zmq_thread_fn zap_handler_,
socket_config_fn socket_config_,
void *socket_config_data_,
const char *routing_id_)
{
// Spawn ZAP handler
zap_requests_handled = zmq_atomic_counter_new ();
TEST_ASSERT_NOT_NULL (zap_requests_handled);
*zap_control_ = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (*zap_control_, "inproc://handler-control"));
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*zap_control_, ZMQ_LINGER, &linger, sizeof (linger)));
if (zap_handler_ != NULL) {
*zap_thread_ = zmq_threadstart (zap_handler_, NULL);
recv_string_expect_success (*zap_control_, "GO", 0);
} else
*zap_thread_ = NULL;
// Server socket will accept connections
*server_ = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*server_, ZMQ_LINGER, &linger, sizeof (linger)));
socket_config_ (*server_, socket_config_data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
*server_, ZMQ_ROUTING_ID, routing_id_, strlen (routing_id_)));
bind_loopback_ipv4 (*server_, my_endpoint_, MAX_SOCKET_STRING);
const char server_monitor_endpoint[] = "inproc://monitor-server";
setup_handshake_socket_monitor (*server_, server_mon_,
server_monitor_endpoint);
}
void shutdown_context_and_server_side (void *zap_thread_,
void *server_,
void *server_mon_,
void *zap_control_,
bool zap_handler_stopped_)
{
if (zap_thread_ && !zap_handler_stopped_) {
send_string_expect_success (zap_control_, "STOP", 0);
recv_string_expect_success (zap_control_, "STOPPED", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_unbind (zap_control_, "inproc://handler-control"));
}
test_context_socket_close (zap_control_);
test_context_socket_close (server_mon_);
test_context_socket_close (server_);
// Wait until ZAP handler terminates
if (zap_thread_)
zmq_threadclose (zap_thread_);
zmq_atomic_counter_destroy (&zap_requests_handled);
}
void *create_and_connect_client (char *my_endpoint_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_)
{
void *client = test_context_socket (ZMQ_DEALER);
socket_config_ (client, socket_config_data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint_));
if (client_mon_) {
setup_handshake_socket_monitor (client, client_mon_,
"inproc://client-monitor");
}
return client;
}
void expect_new_client_bounce_fail (char *my_endpoint_,
void *server_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_,
int expected_client_event_,
int expected_client_value_)
{
void *my_client_mon;
TEST_ASSERT_TRUE (client_mon_ == NULL || expected_client_event_ == 0);
if (expected_client_event_ != 0)
client_mon_ = &my_client_mon;
void *client = create_and_connect_client (my_endpoint_, socket_config_,
socket_config_data_, client_mon_);
expect_bounce_fail (server_, client);
if (expected_client_event_ != 0) {
int events_received = 0;
events_received = expect_monitor_event_multiple (
my_client_mon, expected_client_event_, expected_client_value_, false);
TEST_ASSERT_EQUAL_INT (1, events_received);
test_context_socket_close (my_client_mon);
}
test_context_socket_close_zero_linger (client);
}

View File

@ -37,86 +37,27 @@
typedef void(socket_config_fn) (void *, void *);
const char *test_zap_domain = "ZAPTEST";
// NULL specific functions
void socket_config_null_client (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_);
LIBZMQ_UNUSED (server_secret_);
}
void socket_config_null_client (void *server_, void *server_secret_);
void socket_config_null_server (void *server_, void *server_secret_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
int required = server_secret_ ? *(int *) server_secret_ : 0;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
&required, sizeof (int)));
#else
LIBZMQ_UNUSED (server_secret_);
#endif
}
void socket_config_null_server (void *server_, void *server_secret_);
// PLAIN specific functions
const char *test_plain_username = "testuser";
const char *test_plain_password = "testpass";
void socket_config_plain_client (void *server_, void *server_secret_);
void socket_config_plain_client (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_secret_);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_PASSWORD, test_plain_password, 8));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_USERNAME, test_plain_username, 8));
}
void socket_config_plain_server (void *server_, void *server_secret_)
{
LIBZMQ_UNUSED (server_secret_);
int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
}
void socket_config_plain_server (void *server_, void *server_secret_);
// CURVE specific functions
// We'll generate random test keys at startup
char valid_client_public[41];
char valid_client_secret[41];
char valid_server_public[41];
char valid_server_secret[41];
extern char valid_client_public[41];
extern char valid_client_secret[41];
extern char valid_server_public[41];
extern char valid_server_secret[41];
void setup_testutil_security_curve ()
{
// Generate new keypairs for these tests
TEST_ASSERT_SUCCESS_ERRNO (
zmq_curve_keypair (valid_client_public, valid_client_secret));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_curve_keypair (valid_server_public, valid_server_secret));
}
void setup_testutil_security_curve ();
void socket_config_curve_server (void *server_, void *server_secret_)
{
int as_server = 1;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_CURVE_SERVER, &as_server, sizeof (int)));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (server_, ZMQ_CURVE_SECRETKEY, server_secret_, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
server_, ZMQ_ZAP_DOMAIN, test_zap_domain, strlen (test_zap_domain)));
#ifdef ZMQ_ZAP_ENFORCE_DOMAIN
int required = 1;
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (server_, ZMQ_ZAP_ENFORCE_DOMAIN,
&required, sizeof (int)));
#endif
}
void socket_config_curve_server (void *server_, void *server_secret_);
struct curve_client_data_t
{
@ -125,18 +66,7 @@ struct curve_client_data_t
const char *client_secret;
};
void socket_config_curve_client (void *client_, void *data_)
{
curve_client_data_t *curve_client_data =
static_cast<curve_client_data_t *> (data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_SERVERKEY, curve_client_data->server_public, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_PUBLICKEY, curve_client_data->client_public, 41));
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
client_, ZMQ_CURVE_SECRETKEY, curve_client_data->client_secret, 41));
}
void socket_config_curve_client (void *client_, void *data_);
// --------------------------------------------------------------------------
// This methods receives and validates ZAP requests (allowing or denying
@ -158,148 +88,12 @@ enum zap_protocol_t
zap_do_not_send
};
void *zap_requests_handled;
extern void *zap_requests_handled;
void zap_handler_generic (zap_protocol_t zap_protocol_,
const char *expected_routing_id_ = "IDENT")
{
void *control = zmq_socket (get_test_context (), ZMQ_REQ);
TEST_ASSERT_NOT_NULL (control);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_connect (control, "inproc://handler-control"));
const char *expected_routing_id_ = "IDENT");
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"));
// Signal main thread that we are ready
send_string_expect_success (control, "GO", 0);
zmq_pollitem_t items[] = {
{control, 0, ZMQ_POLLIN, 0},
{handler, 0, ZMQ_POLLIN, 0},
};
// if ordered not to receive the request, ignore the second poll item
const int numitems = (zap_protocol_ == zap_do_not_recv) ? 1 : 2;
// Process ZAP requests forever
while (zmq_poll (items, numitems, -1) >= 0) {
if (items[0].revents & ZMQ_POLLIN) {
recv_string_expect_success (control, "STOP", 0);
break; // Terminating - main thread signal
}
if (!(items[1].revents & ZMQ_POLLIN))
continue;
char *version = s_recv (handler);
if (!version)
break; // Terminating - peer's socket closed
if (zap_protocol_ == zap_disconnect) {
free (version);
break;
}
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);
bool authentication_succeeded = false;
if (streq (mechanism, "CURVE")) {
uint8_t client_key[32];
TEST_ASSERT_EQUAL_INT (32, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (
handler, client_key, 32, 0)));
char client_key_text[41];
zmq_z85_encode (client_key_text, client_key, 32);
authentication_succeeded =
streq (client_key_text, valid_client_public);
} else if (streq (mechanism, "PLAIN")) {
char client_username[32];
int size = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (handler, client_username, 32, 0));
client_username[size] = 0;
char client_password[32];
size = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (handler, client_password, 32, 0));
client_password[size] = 0;
authentication_succeeded =
streq (test_plain_username, client_username)
&& streq (test_plain_password, client_password);
} else if (streq (mechanism, "NULL")) {
authentication_succeeded = true;
} else {
char msg[128];
printf ("Unsupported mechanism: %s\n", mechanism);
TEST_FAIL_MESSAGE (msg);
}
TEST_ASSERT_EQUAL_STRING ("1.0", version);
TEST_ASSERT_EQUAL_STRING (expected_routing_id_, routing_id);
s_sendmore (handler, zap_protocol_ == zap_wrong_version
? "invalid_version"
: version);
s_sendmore (handler, zap_protocol_ == zap_wrong_request_id
? "invalid_request_id"
: sequence);
if (authentication_succeeded) {
const char *status_code;
switch (zap_protocol_) {
case zap_status_internal_error:
status_code = "500";
break;
case zap_status_temporary_failure:
status_code = "300";
break;
case zap_status_invalid:
status_code = "invalid_status";
break;
default:
status_code = "200";
}
s_sendmore (handler, status_code);
s_sendmore (handler, "OK");
s_sendmore (handler, "anonymous");
if (zap_protocol_ == zap_too_many_parts) {
s_sendmore (handler, "");
}
if (zap_protocol_ != zap_do_not_send)
s_send (handler, "");
} else {
s_sendmore (handler, "400");
s_sendmore (handler, "Invalid client public key");
s_sendmore (handler, "");
if (zap_protocol_ != zap_do_not_send)
s_send (handler, "");
}
free (version);
free (sequence);
free (domain);
free (address);
free (routing_id);
free (mechanism);
zmq_atomic_counter_inc (zap_requests_handled);
}
TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (handler, "inproc://zeromq.zap.01"));
close_zero_linger (handler);
if (zap_protocol_ != zap_disconnect) {
send_string_expect_success (control, "STOPPED", 0);
}
close_zero_linger (control);
}
void zap_handler (void * /*unused_*/)
{
zap_handler_generic (zap_ok);
}
void zap_handler (void * /*unused_*/);
// Security-specific monitor event utilities
@ -328,27 +122,6 @@ void zap_handler (void * /*unused_*/)
TEST_ASSERT_EQUAL_INT (0, event_count); \
}
void setup_handshake_socket_monitor (void *server_,
void **server_mon_,
const char *monitor_endpoint_)
{
// Monitor handshake events on the server
TEST_ASSERT_SUCCESS_ERRNO (zmq_socket_monitor (
server_, monitor_endpoint_,
ZMQ_EVENT_HANDSHAKE_SUCCEEDED | ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
| ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
| ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL));
// Create socket for collecting monitor events
*server_mon_ = test_context_socket (ZMQ_PAIR);
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*server_mon_, ZMQ_LINGER, &linger, sizeof (linger)));
// Connect it to the inproc endpoints so they'll get events
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (*server_mon_, monitor_endpoint_));
}
void setup_context_and_server_side (
void **zap_control_,
void **zap_thread_,
@ -358,84 +131,18 @@ void setup_context_and_server_side (
zmq_thread_fn zap_handler_ = &zap_handler,
socket_config_fn socket_config_ = &socket_config_curve_server,
void *socket_config_data_ = valid_server_secret,
const char *routing_id_ = "IDENT")
{
// Spawn ZAP handler
zap_requests_handled = zmq_atomic_counter_new ();
TEST_ASSERT_NOT_NULL (zap_requests_handled);
*zap_control_ = test_context_socket (ZMQ_REP);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_bind (*zap_control_, "inproc://handler-control"));
int linger = 0;
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*zap_control_, ZMQ_LINGER, &linger, sizeof (linger)));
if (zap_handler_ != NULL) {
*zap_thread_ = zmq_threadstart (zap_handler_, NULL);
recv_string_expect_success (*zap_control_, "GO", 0);
} else
*zap_thread_ = NULL;
// Server socket will accept connections
*server_ = test_context_socket (ZMQ_DEALER);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (*server_, ZMQ_LINGER, &linger, sizeof (linger)));
socket_config_ (*server_, socket_config_data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
*server_, ZMQ_ROUTING_ID, routing_id_, strlen (routing_id_)));
bind_loopback_ipv4 (*server_, my_endpoint_, MAX_SOCKET_STRING);
const char server_monitor_endpoint[] = "inproc://monitor-server";
setup_handshake_socket_monitor (*server_, server_mon_,
server_monitor_endpoint);
}
const char *routing_id_ = "IDENT");
void shutdown_context_and_server_side (void *zap_thread_,
void *server_,
void *server_mon_,
void *zap_control_,
bool zap_handler_stopped_ = false)
{
if (zap_thread_ && !zap_handler_stopped_) {
send_string_expect_success (zap_control_, "STOP", 0);
recv_string_expect_success (zap_control_, "STOPPED", 0);
TEST_ASSERT_SUCCESS_ERRNO (
zmq_unbind (zap_control_, "inproc://handler-control"));
}
test_context_socket_close (zap_control_);
test_context_socket_close (server_mon_);
test_context_socket_close (server_);
// Wait until ZAP handler terminates
if (zap_thread_)
zmq_threadclose (zap_thread_);
zmq_atomic_counter_destroy (&zap_requests_handled);
}
bool zap_handler_stopped_ = false);
void *create_and_connect_client (char *my_endpoint_,
socket_config_fn socket_config_,
void *socket_config_data_,
void **client_mon_ = NULL)
{
void *client = test_context_socket (ZMQ_DEALER);
socket_config_ (client, socket_config_data_);
TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint_));
if (client_mon_) {
setup_handshake_socket_monitor (client, client_mon_,
"inproc://client-monitor");
}
return client;
}
void **client_mon_ = NULL);
void expect_new_client_bounce_fail (char *my_endpoint_,
void *server_,
@ -443,27 +150,6 @@ void expect_new_client_bounce_fail (char *my_endpoint_,
void *socket_config_data_,
void **client_mon_ = NULL,
int expected_client_event_ = 0,
int expected_client_value_ = 0)
{
void *my_client_mon;
TEST_ASSERT_TRUE (client_mon_ == NULL || expected_client_event_ == 0);
if (expected_client_event_ != 0)
client_mon_ = &my_client_mon;
void *client = create_and_connect_client (my_endpoint_, socket_config_,
socket_config_data_, client_mon_);
expect_bounce_fail (server_, client);
if (expected_client_event_ != 0) {
int events_received = 0;
events_received = expect_monitor_event_multiple (
my_client_mon, expected_client_event_, expected_client_value_, false);
TEST_ASSERT_EQUAL_INT (1, events_received);
test_context_socket_close (my_client_mon);
}
test_context_socket_close_zero_linger (client);
}
int expected_client_value_ = 0);
#endif

309
tests/testutil_unity.cpp Normal file
View File

@ -0,0 +1,309 @@
/*
Copyright (c) 2007-2019 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_unity.hpp"
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#endif
int test_assert_success_message_errno_helper (int rc_,
const char *msg_,
const char *expr_)
{
if (rc_ == -1) {
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
snprintf (buffer, sizeof (buffer) - 1,
"%s failed%s%s%s, errno = %i (%s)", expr_,
msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", zmq_errno (), zmq_strerror (zmq_errno ()));
TEST_FAIL_MESSAGE (buffer);
}
return rc_;
}
int test_assert_success_message_raw_errno_helper (int rc_,
const char *msg_,
const char *expr_)
{
if (rc_ == -1) {
#if defined ZMQ_HAVE_WINDOWS
int current_errno = WSAGetLastError ();
#else
int current_errno = errno;
#endif
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
snprintf (buffer, sizeof (buffer) - 1, "%s failed%s%s%s, errno = %i",
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", current_errno);
TEST_FAIL_MESSAGE (buffer);
}
return rc_;
}
int test_assert_failure_message_raw_errno_helper (int rc_,
int expected_errno_,
const char *msg_,
const char *expr_)
{
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
if (rc_ != -1) {
snprintf (buffer, sizeof (buffer) - 1,
"%s was unexpectedly successful%s%s%s, expected "
"errno = %i, actual return value = %i",
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", expected_errno_, rc_);
TEST_FAIL_MESSAGE (buffer);
} else {
#if defined ZMQ_HAVE_WINDOWS
int current_errno = WSAGetLastError ();
#else
int current_errno = errno;
#endif
if (current_errno != expected_errno_) {
snprintf (buffer, sizeof (buffer) - 1,
"%s failed with an unexpected error%s%s%s, expected "
"errno = %i, actual errno = %i",
expr_, msg_ ? " (additional info: " : "",
msg_ ? msg_ : "", msg_ ? ")" : "", expected_errno_,
current_errno);
TEST_FAIL_MESSAGE (buffer);
}
}
return rc_;
}
void send_string_expect_success (void *socket_, const char *str_, int flags_)
{
const size_t len = str_ ? strlen (str_) : 0;
const int rc = zmq_send (socket_, str_, len, flags_);
TEST_ASSERT_EQUAL_INT ((int) len, rc);
}
void recv_string_expect_success (void *socket_, const char *str_, int flags_)
{
const size_t len = str_ ? strlen (str_) : 0;
char buffer[255];
TEST_ASSERT_LESS_OR_EQUAL_MESSAGE (sizeof (buffer), len,
"recv_string_expect_success cannot be "
"used for strings longer than 255 "
"characters");
const int rc = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (socket_, buffer, sizeof (buffer), flags_));
TEST_ASSERT_EQUAL_INT ((int) len, rc);
if (str_)
TEST_ASSERT_EQUAL_STRING_LEN (str_, buffer, len);
}
static void *internal_manage_test_context (bool init_, bool clear_)
{
static void *test_context = NULL;
if (clear_) {
TEST_ASSERT_NOT_NULL (test_context);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (test_context));
test_context = NULL;
} else {
if (init_) {
TEST_ASSERT_NULL (test_context);
test_context = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (test_context);
}
}
return test_context;
}
static void internal_manage_test_sockets (void *socket_, bool add_)
{
static void *test_sockets[MAX_TEST_SOCKETS];
static size_t test_socket_count = 0;
if (!socket_) {
TEST_ASSERT_FALSE (add_);
// force-close all sockets
if (test_socket_count) {
for (size_t i = 0; i < test_socket_count; ++i) {
close_zero_linger (test_sockets[i]);
}
fprintf (stderr,
"WARNING: Forced closure of %i sockets, this is an "
"implementation error unless the test case failed\n",
(int) test_socket_count);
test_socket_count = 0;
}
} else {
if (add_) {
++test_socket_count;
TEST_ASSERT_LESS_THAN_MESSAGE (MAX_TEST_SOCKETS, test_socket_count,
"MAX_TEST_SOCKETS must be "
"increased, or you cannot use the "
"test context");
test_sockets[test_socket_count - 1] = socket_;
} else {
bool found = false;
for (size_t i = 0; i < test_socket_count; ++i) {
if (test_sockets[i] == socket_) {
found = true;
}
if (found) {
if (i < test_socket_count)
test_sockets[i] = test_sockets[i + 1];
}
}
TEST_ASSERT_TRUE_MESSAGE (found,
"Attempted to close a socket that was "
"not created by test_context_socket");
--test_socket_count;
}
}
}
void setup_test_context ()
{
internal_manage_test_context (true, false);
}
void *get_test_context ()
{
return internal_manage_test_context (false, false);
}
void teardown_test_context ()
{
// this condition allows an explicit call to teardown_test_context from a
// test. if this is never used, it should probably be removed, to detect
// misuses
if (get_test_context ()) {
internal_manage_test_sockets (NULL, false);
internal_manage_test_context (false, true);
}
}
void *test_context_socket (int type_)
{
void *const socket = zmq_socket (get_test_context (), type_);
TEST_ASSERT_NOT_NULL (socket);
internal_manage_test_sockets (socket, true);
return socket;
}
void *test_context_socket_close (void *socket_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket_));
internal_manage_test_sockets (socket_, false);
return socket_;
}
void *test_context_socket_close_zero_linger (void *socket_)
{
const int linger = 0;
int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
TEST_ASSERT_TRUE (rc == 0 || zmq_errno () == ETERM);
return test_context_socket_close (socket_);
}
void test_bind (void *socket_,
const char *bind_address_,
char *my_endpoint_,
size_t len_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (socket_, bind_address_));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_LAST_ENDPOINT, my_endpoint_, &len_));
}
void bind_loopback (void *socket_, int ipv6_, char *my_endpoint_, size_t len_)
{
if (ipv6_ && !is_ipv6_available ()) {
TEST_IGNORE_MESSAGE ("ipv6 is not available");
}
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket_, ZMQ_IPV6, &ipv6_, sizeof (int)));
test_bind (socket_, ipv6_ ? "tcp://[::1]:*" : "tcp://127.0.0.1:*",
my_endpoint_, len_);
}
void bind_loopback_ipv4 (void *socket_, char *my_endpoint_, size_t len_)
{
bind_loopback (socket_, false, my_endpoint_, len_);
}
void bind_loopback_ipv6 (void *socket_, char *my_endpoint_, size_t len_)
{
bind_loopback (socket_, true, my_endpoint_, len_);
}
void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_)
{
if (!zmq_has ("ipc")) {
TEST_IGNORE_MESSAGE ("ipc is not available");
}
test_bind (socket_, "ipc://*", my_endpoint_, len_);
}
void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_)
{
if (!is_tipc_available ()) {
TEST_IGNORE_MESSAGE ("tipc is not available");
}
test_bind (socket_, "tipc://<*>", my_endpoint_, len_);
}
#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU)
void make_random_ipc_endpoint (char *out_endpoint_)
{
char random_file[16];
strcpy (random_file, "tmpXXXXXX");
#ifdef HAVE_MKDTEMP
TEST_ASSERT_TRUE (mkdtemp (random_file));
strcat (random_file, "/ipc");
#else
int fd = mkstemp (random_file);
TEST_ASSERT_TRUE (fd != -1);
close (fd);
#endif
strcpy (out_endpoint_, "ipc://");
strcat (out_endpoint_, random_file);
}
#endif

View File

@ -35,98 +35,77 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <unity.h>
#include <string.h>
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER <= 1800
#define snprintf _snprintf
#endif
// Internal helper functions that are not intended to be directly called from
// tests. They must be declared in the header since they are used by macros.
int test_assert_success_message_errno_helper (int rc_,
const char *msg_,
const char *expr_)
{
if (rc_ == -1) {
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
snprintf (buffer, sizeof (buffer) - 1,
"%s failed%s%s%s, errno = %i (%s)", expr_,
msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", zmq_errno (), zmq_strerror (zmq_errno ()));
TEST_FAIL_MESSAGE (buffer);
}
return rc_;
}
const char *expr_);
int test_assert_success_message_raw_errno_helper (int rc_,
const char *msg_,
const char *expr_)
{
if (rc_ == -1) {
#if defined ZMQ_HAVE_WINDOWS
int current_errno = WSAGetLastError ();
#else
int current_errno = errno;
#endif
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
snprintf (buffer, sizeof (buffer) - 1, "%s failed%s%s%s, errno = %i",
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", current_errno);
TEST_FAIL_MESSAGE (buffer);
}
return rc_;
}
const char *expr_);
int test_assert_failure_message_raw_errno_helper (int rc_,
int expected_errno_,
const char *msg_,
const char *expr_)
{
char buffer[512];
buffer[sizeof (buffer) - 1] =
0; // to ensure defined behavior with VC++ <= 2013
if (rc_ != -1) {
snprintf (buffer, sizeof (buffer) - 1,
"%s was unexpectedly successful%s%s%s, expected "
"errno = %i, actual return value = %i",
expr_, msg_ ? " (additional info: " : "", msg_ ? msg_ : "",
msg_ ? ")" : "", expected_errno_, rc_);
TEST_FAIL_MESSAGE (buffer);
} else {
#if defined ZMQ_HAVE_WINDOWS
int current_errno = WSAGetLastError ();
#else
int current_errno = errno;
#endif
if (current_errno != expected_errno_) {
snprintf (buffer, sizeof (buffer) - 1,
"%s failed with an unexpected error%s%s%s, expected "
"errno = %i, actual errno = %i",
expr_, msg_ ? " (additional info: " : "",
msg_ ? msg_ : "", msg_ ? ")" : "", expected_errno_,
current_errno);
TEST_FAIL_MESSAGE (buffer);
}
}
return rc_;
}
const char *expr_);
/////////////////////////////////////////////////////////////////////////////
// Macros extending Unity's TEST_ASSERT_* macros in a similar fashion.
/////////////////////////////////////////////////////////////////////////////
// For TEST_ASSERT_SUCCESS_ERRNO, TEST_ASSERT_SUCCESS_MESSAGE_ERRNO and
// TEST_ASSERT_FAILURE_ERRNO, 'expr' must be an expression evaluating
// to a result in the style of a libzmq API function, i.e. an integer which
// is non-negative in case of success, and -1 in case of a failure, and sets
// the value returned by zmq_errno () to the error code.
// TEST_ASSERT_SUCCESS_RAW_ERRNO and TEST_ASSERT_FAILURE_RAW_ERRNO are similar,
// but used with the native socket API functions, and expect that the error
// code can be retrieved in the native way (i.e. WSAGetLastError on Windows,
// and errno otherwise).
// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr', the error number as
// determined by zmq_errno(), and the additional 'msg'.
// In case of success, the result of the macro is the result of 'expr'.
#define TEST_ASSERT_SUCCESS_MESSAGE_ERRNO(expr, msg) \
test_assert_success_message_errno_helper (expr, msg, #expr)
// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr' and the error code.
// A typical use would be:
// TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (socket, endpoint));
// In case of success, the result of the macro is the result of 'expr'.
//
// If an additional message should be displayed in case of a failure, use
// TEST_ASSERT_SUCCESS_MESSAGE_ERRNO.
#define TEST_ASSERT_SUCCESS_ERRNO(expr) \
test_assert_success_message_errno_helper (expr, NULL, #expr)
// Asserts that the socket API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr' and the error code.
// A typical use would be:
// TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0));
// In case of success, the result of the macro is the result of 'expr'.
#define TEST_ASSERT_SUCCESS_RAW_ERRNO(expr) \
test_assert_success_message_raw_errno_helper (expr, NULL, #expr)
// Asserts that the socket API 'expr' is not successful, and the error code is
// 'error_code'. In case of an unexpected succces, or a failure with an
// unexpected error code, the assertion message includes the literal 'expr'
// and, in case of a failure, the actual error code.
#define TEST_ASSERT_FAILURE_RAW_ERRNO(error_code, expr) \
test_assert_failure_message_raw_errno_helper (expr, error_code, NULL, #expr)
// Asserts that the libzmq API 'expr' is not successful, and the error code is
// 'error_code'. In case of an unexpected succces, or a failure with an
// unexpected error code, the assertion message includes the literal 'expr'
// and, in case of a failure, the actual error code.
#define TEST_ASSERT_FAILURE_ERRNO(error_code, expr) \
{ \
int _rc = (expr); \
@ -134,29 +113,35 @@ int test_assert_failure_message_raw_errno_helper (int rc_,
TEST_ASSERT_EQUAL_INT (error_code, errno); \
}
void send_string_expect_success (void *socket_, const char *str_, int flags_)
{
const size_t len = str_ ? strlen (str_) : 0;
const int rc = zmq_send (socket_, str_, len, flags_);
TEST_ASSERT_EQUAL_INT ((int) len, rc);
}
/////////////////////////////////////////////////////////////////////////////
// Utility functions for testing sending and receiving.
/////////////////////////////////////////////////////////////////////////////
void recv_string_expect_success (void *socket_, const char *str_, int flags_)
{
const size_t len = str_ ? strlen (str_) : 0;
char buffer[255];
TEST_ASSERT_LESS_OR_EQUAL_MESSAGE (sizeof (buffer), len,
"recv_string_expect_success cannot be "
"used for strings longer than 255 "
"characters");
// Sends a string via a libzmq socket, and expects the operation to be
// successful (the meaning of which depends on the socket type and configured
// options, and might include dropping the message). Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for sending.
// 'str_' must be a 0-terminated string.
// 'flags_' are as documented by the zmq_send function.
void send_string_expect_success (void *socket_, const char *str_, int flags_);
const int rc = TEST_ASSERT_SUCCESS_ERRNO (
zmq_recv (socket_, buffer, sizeof (buffer), flags_));
TEST_ASSERT_EQUAL_INT ((int) len, rc);
if (str_)
TEST_ASSERT_EQUAL_STRING_LEN (str_, buffer, len);
}
// Receives a message via a libzmq socket, and expects the operation to be
// successful, and the message to be a given string. Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for receiving.
// 'str_' must be a 0-terminated string.
// 'flags_' are as documented by the zmq_recv function.
void recv_string_expect_success (void *socket_, const char *str_, int flags_);
// Sends a byte array via a libzmq socket, and expects the operation to be
// successful (the meaning of which depends on the socket type and configured
// options, and might include dropping the message). Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for sending.
// 'array_' must be a C uint8_t array. The array size is automatically
// determined via template argument deduction.
// 'flags_' are as documented by the zmq_send function.
template <size_t SIZE>
void send_array_expect_success (void *socket_,
const uint8_t (&array_)[SIZE],
@ -166,6 +151,13 @@ void send_array_expect_success (void *socket_,
TEST_ASSERT_EQUAL_INT (static_cast<int> (SIZE), rc);
}
// Receives a message via a libzmq socket, and expects the operation to be
// successful, and the message to be a given byte array. Otherwise, a Unity
// test assertion is triggered.
// 'socket_' must be the libzmq socket to use for receiving.
// 'array_' must be a C uint8_t array. The array size is automatically
// determined via template argument deduction.
// 'flags_' are as documented by the zmq_recv function.
template <size_t SIZE>
void recv_array_expect_success (void *socket_,
const uint8_t (&array_)[SIZE],
@ -183,188 +175,87 @@ void recv_array_expect_success (void *socket_,
TEST_ASSERT_EQUAL_UINT8_ARRAY (array_, buffer, SIZE);
}
// do not call from tests directly, use setup_test_context, get_test_context and teardown_test_context only
void *internal_manage_test_context (bool init_, bool clear_)
{
static void *test_context = NULL;
if (clear_) {
TEST_ASSERT_NOT_NULL (test_context);
TEST_ASSERT_SUCCESS_ERRNO (zmq_ctx_term (test_context));
test_context = NULL;
} else {
if (init_) {
TEST_ASSERT_NULL (test_context);
test_context = zmq_ctx_new ();
TEST_ASSERT_NOT_NULL (test_context);
}
}
return test_context;
}
/////////////////////////////////////////////////////////////////////////////
// Utility function for handling a test libzmq context, that is set up and
// torn down for each Unity test case, such that a clean context is available
// for each test case, and some consistency checks can be performed.
/////////////////////////////////////////////////////////////////////////////
// The maximum number of sockets that can be managed by the test context.
#define MAX_TEST_SOCKETS 128
void internal_manage_test_sockets (void *socket_, bool add_)
{
static void *test_sockets[MAX_TEST_SOCKETS];
static size_t test_socket_count = 0;
if (!socket_) {
assert (!add_);
// Expected to be called during Unity's setUp function.
void setup_test_context ();
// force-close all sockets
if (test_socket_count) {
for (size_t i = 0; i < test_socket_count; ++i) {
close_zero_linger (test_sockets[i]);
}
fprintf (stderr,
"WARNING: Forced closure of %i sockets, this is an "
"implementation error unless the test case failed\n",
(int) test_socket_count);
test_socket_count = 0;
}
} else {
if (add_) {
++test_socket_count;
TEST_ASSERT_LESS_THAN_MESSAGE (MAX_TEST_SOCKETS, test_socket_count,
"MAX_TEST_SOCKETS must be "
"increased, or you cannot use the "
"test context");
test_sockets[test_socket_count - 1] = socket_;
} else {
bool found = false;
for (size_t i = 0; i < test_socket_count; ++i) {
if (test_sockets[i] == socket_) {
found = true;
}
if (found) {
if (i < test_socket_count)
test_sockets[i] = test_sockets[i + 1];
}
}
TEST_ASSERT_TRUE_MESSAGE (found,
"Attempted to close a socket that was "
"not created by test_context_socket");
--test_socket_count;
}
}
}
// Returns the test context, e.g. to create sockets in another thread using
// zmq_socket, or set context options.
void *get_test_context ();
void setup_test_context ()
{
internal_manage_test_context (true, false);
}
// Expected to be called during Unity's tearDown function. Checks that all
// sockets created via test_context_socket have been properly closed using
// test_context_socket_close or test_context_socket_close_zero_linger, and generates a warning otherwise.
void teardown_test_context ();
void *get_test_context ()
{
return internal_manage_test_context (false, false);
}
// Creates a libzmq socket on the test context, and tracks its lifecycle.
// You MUST use test_context_socket_close or test_context_socket_close_zero_linger
// to close a socket created via this function, otherwise undefined behaviour
// will result.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
void *test_context_socket (int type_);
void teardown_test_context ()
{
// this condition allows an explicit call to teardown_test_context from a
// test. if this is never used, it should probably be removed, to detect
// misuses
if (get_test_context ()) {
internal_manage_test_sockets (NULL, false);
internal_manage_test_context (false, true);
}
}
// Closes a socket created via test_context_socket.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
void *test_context_socket_close (void *socket_);
void *test_context_socket (int type_)
{
void *const socket = zmq_socket (get_test_context (), type_);
TEST_ASSERT_NOT_NULL (socket);
internal_manage_test_sockets (socket, true);
return socket;
}
// Closes a socket created via test_context_socket after setting its linger
// timeout to 0.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
void *test_context_socket_close_zero_linger (void *socket_);
void *test_context_socket_close (void *socket_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket_));
internal_manage_test_sockets (socket_, false);
return socket_;
}
/////////////////////////////////////////////////////////////////////////////
// Utility function for handling wildcard binds.
/////////////////////////////////////////////////////////////////////////////
void *test_context_socket_close_zero_linger (void *socket_)
{
const int linger = 0;
int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
TEST_ASSERT_TRUE (rc == 0 || zmq_errno () == ETERM);
return test_context_socket_close (socket_);
}
// All function binds a socket to some wildcard address, and retrieve the bound
// endpoint via the ZMQ_LAST_ENDPOINT socket option to a given buffer.
// Triggers a Unity test assertion in case of a failure (including the buffer
// being too small for the resulting endpoint string).
// Binds to an explicitly given (wildcard) address.
// TODO redesign such that this function is not necessary to be exposed, but
// the protocol to use is rather specified via an enum value
void test_bind (void *socket_,
const char *bind_address_,
char *my_endpoint_,
size_t len_)
{
TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (socket_, bind_address_));
TEST_ASSERT_SUCCESS_ERRNO (
zmq_getsockopt (socket_, ZMQ_LAST_ENDPOINT, my_endpoint_, &len_));
}
size_t len_);
void bind_loopback (void *socket_, int ipv6_, char *my_endpoint_, size_t len_)
{
if (ipv6_ && !is_ipv6_available ()) {
TEST_IGNORE_MESSAGE ("ipv6 is not available");
}
TEST_ASSERT_SUCCESS_ERRNO (
zmq_setsockopt (socket_, ZMQ_IPV6, &ipv6_, sizeof (int)));
test_bind (socket_, ipv6_ ? "tcp://[::1]:*" : "tcp://127.0.0.1:*",
my_endpoint_, len_);
}
// Binds to a tcp endpoint using the ipv4 or ipv6 loopback wildcard address.
void bind_loopback (void *socket_, int ipv6_, char *my_endpoint_, size_t len_);
typedef void (*bind_function_t) (void *socket_,
char *my_endpoint_,
size_t len_);
void bind_loopback_ipv4 (void *socket_, char *my_endpoint_, size_t len_)
{
bind_loopback (socket_, false, my_endpoint_, len_);
}
// Binds to a tcp endpoint using the ipv4 loopback wildcard address.
void bind_loopback_ipv4 (void *socket_, char *my_endpoint_, size_t len_);
void bind_loopback_ipv6 (void *socket_, char *my_endpoint_, size_t len_)
{
bind_loopback (socket_, true, my_endpoint_, len_);
}
// Binds to a tcp endpoint using the ipv6 loopback wildcard address.
void bind_loopback_ipv6 (void *socket_, char *my_endpoint_, size_t len_);
void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_)
{
if (!zmq_has ("ipc")) {
TEST_IGNORE_MESSAGE ("ipc is not available");
}
// Binds to an ipc endpoint using the ipc wildcard address.
// Note that the returned address cannot be reused to bind a second socket.
// If you need to do this, use make_random_ipc_endpoint instead.
void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_);
test_bind (socket_, "ipc://*", my_endpoint_, len_);
}
void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_)
{
if (!is_tipc_available ()) {
TEST_IGNORE_MESSAGE ("tipc is not available");
}
test_bind (socket_, "tipc://<*>", my_endpoint_, len_);
}
// Binds to an ipc endpoint using the tipc wildcard address.
void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_);
#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU)
// utility function to create a random IPC endpoint, similar to what a ipc://*
// wildcard binding does, but in a way it can be reused for multiple binds
void make_random_ipc_endpoint (char *out_endpoint_)
{
char random_file[16];
strcpy (random_file, "tmpXXXXXX");
#ifdef HAVE_MKDTEMP
TEST_ASSERT_TRUE (mkdtemp (random_file));
strcat (random_file, "/ipc");
#else
int fd = mkstemp (random_file);
TEST_ASSERT_TRUE (fd != -1);
close (fd);
#endif
strcpy (out_endpoint_, "ipc://");
strcat (out_endpoint_, random_file);
}
// TODO also add a len parameter here
void make_random_ipc_endpoint (char *out_endpoint_);
#endif

View File

@ -35,7 +35,7 @@ foreach(test ${unittests})
link_directories(${test} PRIVATE "${ZeroMQ_SOURCE_DIR}/../lib")
endif()
target_link_libraries(${test} libzmq-static ${OPTIONAL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} unity)
target_link_libraries(${test} testutil-static)
if(RT_LIBRARY)
target_link_libraries(${test} ${RT_LIBRARY})

View File

@ -25,6 +25,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <ip_resolver.hpp>
#include <ip.hpp>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
void setUp ()
{
}
@ -62,7 +68,7 @@ class test_ip_resolver_t : public zmq::ip_resolver_t
unsigned lut_len = sizeof (dns_lut) / sizeof (dns_lut[0]);
struct addrinfo ai;
assert (service_ == NULL);
TEST_ASSERT_NULL (service_);
bool ipv6 = (hints_->ai_family == AF_INET6);
bool no_dns = (hints_->ai_flags & AI_NUMERICHOST) != 0;
@ -805,9 +811,7 @@ static void test_addr (int family_, const char *addr_, bool multicast_)
test_ip_resolver_t resolver (resolver_opts);
zmq::ip_addr_t addr;
int rc = resolver.resolve (&addr, addr_);
assert (rc == 0);
TEST_ASSERT_SUCCESS_ERRNO (resolver.resolve (&addr, addr_));
TEST_ASSERT_EQUAL (family_, addr.family ());
TEST_ASSERT_EQUAL (multicast_, addr.is_multicast ());

View File

@ -21,28 +21,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define __UNITTEST_RESOLVER_COMMON_INCLUDED__
#include <ip_resolver.hpp>
#include <string.h>
// Attempt a resolution and test the results.
//
// On windows we can receive an IPv4 address even when an IPv6 is requested, if
// we're in this situation then we compare to 'expected_addr_v4_failover_'
// instead.
void validate_address(int family, const zmq::ip_addr_t *addr_,
const char *expected_addr_,
uint16_t expected_port_ = 0,
uint16_t expected_zone_ = 0,
const char *expected_addr_v4_failover_ = NULL)
void validate_address (int family,
const zmq::ip_addr_t *addr_,
const char *expected_addr_,
uint16_t expected_port_ = 0,
uint16_t expected_zone_ = 0,
const char *expected_addr_v4_failover_ = NULL)
{
#if defined ZMQ_HAVE_WINDOWS
if (family == AF_INET6 && expected_addr_v4_failover_ != NULL &&
addr_->family () == AF_INET) {
#if defined ZMQ_HAVE_WINDOWS
if (family == AF_INET6 && expected_addr_v4_failover_ != NULL
&& addr_->family () == AF_INET) {
// We've requested an IPv6 but the system gave us an IPv4, use the
// failover address
family = AF_INET;
expected_addr_ = expected_addr_v4_failover_;
}
#else
(void)expected_addr_v4_failover_;
(void) expected_addr_v4_failover_;
#endif
TEST_ASSERT_EQUAL (family, addr_->family ());
@ -51,7 +53,8 @@ void validate_address(int family, const zmq::ip_addr_t *addr_,
struct in6_addr expected_addr;
const sockaddr_in6 *ip6_addr = &addr_->ipv6;
assert (test_inet_pton (AF_INET6, expected_addr_, &expected_addr) == 1);
TEST_ASSERT_EQUAL (
1, test_inet_pton (AF_INET6, expected_addr_, &expected_addr));
int neq = memcmp (&ip6_addr->sin6_addr, &expected_addr,
sizeof (expected_addr_));
@ -63,7 +66,8 @@ void validate_address(int family, const zmq::ip_addr_t *addr_,
struct in_addr expected_addr;
const sockaddr_in *ip4_addr = &addr_->ipv4;
assert (test_inet_pton (AF_INET, expected_addr_, &expected_addr) == 1);
TEST_ASSERT_EQUAL (
1, test_inet_pton (AF_INET, expected_addr_, &expected_addr));
TEST_ASSERT_EQUAL (expected_addr.s_addr, ip4_addr->sin_addr.s_addr);
TEST_ASSERT_EQUAL (htons (expected_port_), ip4_addr->sin_port);