From 597cc5edd624525563e6549dc0057eca2a51c81d Mon Sep 17 00:00:00 2001 From: Micah Anderson Date: Tue, 11 Nov 2014 13:30:46 -0500 Subject: upgrade to new version --- tests/Makefile.am | 103 ++++ tests/Makefile.in | 1096 ++++++++++++++++++++++++++++++++++++++ tests/test_abstract_ipc.cpp | 57 ++ tests/test_conflate.cpp | 72 +++ tests/test_connect_resolve.cpp | 53 ++ tests/test_ctx_destroy.cpp | 90 ++++ tests/test_ctx_options.cpp | 52 ++ tests/test_disconnect_inproc.cpp | 125 +++++ tests/test_fork.cpp | 81 +++ tests/test_hwm.cpp | 299 +++++++++++ tests/test_immediate.cpp | 228 ++++++++ tests/test_inproc_connect.cpp | 428 +++++++++++++++ tests/test_invalid_rep.cpp | 88 +++ tests/test_iov.cpp | 106 ++++ tests/test_issue_566.cpp | 85 +++ tests/test_last_endpoint.cpp | 56 ++ tests/test_many_sockets.cpp | 90 ++++ tests/test_monitor.cpp | 272 ++++++++++ tests/test_msg_flags.cpp | 79 +++ tests/test_pair_inproc.cpp | 71 +++ tests/test_pair_ipc.cpp | 50 ++ tests/test_pair_tcp.cpp | 50 ++ tests/test_probe_router.cpp | 72 +++ tests/test_req_correlate.cpp | 177 ++++++ tests/test_req_relaxed.cpp | 116 ++++ tests/test_reqrep_device.cpp | 135 +++++ tests/test_reqrep_inproc.cpp | 50 ++ tests/test_reqrep_ipc.cpp | 50 ++ tests/test_reqrep_tcp.cpp | 50 ++ tests/test_router_mandatory.cpp | 81 +++ tests/test_router_raw_empty.cpp | 65 +++ tests/test_security_curve.cpp | 231 ++++++++ tests/test_security_null.cpp | 148 +++++ tests/test_security_plain.cpp | 150 ++++++ tests/test_shutdown_stress.cpp | 80 +++ tests/test_spec_dealer.cpp | 254 +++++++++ tests/test_spec_pushpull.cpp | 293 ++++++++++ tests/test_spec_rep.cpp | 155 ++++++ tests/test_spec_req.cpp | 253 +++++++++ tests/test_spec_router.cpp | 204 +++++++ tests/test_stream.cpp | 227 ++++++++ tests/test_sub_forward.cpp | 91 ++++ tests/test_system.cpp | 82 +++ tests/test_term_endpoint.cpp | 104 ++++ tests/test_timeo.cpp | 75 +++ tests/testutil.hpp | 294 ++++++++++ 46 files changed, 7068 insertions(+) create mode 100644 tests/Makefile.am create mode 100644 tests/Makefile.in create mode 100644 tests/test_abstract_ipc.cpp create mode 100644 tests/test_conflate.cpp create mode 100644 tests/test_connect_resolve.cpp create mode 100644 tests/test_ctx_destroy.cpp create mode 100644 tests/test_ctx_options.cpp create mode 100644 tests/test_disconnect_inproc.cpp create mode 100644 tests/test_fork.cpp create mode 100644 tests/test_hwm.cpp create mode 100644 tests/test_immediate.cpp create mode 100644 tests/test_inproc_connect.cpp create mode 100644 tests/test_invalid_rep.cpp create mode 100644 tests/test_iov.cpp create mode 100644 tests/test_issue_566.cpp create mode 100644 tests/test_last_endpoint.cpp create mode 100644 tests/test_many_sockets.cpp create mode 100644 tests/test_monitor.cpp create mode 100644 tests/test_msg_flags.cpp create mode 100644 tests/test_pair_inproc.cpp create mode 100644 tests/test_pair_ipc.cpp create mode 100644 tests/test_pair_tcp.cpp create mode 100644 tests/test_probe_router.cpp create mode 100644 tests/test_req_correlate.cpp create mode 100644 tests/test_req_relaxed.cpp create mode 100644 tests/test_reqrep_device.cpp create mode 100644 tests/test_reqrep_inproc.cpp create mode 100644 tests/test_reqrep_ipc.cpp create mode 100644 tests/test_reqrep_tcp.cpp create mode 100644 tests/test_router_mandatory.cpp create mode 100644 tests/test_router_raw_empty.cpp create mode 100644 tests/test_security_curve.cpp create mode 100644 tests/test_security_null.cpp create mode 100644 tests/test_security_plain.cpp create mode 100644 tests/test_shutdown_stress.cpp create mode 100644 tests/test_spec_dealer.cpp create mode 100644 tests/test_spec_pushpull.cpp create mode 100644 tests/test_spec_rep.cpp create mode 100644 tests/test_spec_req.cpp create mode 100644 tests/test_spec_router.cpp create mode 100644 tests/test_stream.cpp create mode 100644 tests/test_sub_forward.cpp create mode 100644 tests/test_system.cpp create mode 100644 tests/test_term_endpoint.cpp create mode 100644 tests/test_timeo.cpp create mode 100644 tests/testutil.hpp (limited to 'tests') diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..a1491d7 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,103 @@ +INCLUDES = -I$(top_builddir)/include \ + -I$(top_srcdir)/include + +LDADD = $(top_builddir)/src/libzmq.la + +noinst_PROGRAMS = test_system \ + test_pair_inproc \ + test_pair_tcp \ + test_reqrep_inproc \ + test_reqrep_tcp \ + test_hwm \ + test_reqrep_device \ + test_sub_forward \ + test_invalid_rep \ + test_msg_flags \ + test_connect_resolve \ + test_immediate \ + test_last_endpoint \ + test_term_endpoint \ + test_monitor \ + test_router_mandatory \ + test_router_raw_empty \ + test_probe_router \ + test_stream \ + test_disconnect_inproc \ + test_ctx_options \ + test_ctx_destroy \ + test_security_null \ + test_security_plain \ + test_iov \ + test_spec_req \ + test_spec_rep \ + test_spec_dealer \ + test_spec_router \ + test_spec_pushpull \ + test_req_correlate \ + test_req_relaxed \ + test_conflate \ + test_inproc_connect \ + test_issue_566 \ + test_abstract_ipc \ + test_many_sockets + +if !ON_MINGW +noinst_PROGRAMS += test_shutdown_stress \ + test_pair_ipc \ + test_reqrep_ipc \ + test_timeo \ + test_fork +endif + +test_system_SOURCES = test_system.cpp +test_pair_inproc_SOURCES = test_pair_inproc.cpp testutil.hpp +test_pair_tcp_SOURCES = test_pair_tcp.cpp testutil.hpp +test_reqrep_inproc_SOURCES = test_reqrep_inproc.cpp testutil.hpp +test_reqrep_tcp_SOURCES = test_reqrep_tcp.cpp testutil.hpp +test_hwm_SOURCES = test_hwm.cpp +test_reqrep_device_SOURCES = test_reqrep_device.cpp +test_sub_forward_SOURCES = test_sub_forward.cpp +test_invalid_rep_SOURCES = test_invalid_rep.cpp +test_msg_flags_SOURCES = test_msg_flags.cpp +test_connect_resolve_SOURCES = test_connect_resolve.cpp +test_immediate_SOURCES = test_immediate.cpp +test_last_endpoint_SOURCES = test_last_endpoint.cpp +test_term_endpoint_SOURCES = test_term_endpoint.cpp +test_monitor_SOURCES = test_monitor.cpp +test_router_mandatory_SOURCES = test_router_mandatory.cpp +test_router_raw_empty_SOURCES = test_router_raw_empty.cpp +test_probe_router_SOURCES = test_probe_router.cpp +test_stream_SOURCES = test_stream.cpp +test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp +test_ctx_options_SOURCES = test_ctx_options.cpp +test_iov_SOURCES = test_iov.cpp +test_ctx_destroy_SOURCES = test_ctx_destroy.cpp +test_security_null_SOURCES = test_security_null.cpp +test_security_plain_SOURCES = test_security_plain.cpp +test_security_curve_SOURCES = test_security_curve.cpp +test_spec_req_SOURCES = test_spec_req.cpp +test_spec_rep_SOURCES = test_spec_rep.cpp +test_spec_dealer_SOURCES = test_spec_dealer.cpp +test_spec_router_SOURCES = test_spec_router.cpp +test_spec_pushpull_SOURCES = test_spec_pushpull.cpp +test_req_correlate_SOURCES = test_req_correlate.cpp +test_req_relaxed_SOURCES = test_req_relaxed.cpp +test_conflate_SOURCES = test_conflate.cpp +test_inproc_connect_SOURCES = test_inproc_connect.cpp +test_issue_566_SOURCES = test_issue_566.cpp +test_abstract_ipc_SOURCES = test_abstract_ipc.cpp +test_many_sockets_SOURCES = test_many_sockets.cpp +if !ON_MINGW +test_shutdown_stress_SOURCES = test_shutdown_stress.cpp +test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp +test_reqrep_ipc_SOURCES = test_reqrep_ipc.cpp testutil.hpp +test_timeo_SOURCES = test_timeo.cpp +test_fork_SOURCES = test_fork.cpp +endif + +# Run the test cases +TESTS = $(noinst_PROGRAMS) + +if !ON_LINUX +XFAIL_TESTS = test_abstract_ipc +endif diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 0000000..b6df9fc --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,1096 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test_system$(EXEEXT) test_pair_inproc$(EXEEXT) \ + test_pair_tcp$(EXEEXT) test_reqrep_inproc$(EXEEXT) \ + test_reqrep_tcp$(EXEEXT) test_hwm$(EXEEXT) \ + test_reqrep_device$(EXEEXT) test_sub_forward$(EXEEXT) \ + test_invalid_rep$(EXEEXT) test_msg_flags$(EXEEXT) \ + test_connect_resolve$(EXEEXT) test_immediate$(EXEEXT) \ + test_last_endpoint$(EXEEXT) test_term_endpoint$(EXEEXT) \ + test_monitor$(EXEEXT) test_router_mandatory$(EXEEXT) \ + test_router_raw_empty$(EXEEXT) test_probe_router$(EXEEXT) \ + test_stream$(EXEEXT) test_disconnect_inproc$(EXEEXT) \ + test_ctx_options$(EXEEXT) test_ctx_destroy$(EXEEXT) \ + test_security_null$(EXEEXT) test_security_plain$(EXEEXT) \ + test_security_curve$(EXEEXT) test_iov$(EXEEXT) \ + test_spec_req$(EXEEXT) test_spec_rep$(EXEEXT) \ + test_spec_dealer$(EXEEXT) test_spec_router$(EXEEXT) \ + test_spec_pushpull$(EXEEXT) test_req_correlate$(EXEEXT) \ + test_req_relaxed$(EXEEXT) test_conflate$(EXEEXT) \ + test_inproc_connect$(EXEEXT) test_issue_566$(EXEEXT) \ + test_abstract_ipc$(EXEEXT) test_many_sockets$(EXEEXT) \ + $(am__EXEEXT_1) +@ON_MINGW_FALSE@am__append_1 = test_shutdown_stress \ +@ON_MINGW_FALSE@ test_pair_ipc \ +@ON_MINGW_FALSE@ test_reqrep_ipc \ +@ON_MINGW_FALSE@ test_timeo \ +@ON_MINGW_FALSE@ test_fork + +@ON_LINUX_FALSE@XFAIL_TESTS = test_abstract_ipc$(EXEEXT) +subdir = tests +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ + $(top_srcdir)/config/ltoptions.m4 \ + $(top_srcdir)/config/ltsugar.m4 \ + $(top_srcdir)/config/ltversion.m4 \ + $(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/src/platform.hpp +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +@ON_MINGW_FALSE@am__EXEEXT_1 = test_shutdown_stress$(EXEEXT) \ +@ON_MINGW_FALSE@ test_pair_ipc$(EXEEXT) \ +@ON_MINGW_FALSE@ test_reqrep_ipc$(EXEEXT) test_timeo$(EXEEXT) \ +@ON_MINGW_FALSE@ test_fork$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_test_abstract_ipc_OBJECTS = test_abstract_ipc.$(OBJEXT) +test_abstract_ipc_OBJECTS = $(am_test_abstract_ipc_OBJECTS) +test_abstract_ipc_LDADD = $(LDADD) +test_abstract_ipc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am_test_conflate_OBJECTS = test_conflate.$(OBJEXT) +test_conflate_OBJECTS = $(am_test_conflate_OBJECTS) +test_conflate_LDADD = $(LDADD) +test_conflate_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_connect_resolve_OBJECTS = test_connect_resolve.$(OBJEXT) +test_connect_resolve_OBJECTS = $(am_test_connect_resolve_OBJECTS) +test_connect_resolve_LDADD = $(LDADD) +test_connect_resolve_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_ctx_destroy_OBJECTS = test_ctx_destroy.$(OBJEXT) +test_ctx_destroy_OBJECTS = $(am_test_ctx_destroy_OBJECTS) +test_ctx_destroy_LDADD = $(LDADD) +test_ctx_destroy_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_ctx_options_OBJECTS = test_ctx_options.$(OBJEXT) +test_ctx_options_OBJECTS = $(am_test_ctx_options_OBJECTS) +test_ctx_options_LDADD = $(LDADD) +test_ctx_options_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_disconnect_inproc_OBJECTS = test_disconnect_inproc.$(OBJEXT) +test_disconnect_inproc_OBJECTS = $(am_test_disconnect_inproc_OBJECTS) +test_disconnect_inproc_LDADD = $(LDADD) +test_disconnect_inproc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am__test_fork_SOURCES_DIST = test_fork.cpp +@ON_MINGW_FALSE@am_test_fork_OBJECTS = test_fork.$(OBJEXT) +test_fork_OBJECTS = $(am_test_fork_OBJECTS) +test_fork_LDADD = $(LDADD) +test_fork_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_hwm_OBJECTS = test_hwm.$(OBJEXT) +test_hwm_OBJECTS = $(am_test_hwm_OBJECTS) +test_hwm_LDADD = $(LDADD) +test_hwm_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_immediate_OBJECTS = test_immediate.$(OBJEXT) +test_immediate_OBJECTS = $(am_test_immediate_OBJECTS) +test_immediate_LDADD = $(LDADD) +test_immediate_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_inproc_connect_OBJECTS = test_inproc_connect.$(OBJEXT) +test_inproc_connect_OBJECTS = $(am_test_inproc_connect_OBJECTS) +test_inproc_connect_LDADD = $(LDADD) +test_inproc_connect_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_invalid_rep_OBJECTS = test_invalid_rep.$(OBJEXT) +test_invalid_rep_OBJECTS = $(am_test_invalid_rep_OBJECTS) +test_invalid_rep_LDADD = $(LDADD) +test_invalid_rep_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_iov_OBJECTS = test_iov.$(OBJEXT) +test_iov_OBJECTS = $(am_test_iov_OBJECTS) +test_iov_LDADD = $(LDADD) +test_iov_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_issue_566_OBJECTS = test_issue_566.$(OBJEXT) +test_issue_566_OBJECTS = $(am_test_issue_566_OBJECTS) +test_issue_566_LDADD = $(LDADD) +test_issue_566_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_last_endpoint_OBJECTS = test_last_endpoint.$(OBJEXT) +test_last_endpoint_OBJECTS = $(am_test_last_endpoint_OBJECTS) +test_last_endpoint_LDADD = $(LDADD) +test_last_endpoint_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_many_sockets_OBJECTS = test_many_sockets.$(OBJEXT) +test_many_sockets_OBJECTS = $(am_test_many_sockets_OBJECTS) +test_many_sockets_LDADD = $(LDADD) +test_many_sockets_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_monitor_OBJECTS = test_monitor.$(OBJEXT) +test_monitor_OBJECTS = $(am_test_monitor_OBJECTS) +test_monitor_LDADD = $(LDADD) +test_monitor_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_msg_flags_OBJECTS = test_msg_flags.$(OBJEXT) +test_msg_flags_OBJECTS = $(am_test_msg_flags_OBJECTS) +test_msg_flags_LDADD = $(LDADD) +test_msg_flags_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_pair_inproc_OBJECTS = test_pair_inproc.$(OBJEXT) +test_pair_inproc_OBJECTS = $(am_test_pair_inproc_OBJECTS) +test_pair_inproc_LDADD = $(LDADD) +test_pair_inproc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am__test_pair_ipc_SOURCES_DIST = test_pair_ipc.cpp testutil.hpp +@ON_MINGW_FALSE@am_test_pair_ipc_OBJECTS = test_pair_ipc.$(OBJEXT) +test_pair_ipc_OBJECTS = $(am_test_pair_ipc_OBJECTS) +test_pair_ipc_LDADD = $(LDADD) +test_pair_ipc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_pair_tcp_OBJECTS = test_pair_tcp.$(OBJEXT) +test_pair_tcp_OBJECTS = $(am_test_pair_tcp_OBJECTS) +test_pair_tcp_LDADD = $(LDADD) +test_pair_tcp_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_probe_router_OBJECTS = test_probe_router.$(OBJEXT) +test_probe_router_OBJECTS = $(am_test_probe_router_OBJECTS) +test_probe_router_LDADD = $(LDADD) +test_probe_router_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_req_correlate_OBJECTS = test_req_correlate.$(OBJEXT) +test_req_correlate_OBJECTS = $(am_test_req_correlate_OBJECTS) +test_req_correlate_LDADD = $(LDADD) +test_req_correlate_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_req_relaxed_OBJECTS = test_req_relaxed.$(OBJEXT) +test_req_relaxed_OBJECTS = $(am_test_req_relaxed_OBJECTS) +test_req_relaxed_LDADD = $(LDADD) +test_req_relaxed_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_reqrep_device_OBJECTS = test_reqrep_device.$(OBJEXT) +test_reqrep_device_OBJECTS = $(am_test_reqrep_device_OBJECTS) +test_reqrep_device_LDADD = $(LDADD) +test_reqrep_device_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_reqrep_inproc_OBJECTS = test_reqrep_inproc.$(OBJEXT) +test_reqrep_inproc_OBJECTS = $(am_test_reqrep_inproc_OBJECTS) +test_reqrep_inproc_LDADD = $(LDADD) +test_reqrep_inproc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am__test_reqrep_ipc_SOURCES_DIST = test_reqrep_ipc.cpp testutil.hpp +@ON_MINGW_FALSE@am_test_reqrep_ipc_OBJECTS = \ +@ON_MINGW_FALSE@ test_reqrep_ipc.$(OBJEXT) +test_reqrep_ipc_OBJECTS = $(am_test_reqrep_ipc_OBJECTS) +test_reqrep_ipc_LDADD = $(LDADD) +test_reqrep_ipc_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_reqrep_tcp_OBJECTS = test_reqrep_tcp.$(OBJEXT) +test_reqrep_tcp_OBJECTS = $(am_test_reqrep_tcp_OBJECTS) +test_reqrep_tcp_LDADD = $(LDADD) +test_reqrep_tcp_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_router_mandatory_OBJECTS = test_router_mandatory.$(OBJEXT) +test_router_mandatory_OBJECTS = $(am_test_router_mandatory_OBJECTS) +test_router_mandatory_LDADD = $(LDADD) +test_router_mandatory_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_router_raw_empty_OBJECTS = test_router_raw_empty.$(OBJEXT) +test_router_raw_empty_OBJECTS = $(am_test_router_raw_empty_OBJECTS) +test_router_raw_empty_LDADD = $(LDADD) +test_router_raw_empty_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_security_curve_OBJECTS = test_security_curve.$(OBJEXT) +test_security_curve_OBJECTS = $(am_test_security_curve_OBJECTS) +test_security_curve_LDADD = $(LDADD) +test_security_curve_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_security_null_OBJECTS = test_security_null.$(OBJEXT) +test_security_null_OBJECTS = $(am_test_security_null_OBJECTS) +test_security_null_LDADD = $(LDADD) +test_security_null_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_security_plain_OBJECTS = test_security_plain.$(OBJEXT) +test_security_plain_OBJECTS = $(am_test_security_plain_OBJECTS) +test_security_plain_LDADD = $(LDADD) +test_security_plain_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am__test_shutdown_stress_SOURCES_DIST = test_shutdown_stress.cpp +@ON_MINGW_FALSE@am_test_shutdown_stress_OBJECTS = \ +@ON_MINGW_FALSE@ test_shutdown_stress.$(OBJEXT) +test_shutdown_stress_OBJECTS = $(am_test_shutdown_stress_OBJECTS) +test_shutdown_stress_LDADD = $(LDADD) +test_shutdown_stress_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_spec_dealer_OBJECTS = test_spec_dealer.$(OBJEXT) +test_spec_dealer_OBJECTS = $(am_test_spec_dealer_OBJECTS) +test_spec_dealer_LDADD = $(LDADD) +test_spec_dealer_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_spec_pushpull_OBJECTS = test_spec_pushpull.$(OBJEXT) +test_spec_pushpull_OBJECTS = $(am_test_spec_pushpull_OBJECTS) +test_spec_pushpull_LDADD = $(LDADD) +test_spec_pushpull_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_spec_rep_OBJECTS = test_spec_rep.$(OBJEXT) +test_spec_rep_OBJECTS = $(am_test_spec_rep_OBJECTS) +test_spec_rep_LDADD = $(LDADD) +test_spec_rep_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_spec_req_OBJECTS = test_spec_req.$(OBJEXT) +test_spec_req_OBJECTS = $(am_test_spec_req_OBJECTS) +test_spec_req_LDADD = $(LDADD) +test_spec_req_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_spec_router_OBJECTS = test_spec_router.$(OBJEXT) +test_spec_router_OBJECTS = $(am_test_spec_router_OBJECTS) +test_spec_router_LDADD = $(LDADD) +test_spec_router_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_stream_OBJECTS = test_stream.$(OBJEXT) +test_stream_OBJECTS = $(am_test_stream_OBJECTS) +test_stream_LDADD = $(LDADD) +test_stream_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_sub_forward_OBJECTS = test_sub_forward.$(OBJEXT) +test_sub_forward_OBJECTS = $(am_test_sub_forward_OBJECTS) +test_sub_forward_LDADD = $(LDADD) +test_sub_forward_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_system_OBJECTS = test_system.$(OBJEXT) +test_system_OBJECTS = $(am_test_system_OBJECTS) +test_system_LDADD = $(LDADD) +test_system_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am_test_term_endpoint_OBJECTS = test_term_endpoint.$(OBJEXT) +test_term_endpoint_OBJECTS = $(am_test_term_endpoint_OBJECTS) +test_term_endpoint_LDADD = $(LDADD) +test_term_endpoint_DEPENDENCIES = $(top_builddir)/src/libzmq.la +am__test_timeo_SOURCES_DIST = test_timeo.cpp +@ON_MINGW_FALSE@am_test_timeo_OBJECTS = test_timeo.$(OBJEXT) +test_timeo_OBJECTS = $(am_test_timeo_OBJECTS) +test_timeo_LDADD = $(LDADD) +test_timeo_DEPENDENCIES = $(top_builddir)/src/libzmq.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(test_abstract_ipc_SOURCES) $(test_conflate_SOURCES) \ + $(test_connect_resolve_SOURCES) $(test_ctx_destroy_SOURCES) \ + $(test_ctx_options_SOURCES) $(test_disconnect_inproc_SOURCES) \ + $(test_fork_SOURCES) $(test_hwm_SOURCES) \ + $(test_immediate_SOURCES) $(test_inproc_connect_SOURCES) \ + $(test_invalid_rep_SOURCES) $(test_iov_SOURCES) \ + $(test_issue_566_SOURCES) $(test_last_endpoint_SOURCES) \ + $(test_many_sockets_SOURCES) $(test_monitor_SOURCES) \ + $(test_msg_flags_SOURCES) $(test_pair_inproc_SOURCES) \ + $(test_pair_ipc_SOURCES) $(test_pair_tcp_SOURCES) \ + $(test_probe_router_SOURCES) $(test_req_correlate_SOURCES) \ + $(test_req_relaxed_SOURCES) $(test_reqrep_device_SOURCES) \ + $(test_reqrep_inproc_SOURCES) $(test_reqrep_ipc_SOURCES) \ + $(test_reqrep_tcp_SOURCES) $(test_router_mandatory_SOURCES) \ + $(test_router_raw_empty_SOURCES) \ + $(test_security_curve_SOURCES) $(test_security_null_SOURCES) \ + $(test_security_plain_SOURCES) $(test_shutdown_stress_SOURCES) \ + $(test_spec_dealer_SOURCES) $(test_spec_pushpull_SOURCES) \ + $(test_spec_rep_SOURCES) $(test_spec_req_SOURCES) \ + $(test_spec_router_SOURCES) $(test_stream_SOURCES) \ + $(test_sub_forward_SOURCES) $(test_system_SOURCES) \ + $(test_term_endpoint_SOURCES) $(test_timeo_SOURCES) +DIST_SOURCES = $(test_abstract_ipc_SOURCES) $(test_conflate_SOURCES) \ + $(test_connect_resolve_SOURCES) $(test_ctx_destroy_SOURCES) \ + $(test_ctx_options_SOURCES) $(test_disconnect_inproc_SOURCES) \ + $(am__test_fork_SOURCES_DIST) $(test_hwm_SOURCES) \ + $(test_immediate_SOURCES) $(test_inproc_connect_SOURCES) \ + $(test_invalid_rep_SOURCES) $(test_iov_SOURCES) \ + $(test_issue_566_SOURCES) $(test_last_endpoint_SOURCES) \ + $(test_many_sockets_SOURCES) $(test_monitor_SOURCES) \ + $(test_msg_flags_SOURCES) $(test_pair_inproc_SOURCES) \ + $(am__test_pair_ipc_SOURCES_DIST) $(test_pair_tcp_SOURCES) \ + $(test_probe_router_SOURCES) $(test_req_correlate_SOURCES) \ + $(test_req_relaxed_SOURCES) $(test_reqrep_device_SOURCES) \ + $(test_reqrep_inproc_SOURCES) \ + $(am__test_reqrep_ipc_SOURCES_DIST) $(test_reqrep_tcp_SOURCES) \ + $(test_router_mandatory_SOURCES) \ + $(test_router_raw_empty_SOURCES) \ + $(test_security_curve_SOURCES) $(test_security_null_SOURCES) \ + $(test_security_plain_SOURCES) \ + $(am__test_shutdown_stress_SOURCES_DIST) \ + $(test_spec_dealer_SOURCES) $(test_spec_pushpull_SOURCES) \ + $(test_spec_rep_SOURCES) $(test_spec_req_SOURCES) \ + $(test_spec_router_SOURCES) $(test_stream_SOURCES) \ + $(test_sub_forward_SOURCES) $(test_system_SOURCES) \ + $(test_term_endpoint_SOURCES) $(am__test_timeo_SOURCES_DIST) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBZMQ_EXTRA_CFLAGS = @LIBZMQ_EXTRA_CFLAGS@ +LIBZMQ_EXTRA_CXXFLAGS = @LIBZMQ_EXTRA_CXXFLAGS@ +LIBZMQ_EXTRA_LDFLAGS = @LIBZMQ_EXTRA_LDFLAGS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LTVER = @LTVER@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +OpenPGM_CFLAGS = @OpenPGM_CFLAGS@ +OpenPGM_LIBS = @OpenPGM_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XMLTO = @XMLTO@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libzmq_have_asciidoc = @libzmq_have_asciidoc@ +libzmq_have_xmlto = @libzmq_have_xmlto@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pgm_basename = @pgm_basename@ +pgm_srcdir = @pgm_srcdir@ +pgm_subdir = @pgm_subdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_builddir)/include \ + -I$(top_srcdir)/include + +LDADD = $(top_builddir)/src/libzmq.la +test_system_SOURCES = test_system.cpp +test_pair_inproc_SOURCES = test_pair_inproc.cpp testutil.hpp +test_pair_tcp_SOURCES = test_pair_tcp.cpp testutil.hpp +test_reqrep_inproc_SOURCES = test_reqrep_inproc.cpp testutil.hpp +test_reqrep_tcp_SOURCES = test_reqrep_tcp.cpp testutil.hpp +test_hwm_SOURCES = test_hwm.cpp +test_reqrep_device_SOURCES = test_reqrep_device.cpp +test_sub_forward_SOURCES = test_sub_forward.cpp +test_invalid_rep_SOURCES = test_invalid_rep.cpp +test_msg_flags_SOURCES = test_msg_flags.cpp +test_connect_resolve_SOURCES = test_connect_resolve.cpp +test_immediate_SOURCES = test_immediate.cpp +test_last_endpoint_SOURCES = test_last_endpoint.cpp +test_term_endpoint_SOURCES = test_term_endpoint.cpp +test_monitor_SOURCES = test_monitor.cpp +test_router_mandatory_SOURCES = test_router_mandatory.cpp +test_router_raw_empty_SOURCES = test_router_raw_empty.cpp +test_probe_router_SOURCES = test_probe_router.cpp +test_stream_SOURCES = test_stream.cpp +test_disconnect_inproc_SOURCES = test_disconnect_inproc.cpp +test_ctx_options_SOURCES = test_ctx_options.cpp +test_iov_SOURCES = test_iov.cpp +test_ctx_destroy_SOURCES = test_ctx_destroy.cpp +test_security_null_SOURCES = test_security_null.cpp +test_security_plain_SOURCES = test_security_plain.cpp +test_security_curve_SOURCES = test_security_curve.cpp +test_spec_req_SOURCES = test_spec_req.cpp +test_spec_rep_SOURCES = test_spec_rep.cpp +test_spec_dealer_SOURCES = test_spec_dealer.cpp +test_spec_router_SOURCES = test_spec_router.cpp +test_spec_pushpull_SOURCES = test_spec_pushpull.cpp +test_req_correlate_SOURCES = test_req_correlate.cpp +test_req_relaxed_SOURCES = test_req_relaxed.cpp +test_conflate_SOURCES = test_conflate.cpp +test_inproc_connect_SOURCES = test_inproc_connect.cpp +test_issue_566_SOURCES = test_issue_566.cpp +test_abstract_ipc_SOURCES = test_abstract_ipc.cpp +test_many_sockets_SOURCES = test_many_sockets.cpp +@ON_MINGW_FALSE@test_shutdown_stress_SOURCES = test_shutdown_stress.cpp +@ON_MINGW_FALSE@test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp +@ON_MINGW_FALSE@test_reqrep_ipc_SOURCES = test_reqrep_ipc.cpp testutil.hpp +@ON_MINGW_FALSE@test_timeo_SOURCES = test_timeo.cpp +@ON_MINGW_FALSE@test_fork_SOURCES = test_fork.cpp + +# Run the test cases +TESTS = $(noinst_PROGRAMS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +test_abstract_ipc$(EXEEXT): $(test_abstract_ipc_OBJECTS) $(test_abstract_ipc_DEPENDENCIES) $(EXTRA_test_abstract_ipc_DEPENDENCIES) + @rm -f test_abstract_ipc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_abstract_ipc_OBJECTS) $(test_abstract_ipc_LDADD) $(LIBS) +test_conflate$(EXEEXT): $(test_conflate_OBJECTS) $(test_conflate_DEPENDENCIES) $(EXTRA_test_conflate_DEPENDENCIES) + @rm -f test_conflate$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_conflate_OBJECTS) $(test_conflate_LDADD) $(LIBS) +test_connect_resolve$(EXEEXT): $(test_connect_resolve_OBJECTS) $(test_connect_resolve_DEPENDENCIES) $(EXTRA_test_connect_resolve_DEPENDENCIES) + @rm -f test_connect_resolve$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_connect_resolve_OBJECTS) $(test_connect_resolve_LDADD) $(LIBS) +test_ctx_destroy$(EXEEXT): $(test_ctx_destroy_OBJECTS) $(test_ctx_destroy_DEPENDENCIES) $(EXTRA_test_ctx_destroy_DEPENDENCIES) + @rm -f test_ctx_destroy$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_ctx_destroy_OBJECTS) $(test_ctx_destroy_LDADD) $(LIBS) +test_ctx_options$(EXEEXT): $(test_ctx_options_OBJECTS) $(test_ctx_options_DEPENDENCIES) $(EXTRA_test_ctx_options_DEPENDENCIES) + @rm -f test_ctx_options$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_ctx_options_OBJECTS) $(test_ctx_options_LDADD) $(LIBS) +test_disconnect_inproc$(EXEEXT): $(test_disconnect_inproc_OBJECTS) $(test_disconnect_inproc_DEPENDENCIES) $(EXTRA_test_disconnect_inproc_DEPENDENCIES) + @rm -f test_disconnect_inproc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_disconnect_inproc_OBJECTS) $(test_disconnect_inproc_LDADD) $(LIBS) +test_fork$(EXEEXT): $(test_fork_OBJECTS) $(test_fork_DEPENDENCIES) $(EXTRA_test_fork_DEPENDENCIES) + @rm -f test_fork$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_fork_OBJECTS) $(test_fork_LDADD) $(LIBS) +test_hwm$(EXEEXT): $(test_hwm_OBJECTS) $(test_hwm_DEPENDENCIES) $(EXTRA_test_hwm_DEPENDENCIES) + @rm -f test_hwm$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_hwm_OBJECTS) $(test_hwm_LDADD) $(LIBS) +test_immediate$(EXEEXT): $(test_immediate_OBJECTS) $(test_immediate_DEPENDENCIES) $(EXTRA_test_immediate_DEPENDENCIES) + @rm -f test_immediate$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_immediate_OBJECTS) $(test_immediate_LDADD) $(LIBS) +test_inproc_connect$(EXEEXT): $(test_inproc_connect_OBJECTS) $(test_inproc_connect_DEPENDENCIES) $(EXTRA_test_inproc_connect_DEPENDENCIES) + @rm -f test_inproc_connect$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_inproc_connect_OBJECTS) $(test_inproc_connect_LDADD) $(LIBS) +test_invalid_rep$(EXEEXT): $(test_invalid_rep_OBJECTS) $(test_invalid_rep_DEPENDENCIES) $(EXTRA_test_invalid_rep_DEPENDENCIES) + @rm -f test_invalid_rep$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_invalid_rep_OBJECTS) $(test_invalid_rep_LDADD) $(LIBS) +test_iov$(EXEEXT): $(test_iov_OBJECTS) $(test_iov_DEPENDENCIES) $(EXTRA_test_iov_DEPENDENCIES) + @rm -f test_iov$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_iov_OBJECTS) $(test_iov_LDADD) $(LIBS) +test_issue_566$(EXEEXT): $(test_issue_566_OBJECTS) $(test_issue_566_DEPENDENCIES) $(EXTRA_test_issue_566_DEPENDENCIES) + @rm -f test_issue_566$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_issue_566_OBJECTS) $(test_issue_566_LDADD) $(LIBS) +test_last_endpoint$(EXEEXT): $(test_last_endpoint_OBJECTS) $(test_last_endpoint_DEPENDENCIES) $(EXTRA_test_last_endpoint_DEPENDENCIES) + @rm -f test_last_endpoint$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_last_endpoint_OBJECTS) $(test_last_endpoint_LDADD) $(LIBS) +test_many_sockets$(EXEEXT): $(test_many_sockets_OBJECTS) $(test_many_sockets_DEPENDENCIES) $(EXTRA_test_many_sockets_DEPENDENCIES) + @rm -f test_many_sockets$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_many_sockets_OBJECTS) $(test_many_sockets_LDADD) $(LIBS) +test_monitor$(EXEEXT): $(test_monitor_OBJECTS) $(test_monitor_DEPENDENCIES) $(EXTRA_test_monitor_DEPENDENCIES) + @rm -f test_monitor$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_monitor_OBJECTS) $(test_monitor_LDADD) $(LIBS) +test_msg_flags$(EXEEXT): $(test_msg_flags_OBJECTS) $(test_msg_flags_DEPENDENCIES) $(EXTRA_test_msg_flags_DEPENDENCIES) + @rm -f test_msg_flags$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_msg_flags_OBJECTS) $(test_msg_flags_LDADD) $(LIBS) +test_pair_inproc$(EXEEXT): $(test_pair_inproc_OBJECTS) $(test_pair_inproc_DEPENDENCIES) $(EXTRA_test_pair_inproc_DEPENDENCIES) + @rm -f test_pair_inproc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_pair_inproc_OBJECTS) $(test_pair_inproc_LDADD) $(LIBS) +test_pair_ipc$(EXEEXT): $(test_pair_ipc_OBJECTS) $(test_pair_ipc_DEPENDENCIES) $(EXTRA_test_pair_ipc_DEPENDENCIES) + @rm -f test_pair_ipc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_pair_ipc_OBJECTS) $(test_pair_ipc_LDADD) $(LIBS) +test_pair_tcp$(EXEEXT): $(test_pair_tcp_OBJECTS) $(test_pair_tcp_DEPENDENCIES) $(EXTRA_test_pair_tcp_DEPENDENCIES) + @rm -f test_pair_tcp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_pair_tcp_OBJECTS) $(test_pair_tcp_LDADD) $(LIBS) +test_probe_router$(EXEEXT): $(test_probe_router_OBJECTS) $(test_probe_router_DEPENDENCIES) $(EXTRA_test_probe_router_DEPENDENCIES) + @rm -f test_probe_router$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_probe_router_OBJECTS) $(test_probe_router_LDADD) $(LIBS) +test_req_correlate$(EXEEXT): $(test_req_correlate_OBJECTS) $(test_req_correlate_DEPENDENCIES) $(EXTRA_test_req_correlate_DEPENDENCIES) + @rm -f test_req_correlate$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_req_correlate_OBJECTS) $(test_req_correlate_LDADD) $(LIBS) +test_req_relaxed$(EXEEXT): $(test_req_relaxed_OBJECTS) $(test_req_relaxed_DEPENDENCIES) $(EXTRA_test_req_relaxed_DEPENDENCIES) + @rm -f test_req_relaxed$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_req_relaxed_OBJECTS) $(test_req_relaxed_LDADD) $(LIBS) +test_reqrep_device$(EXEEXT): $(test_reqrep_device_OBJECTS) $(test_reqrep_device_DEPENDENCIES) $(EXTRA_test_reqrep_device_DEPENDENCIES) + @rm -f test_reqrep_device$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_reqrep_device_OBJECTS) $(test_reqrep_device_LDADD) $(LIBS) +test_reqrep_inproc$(EXEEXT): $(test_reqrep_inproc_OBJECTS) $(test_reqrep_inproc_DEPENDENCIES) $(EXTRA_test_reqrep_inproc_DEPENDENCIES) + @rm -f test_reqrep_inproc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_reqrep_inproc_OBJECTS) $(test_reqrep_inproc_LDADD) $(LIBS) +test_reqrep_ipc$(EXEEXT): $(test_reqrep_ipc_OBJECTS) $(test_reqrep_ipc_DEPENDENCIES) $(EXTRA_test_reqrep_ipc_DEPENDENCIES) + @rm -f test_reqrep_ipc$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_reqrep_ipc_OBJECTS) $(test_reqrep_ipc_LDADD) $(LIBS) +test_reqrep_tcp$(EXEEXT): $(test_reqrep_tcp_OBJECTS) $(test_reqrep_tcp_DEPENDENCIES) $(EXTRA_test_reqrep_tcp_DEPENDENCIES) + @rm -f test_reqrep_tcp$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_reqrep_tcp_OBJECTS) $(test_reqrep_tcp_LDADD) $(LIBS) +test_router_mandatory$(EXEEXT): $(test_router_mandatory_OBJECTS) $(test_router_mandatory_DEPENDENCIES) $(EXTRA_test_router_mandatory_DEPENDENCIES) + @rm -f test_router_mandatory$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_router_mandatory_OBJECTS) $(test_router_mandatory_LDADD) $(LIBS) +test_router_raw_empty$(EXEEXT): $(test_router_raw_empty_OBJECTS) $(test_router_raw_empty_DEPENDENCIES) $(EXTRA_test_router_raw_empty_DEPENDENCIES) + @rm -f test_router_raw_empty$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_router_raw_empty_OBJECTS) $(test_router_raw_empty_LDADD) $(LIBS) +test_security_curve$(EXEEXT): $(test_security_curve_OBJECTS) $(test_security_curve_DEPENDENCIES) $(EXTRA_test_security_curve_DEPENDENCIES) + @rm -f test_security_curve$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_security_curve_OBJECTS) $(test_security_curve_LDADD) $(LIBS) +test_security_null$(EXEEXT): $(test_security_null_OBJECTS) $(test_security_null_DEPENDENCIES) $(EXTRA_test_security_null_DEPENDENCIES) + @rm -f test_security_null$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_security_null_OBJECTS) $(test_security_null_LDADD) $(LIBS) +test_security_plain$(EXEEXT): $(test_security_plain_OBJECTS) $(test_security_plain_DEPENDENCIES) $(EXTRA_test_security_plain_DEPENDENCIES) + @rm -f test_security_plain$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_security_plain_OBJECTS) $(test_security_plain_LDADD) $(LIBS) +test_shutdown_stress$(EXEEXT): $(test_shutdown_stress_OBJECTS) $(test_shutdown_stress_DEPENDENCIES) $(EXTRA_test_shutdown_stress_DEPENDENCIES) + @rm -f test_shutdown_stress$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_shutdown_stress_OBJECTS) $(test_shutdown_stress_LDADD) $(LIBS) +test_spec_dealer$(EXEEXT): $(test_spec_dealer_OBJECTS) $(test_spec_dealer_DEPENDENCIES) $(EXTRA_test_spec_dealer_DEPENDENCIES) + @rm -f test_spec_dealer$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_spec_dealer_OBJECTS) $(test_spec_dealer_LDADD) $(LIBS) +test_spec_pushpull$(EXEEXT): $(test_spec_pushpull_OBJECTS) $(test_spec_pushpull_DEPENDENCIES) $(EXTRA_test_spec_pushpull_DEPENDENCIES) + @rm -f test_spec_pushpull$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_spec_pushpull_OBJECTS) $(test_spec_pushpull_LDADD) $(LIBS) +test_spec_rep$(EXEEXT): $(test_spec_rep_OBJECTS) $(test_spec_rep_DEPENDENCIES) $(EXTRA_test_spec_rep_DEPENDENCIES) + @rm -f test_spec_rep$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_spec_rep_OBJECTS) $(test_spec_rep_LDADD) $(LIBS) +test_spec_req$(EXEEXT): $(test_spec_req_OBJECTS) $(test_spec_req_DEPENDENCIES) $(EXTRA_test_spec_req_DEPENDENCIES) + @rm -f test_spec_req$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_spec_req_OBJECTS) $(test_spec_req_LDADD) $(LIBS) +test_spec_router$(EXEEXT): $(test_spec_router_OBJECTS) $(test_spec_router_DEPENDENCIES) $(EXTRA_test_spec_router_DEPENDENCIES) + @rm -f test_spec_router$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_spec_router_OBJECTS) $(test_spec_router_LDADD) $(LIBS) +test_stream$(EXEEXT): $(test_stream_OBJECTS) $(test_stream_DEPENDENCIES) $(EXTRA_test_stream_DEPENDENCIES) + @rm -f test_stream$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_stream_OBJECTS) $(test_stream_LDADD) $(LIBS) +test_sub_forward$(EXEEXT): $(test_sub_forward_OBJECTS) $(test_sub_forward_DEPENDENCIES) $(EXTRA_test_sub_forward_DEPENDENCIES) + @rm -f test_sub_forward$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_sub_forward_OBJECTS) $(test_sub_forward_LDADD) $(LIBS) +test_system$(EXEEXT): $(test_system_OBJECTS) $(test_system_DEPENDENCIES) $(EXTRA_test_system_DEPENDENCIES) + @rm -f test_system$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_system_OBJECTS) $(test_system_LDADD) $(LIBS) +test_term_endpoint$(EXEEXT): $(test_term_endpoint_OBJECTS) $(test_term_endpoint_DEPENDENCIES) $(EXTRA_test_term_endpoint_DEPENDENCIES) + @rm -f test_term_endpoint$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_term_endpoint_OBJECTS) $(test_term_endpoint_LDADD) $(LIBS) +test_timeo$(EXEEXT): $(test_timeo_OBJECTS) $(test_timeo_DEPENDENCIES) $(EXTRA_test_timeo_DEPENDENCIES) + @rm -f test_timeo$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_timeo_OBJECTS) $(test_timeo_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_abstract_ipc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conflate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connect_resolve.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ctx_destroy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ctx_options.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_disconnect_inproc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fork.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_hwm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_immediate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_inproc_connect.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_invalid_rep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_iov.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_issue_566.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_last_endpoint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_many_sockets.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_msg_flags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pair_inproc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pair_ipc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pair_tcp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_probe_router.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_req_correlate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_req_relaxed.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_reqrep_device.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_reqrep_inproc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_reqrep_ipc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_reqrep_tcp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_router_mandatory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_router_raw_empty.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_security_curve.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_security_null.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_security_plain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_shutdown_stress.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spec_dealer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spec_pushpull.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spec_rep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spec_req.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_spec_router.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_stream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sub_forward.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_system.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_term_endpoint.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_timeo.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/test_abstract_ipc.cpp b/tests/test_abstract_ipc.cpp new file mode 100644 index 0000000..3c91f32 --- /dev/null +++ b/tests/test_abstract_ipc.cpp @@ -0,0 +1,57 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_PAIR); + assert (sb); + int rc = zmq_bind (sb, "ipc://@/tmp/tester"); + assert (rc == 0); + + char endpoint[200]; + size_t size = sizeof(endpoint); + rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &size); + assert (rc == 0); + rc = strncmp(endpoint, "ipc://@/tmp/tester", size); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_PAIR); + assert (sc); + rc = zmq_connect (sc, "ipc://@/tmp/tester"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_conflate.cpp b/tests/test_conflate.cpp new file mode 100644 index 0000000..9c3ba5a --- /dev/null +++ b/tests/test_conflate.cpp @@ -0,0 +1,72 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (int argc, char *argv []) +{ + const char *bind_to = "tcp://127.0.0.1:5555"; + + int rc; + + void* ctx = zmq_init (1); + assert (ctx); + + void* s_in = zmq_socket (ctx, ZMQ_PULL); + assert (s_in); + + int conflate = 1; + rc = zmq_setsockopt (s_in, ZMQ_CONFLATE, &conflate, sizeof(conflate)); + assert (rc == 0); + + rc = zmq_bind (s_in, bind_to); + assert (rc == 0); + + void* s_out = zmq_socket (ctx, ZMQ_PUSH); + assert (s_out); + + rc = zmq_connect (s_out, bind_to); + assert (rc == 0); + + int message_count = 20; + for (int j = 0; j < message_count; ++j) { + rc = zmq_send(s_out, (void*)&j, sizeof(int), 0); + if (rc < 0) { + printf ("error in zmq_sendmsg: %s\n", zmq_strerror (errno)); + return -1; + } + } + msleep (SETTLE_TIME); + + int payload_recved = 0; + rc = zmq_recv (s_in, (void*)&payload_recved, sizeof(int), 0); + assert (rc > 0); + assert (payload_recved == message_count - 1); + + rc = zmq_close (s_in); + assert (rc == 0); + + rc = zmq_close (s_out); + assert (rc == 0); + + rc = zmq_term (ctx); + assert (rc == 0); + + return 0; +} diff --git a/tests/test_connect_resolve.cpp b/tests/test_connect_resolve.cpp new file mode 100644 index 0000000..4c49e8f --- /dev/null +++ b/tests/test_connect_resolve.cpp @@ -0,0 +1,53 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sock = zmq_socket (ctx, ZMQ_PUB); + assert (sock); + + int rc = zmq_connect (sock, "tcp://localhost:1234"); + assert (rc == 0); + + rc = zmq_connect (sock, "tcp://localhost:invalid"); + assert (rc == -1); + assert (errno == EINVAL); + + rc = zmq_connect (sock, "tcp://in val id:1234"); + assert (rc == -1); + assert (errno == EINVAL); + + rc = zmq_connect (sock, "invalid://localhost:1234"); + assert (rc == -1); + assert (errno == EPROTONOSUPPORT); + + rc = zmq_close (sock); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0; +} diff --git a/tests/test_ctx_destroy.cpp b/tests/test_ctx_destroy.cpp new file mode 100644 index 0000000..a269b2b --- /dev/null +++ b/tests/test_ctx_destroy.cpp @@ -0,0 +1,90 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +static void receiver (void *socket) +{ + char buffer[16]; + int rc = zmq_recv (socket, &buffer, sizeof (buffer), 0); + assert(rc == -1); +} + +void test_ctx_destroy() +{ + int rc; + + // Set up our context and sockets + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *socket = zmq_socket (ctx, ZMQ_PULL); + assert (socket); + + // Close the socket + rc = zmq_close (socket); + assert (rc == 0); + + // Destroy the context + rc = zmq_ctx_destroy (ctx); + assert (rc == 0); +} + +void test_ctx_shutdown() +{ + int rc; + + // Set up our context and sockets + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *socket = zmq_socket (ctx, ZMQ_PULL); + assert (socket); + + // Spawn a thread to receive on socket + void *receiver_thread = zmq_threadstart (&receiver, socket); + + // Wait for thread to start up and block + msleep (SETTLE_TIME); + + // Shutdown context, if we used destroy here we would deadlock. + rc = zmq_ctx_shutdown (ctx); + assert (rc == 0); + + // Wait for thread to finish + zmq_threadclose (receiver_thread); + + // Close the socket. + rc = zmq_close (socket); + assert (rc == 0); + + // Destory the context, will now not hang as we have closed the socket. + rc = zmq_ctx_destroy (ctx); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + + test_ctx_destroy(); + test_ctx_shutdown(); + + return 0; +} diff --git a/tests/test_ctx_options.cpp b/tests/test_ctx_options.cpp new file mode 100644 index 0000000..900e125 --- /dev/null +++ b/tests/test_ctx_options.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + int rc; + + // 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); + assert (zmq_ctx_get (ctx, ZMQ_IO_THREADS) == ZMQ_IO_THREADS_DFLT); + assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 0); + + rc = zmq_ctx_set (ctx, ZMQ_IPV6, true); + assert (zmq_ctx_get (ctx, ZMQ_IPV6) == 1); + + void *router = zmq_socket (ctx, ZMQ_ROUTER); + int ipv6; + size_t optsize = sizeof (int); + rc = zmq_getsockopt (router, ZMQ_IPV6, &ipv6, &optsize); + assert (rc == 0); + assert (ipv6); + + rc = zmq_close (router); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0; +} diff --git a/tests/test_disconnect_inproc.cpp b/tests/test_disconnect_inproc.cpp new file mode 100644 index 0000000..1b0fd31 --- /dev/null +++ b/tests/test_disconnect_inproc.cpp @@ -0,0 +1,125 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +/// 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)); \ +memcpy(zmq_msg_data(&msg), data, size + 1); + +int publicationsReceived = 0; +bool isSubscribed = false; + +int main(int argc, char** argv) { + setup_test_environment(); + void* context = zmq_ctx_new(); + void* pubSocket; + void* subSocket; + + (pubSocket = zmq_socket(context, ZMQ_XPUB)) || printf("zmq_socket: %s\n", zmq_strerror(errno)); + (subSocket = zmq_socket(context, ZMQ_SUB)) || printf("zmq_socket: %s\n", zmq_strerror(errno)); + zmq_setsockopt(subSocket, ZMQ_SUBSCRIBE, "foo", 3) && printf("zmq_setsockopt: %s\n",zmq_strerror(errno)); + + zmq_bind(pubSocket, "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)); + + int more; + size_t more_size = sizeof(more); + int iteration = 0; + + while (1) { + zmq_pollitem_t items [] = { + { subSocket, 0, ZMQ_POLLIN, 0 }, // read publications + { pubSocket, 0, ZMQ_POLLIN, 0 }, // read subscriptions + }; + int rc = zmq_poll (items, 2, 100); + + if (items [1].revents & ZMQ_POLLIN) { + while (1) { + zmq_msg_t msg; + zmq_msg_init (&msg); + zmq_msg_recv (&msg, pubSocket, 0); + char* buffer = (char*)zmq_msg_data(&msg); + + if (buffer[0] == 0) { + assert(isSubscribed); + isSubscribed = false; + } + else { + assert(!isSubscribed); + isSubscribed = true; + } + + zmq_getsockopt (pubSocket, ZMQ_RCVMORE, &more, &more_size); + zmq_msg_close (&msg); + + if (!more) + break; // Last message part + } + } + + if (items[0].revents & ZMQ_POLLIN) { + while (1) { + zmq_msg_t msg; + zmq_msg_init (&msg); + zmq_msg_recv (&msg, subSocket, 0); + zmq_getsockopt (subSocket, ZMQ_RCVMORE, &more, &more_size); + zmq_msg_close (&msg); + + if (!more) { + publicationsReceived++; + break; // Last message part + } + } + } + if (iteration == 1) { + zmq_connect(subSocket, "inproc://someInProcDescriptor") && printf("zmq_connect: %s\n", zmq_strerror(errno)); + //zmq_connect(subSocket, "tcp://127.0.0.1:30010") && printf("zmq_connect: %s\n", zmq_strerror(errno)); + } + if (iteration == 4) { + zmq_disconnect(subSocket, "inproc://someInProcDescriptor") && printf("zmq_disconnect(%d): %s\n", errno, zmq_strerror(errno)); + //zmq_disconnect(subSocket, "tcp://127.0.0.1:30010") && printf("zmq_disconnect: %s\n", zmq_strerror(errno)); + } + if (iteration > 4 && rc == 0) + break; + + zmq_msg_t channelEnvlp; + ZMQ_PREPARE_STRING(channelEnvlp, "foo", 3); + zmq_msg_send (&channelEnvlp, pubSocket, ZMQ_SNDMORE) >= 0 || printf("zmq_msg_send: %s\n",zmq_strerror(errno)); + zmq_msg_close(&channelEnvlp) && printf("zmq_msg_close: %s\n",zmq_strerror(errno)); + + zmq_msg_t message; + ZMQ_PREPARE_STRING(message, "this is foo!", 12); + zmq_msg_send (&message, pubSocket, 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++; + } + assert(publicationsReceived == 3); + assert(!isSubscribed); + + zmq_close(pubSocket) && printf("zmq_close: %s", zmq_strerror(errno)); + zmq_close(subSocket) && printf("zmq_close: %s", zmq_strerror(errno)); + + zmq_ctx_term(context); + return 0; +} + diff --git a/tests/test_fork.cpp b/tests/test_fork.cpp new file mode 100644 index 0000000..637b6e9 --- /dev/null +++ b/tests/test_fork.cpp @@ -0,0 +1,81 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *address = "tcp://127.0.0.1:6571"; + +#define NUM_MESSAGES 5 + +int main (void) +{ + 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); + + int pid = fork (); + if (pid == 0) { + // Child process + // Immediately close parent sockets and context + zmq_close (pull); + zmq_term (ctx); + + // 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, address); + assert (rc == 0); + int count; + for (count = 0; count < NUM_MESSAGES; count++) + zmq_send (push, "Hello", 5, 0); + + zmq_close (push); + zmq_ctx_destroy (child_ctx); + exit (0); + } + else { + // Parent process + int count; + for (count = 0; count < NUM_MESSAGES; count++) { + char buffer [5]; + int num_bytes = zmq_recv (pull, buffer, 5, 0); + assert (num_bytes == 5); + } + int child_status; + while (true) { + rc = waitpid (pid, &child_status, 0); + if (rc == -1 && errno == EINTR) + continue; + assert (rc > 0); + // Verify the status code of the child was zero + assert (WEXITSTATUS (child_status) == 0); + break; + } + exit (0); + } + return 0; +} diff --git a/tests/test_hwm.cpp b/tests/test_hwm.cpp new file mode 100644 index 0000000..b1d871e --- /dev/null +++ b/tests/test_hwm.cpp @@ -0,0 +1,299 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const int MAX_SENDS = 10000; + +enum TestType { BIND_FIRST, CONNECT_FIRST }; + +int test_defaults () +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + int rc; + + // Set up bind socket + void *bind_socket = zmq_socket (ctx, ZMQ_PULL); + assert (bind_socket); + rc = zmq_bind (bind_socket, "inproc://a"); + assert (rc == 0); + + // Set up connect socket + void *connect_socket = zmq_socket (ctx, ZMQ_PUSH); + assert (connect_socket); + rc = zmq_connect (connect_socket, "inproc://a"); + assert (rc == 0); + + // Send until we block + int send_count = 0; + while (send_count < MAX_SENDS && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++send_count; + + // Now receive all sent messages + int recv_count = 0; + while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++recv_count; + + assert (send_count == recv_count); + + // Clean up + rc = zmq_close (connect_socket); + assert (rc == 0); + + rc = zmq_close (bind_socket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return send_count; +} + +int count_msg (int send_hwm, int recv_hwm, TestType testType) +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + int rc; + + void *bind_socket; + void *connect_socket; + if (testType == BIND_FIRST) + { + // Set up bind socket + bind_socket = zmq_socket (ctx, ZMQ_PULL); + assert (bind_socket); + rc = zmq_setsockopt (bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)); + assert (rc == 0); + rc = zmq_bind (bind_socket, "inproc://a"); + assert (rc == 0); + + // Set up connect socket + connect_socket = zmq_socket (ctx, ZMQ_PUSH); + assert (connect_socket); + rc = zmq_setsockopt (connect_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)); + assert (rc == 0); + rc = zmq_connect (connect_socket, "inproc://a"); + assert (rc == 0); + } + else + { + // Set up connect socket + connect_socket = zmq_socket (ctx, ZMQ_PUSH); + assert (connect_socket); + rc = zmq_setsockopt (connect_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)); + assert (rc == 0); + rc = zmq_connect (connect_socket, "inproc://a"); + assert (rc == 0); + + // Set up bind socket + bind_socket = zmq_socket (ctx, ZMQ_PULL); + assert (bind_socket); + rc = zmq_setsockopt (bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)); + assert (rc == 0); + rc = zmq_bind (bind_socket, "inproc://a"); + assert (rc == 0); + } + + // Send until we block + int send_count = 0; + while (send_count < MAX_SENDS && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++send_count; + + // Now receive all sent messages + int recv_count = 0; + while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++recv_count; + + assert (send_count == recv_count); + + // Now it should be possible to send one more. + rc = zmq_send (connect_socket, NULL, 0, 0); + assert (rc == 0); + + // Consume the remaining message. + rc = zmq_recv (bind_socket, NULL, 0, 0); + assert (rc == 0); + + // Clean up + rc = zmq_close (connect_socket); + assert (rc == 0); + + rc = zmq_close (bind_socket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return send_count; +} + +int test_inproc_bind_first (int send_hwm, int recv_hwm) +{ + return count_msg(send_hwm, recv_hwm, BIND_FIRST); +} + +int test_inproc_connect_first (int send_hwm, int recv_hwm) +{ + return count_msg(send_hwm, recv_hwm, CONNECT_FIRST); +} + +int test_inproc_connect_and_close_first (int send_hwm, int recv_hwm) +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + int rc; + + // Set up connect socket + void *connect_socket = zmq_socket (ctx, ZMQ_PUSH); + assert (connect_socket); + rc = zmq_setsockopt (connect_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)); + assert (rc == 0); + rc = zmq_connect (connect_socket, "inproc://a"); + assert (rc == 0); + + // Send until we block + int send_count = 0; + while (send_count < MAX_SENDS && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++send_count; + + // Close connect + rc = zmq_close (connect_socket); + assert (rc == 0); + + // Set up bind socket + void *bind_socket = zmq_socket (ctx, ZMQ_PULL); + assert (bind_socket); + rc = zmq_setsockopt (bind_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)); + assert (rc == 0); + rc = zmq_bind (bind_socket, "inproc://a"); + assert (rc == 0); + + // Now receive all sent messages + int recv_count = 0; + while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++recv_count; + + assert (send_count == recv_count); + + // Clean up + rc = zmq_close (bind_socket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return send_count; +} + +int test_inproc_bind_and_close_first (int send_hwm, int recv_hwm) +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + int rc; + + // Set up bind socket + void *bind_socket = zmq_socket (ctx, ZMQ_PUSH); + assert (bind_socket); + rc = zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &send_hwm, sizeof (send_hwm)); + assert (rc == 0); + rc = zmq_bind (bind_socket, "inproc://a"); + assert (rc == 0); + + // Send until we block + int send_count = 0; + while (send_count < MAX_SENDS && zmq_send (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++send_count; + + // Close bind + rc = zmq_close (bind_socket); + assert (rc == 0); + + /* 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); + assert (connect_socket); + rc = zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)); + assert (rc == 0); + rc = zmq_connect (connect_socket, "inproc://a"); + assert (rc == 0); + + // Now receive all sent messages + int recv_count = 0; + while (zmq_recv (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0) + ++recv_count; + + assert (send_count == recv_count); + */ + + // Clean up + //rc = zmq_close (connect_socket); + //assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return send_count; +} + +int main (void) +{ + setup_test_environment(); + + int count; + + // Default values are 1000 on send and 1000 one receive, so 2000 total + count = test_defaults (); + assert (count == 2000); + + // Infinite send and receive buffer + count = test_inproc_bind_first (0, 0); + assert (count == MAX_SENDS); + count = test_inproc_connect_first (0, 0); + assert (count == MAX_SENDS); + + // Infinite send buffer + count = test_inproc_bind_first (1, 0); + assert (count == MAX_SENDS); + count = test_inproc_connect_first (1, 0); + assert (count == MAX_SENDS); + + // Infinite receive buffer + count = test_inproc_bind_first (0, 1); + assert (count == MAX_SENDS); + count = test_inproc_connect_first (0, 1); + assert (count == MAX_SENDS); + + // Send and recv buffers hwm 1, so total that can be queued is 2 + count = test_inproc_bind_first (1, 1); + assert (count == 2); + count = test_inproc_connect_first (1, 1); + assert (count == 2); + + // Send hwm of 1, send before bind so total that can be queued is 1 + count = test_inproc_connect_and_close_first (1, 0); + assert (count == 1); + + // Send hwm of 1, send from bind side before connect so total that can be queued should be 1, + // however currently all messages get thrown away before the connect. BUG? + count = test_inproc_bind_and_close_first (1, 0); + //assert (count == 1); + + return 0; +} diff --git a/tests/test_immediate.cpp b/tests/test_immediate.cpp new file mode 100644 index 0000000..2ac4aa3 --- /dev/null +++ b/tests/test_immediate.cpp @@ -0,0 +1,228 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + int val; + int rc; + char buffer[16]; + // TEST 1. + // First we're going to attempt to send messages to two + // pipes, one connected, the other not. We should see + // the PUSH load balancing to both pipes, and hence half + // of the messages getting queued, as connect() creates a + // pipe immediately. + + void *context = zmq_ctx_new(); + assert (context); + void *to = zmq_socket(context, ZMQ_PULL); + assert (to); + + // Bind the one valid receiver + val = 0; + rc = zmq_setsockopt(to, ZMQ_LINGER, &val, sizeof(val)); + assert (rc == 0); + rc = zmq_bind (to, "tcp://127.0.0.1:6555"); + assert (rc == 0); + + // Create a socket pushing to two endpoints - only 1 message should arrive. + void *from = zmq_socket (context, ZMQ_PUSH); + assert(from); + + val = 0; + zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)); + // This pipe will not connect + rc = zmq_connect (from, "tcp://localhost:5556"); + assert (rc == 0); + // This pipe will + rc = zmq_connect (from, "tcp://localhost:6555"); + assert (rc == 0); + + // We send 10 messages, 5 should just get stuck in the queue + // for the not-yet-connected pipe + for (int i = 0; i < 10; ++i) { + rc = zmq_send (from, "Hello", 5, 0); + assert (rc == 5); + } + + // We now consume from the connected pipe + // - we should see just 5 + int timeout = 100; + rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + int seen = 0; + while (true) { + rc = zmq_recv (to, &buffer, sizeof (buffer), 0); + if (rc == -1) + break; // Break when we didn't get a message + seen++; + } + assert (seen == 5); + + rc = zmq_close (from); + assert (rc == 0); + + rc = zmq_close (to); + assert (rc == 0); + + rc = zmq_ctx_term (context); + assert (rc == 0); + + // TEST 2 + // This time we will do the same thing, connect two pipes, + // one of which will succeed in connecting to a bound + // receiver, the other of which will fail. However, we will + // also set the delay attach on connect flag, which should + // cause the pipe attachment to be delayed until the connection + // succeeds. + context = zmq_ctx_new(); + + // Bind the valid socket + to = zmq_socket (context, ZMQ_PULL); + assert (to); + rc = zmq_bind (to, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + val = 0; + rc = zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof(val)); + assert (rc == 0); + + // Create a socket pushing to two endpoints - all messages should arrive. + from = zmq_socket (context, ZMQ_PUSH); + assert (from); + + val = 0; + rc = zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof(val)); + assert (rc == 0); + + // Set the key flag + val = 1; + rc = zmq_setsockopt (from, ZMQ_IMMEDIATE, &val, sizeof(val)); + assert (rc == 0); + + // Connect to the invalid socket + rc = zmq_connect (from, "tcp://localhost:5561"); + assert (rc == 0); + // Connect to the valid socket + rc = zmq_connect (from, "tcp://localhost:5560"); + assert (rc == 0); + + // Send 10 messages, all should be routed to the connected pipe + for (int i = 0; i < 10; ++i) { + rc = zmq_send (from, "Hello", 5, 0); + assert (rc == 5); + } + rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + seen = 0; + while (true) { + rc = zmq_recv (to, &buffer, sizeof (buffer), 0); + if (rc == -1) + break; // Break when we didn't get a message + seen++; + } + assert (seen == 10); + + rc = zmq_close (from); + assert (rc == 0); + + rc = zmq_close (to); + assert (rc == 0); + + rc = zmq_ctx_term (context); + assert (rc == 0); + + // TEST 3 + // This time we want to validate that the same blocking behaviour + // occurs with an existing connection that is broken. We will send + // messages to a connected pipe, disconnect and verify the messages + // block. Then we reconnect and verify messages flow again. + context = zmq_ctx_new (); + + void *backend = zmq_socket (context, ZMQ_DEALER); + assert (backend); + void *frontend = zmq_socket (context, ZMQ_DEALER); + assert (frontend); + int zero = 0; + rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)); + assert (rc == 0); + rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero)); + assert (rc == 0); + + // Frontend connects to backend using IMMEDIATE + int on = 1; + rc = zmq_setsockopt (frontend, ZMQ_IMMEDIATE, &on, sizeof (on)); + assert (rc == 0); + rc = zmq_bind (backend, "tcp://127.0.0.1:5560"); + assert (rc == 0); + rc = zmq_connect (frontend, "tcp://localhost:5560"); + assert (rc == 0); + + // Ping backend to frontend so we know when the connection is up + rc = zmq_send (backend, "Hello", 5, 0); + assert (rc == 5); + rc = zmq_recv (frontend, buffer, 255, 0); + assert (rc == 5); + + // Send message from frontend to backend + rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT); + assert (rc == 5); + + rc = zmq_close (backend); + assert (rc == 0); + + // Give time to process disconnect + msleep (SETTLE_TIME); + + // Send a message, should fail + rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT); + assert (rc == -1); + + // Recreate backend socket + backend = zmq_socket (context, ZMQ_DEALER); + assert (backend); + rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero)); + assert (rc == 0); + rc = zmq_bind (backend, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Ping backend to frontend so we know when the connection is up + rc = zmq_send (backend, "Hello", 5, 0); + assert (rc == 5); + rc = zmq_recv (frontend, buffer, 255, 0); + assert (rc == 5); + + // After the reconnect, should succeed + rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT); + assert (rc == 5); + + rc = zmq_close (backend); + assert (rc == 0); + + rc = zmq_close (frontend); + assert (rc == 0); + + rc = zmq_ctx_term (context); + assert (rc == 0); +} diff --git a/tests/test_inproc_connect.cpp b/tests/test_inproc_connect.cpp new file mode 100644 index 0000000..0c3de45 --- /dev/null +++ b/tests/test_inproc_connect.cpp @@ -0,0 +1,428 @@ +/* + Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +static void pusher (void *ctx) +{ + // Connect first + void *connectSocket = zmq_socket (ctx, ZMQ_PAIR); + assert (connectSocket); + int rc = zmq_connect (connectSocket, "inproc://a"); + assert (rc == 0); + + // Queue up some data + rc = zmq_send_const (connectSocket, "foobar", 6, 0); + assert (rc == 6); + + // Cleanup + rc = zmq_close (connectSocket); + assert (rc == 0); +} + +static void simult_conn (void *payload) +{ + // Pull out arguments - context followed by endpoint string + void* ctx = (void*)((void**)payload)[0]; + char* endpt = (char*)((void**)payload)[1]; + + // Connect + void *connectSocket = zmq_socket (ctx, ZMQ_SUB); + assert (connectSocket); + int rc = zmq_connect (connectSocket, endpt); + assert (rc == 0); + + // Cleanup + rc = zmq_close (connectSocket); + assert (rc == 0); +} + +static void simult_bind (void *payload) +{ + // Pull out arguments - context followed by endpoint string + void* ctx = (void*)((void**)payload)[0]; + char* endpt = (char*)((void**)payload)[1]; + + // Bind + void *bindSocket = zmq_socket (ctx, ZMQ_PUB); + assert (bindSocket); + int rc = zmq_bind (bindSocket, endpt); + assert (rc == 0); + + // Cleanup + rc = zmq_close (bindSocket); + assert (rc == 0); +} + +void test_bind_before_connect() +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Bind first + void *bindSocket = zmq_socket (ctx, ZMQ_PAIR); + assert (bindSocket); + int rc = zmq_bind (bindSocket, "inproc://a"); + assert (rc == 0); + + // Now connect + void *connectSocket = zmq_socket (ctx, ZMQ_PAIR); + assert (connectSocket); + rc = zmq_connect (connectSocket, "inproc://a"); + assert (rc == 0); + + // Queue up some data + rc = zmq_send_const (connectSocket, "foobar", 6, 0); + assert (rc == 6); + + // Read pending message + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, bindSocket, 0); + assert (rc == 6); + void *data = zmq_msg_data (&msg); + assert (memcmp ("foobar", data, 6) == 0); + + // Cleanup + rc = zmq_close (connectSocket); + assert (rc == 0); + + rc = zmq_close (bindSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_connect_before_bind() +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Connect first + void *connectSocket = zmq_socket (ctx, ZMQ_PAIR); + assert (connectSocket); + int rc = zmq_connect (connectSocket, "inproc://a"); + assert (rc == 0); + + // Queue up some data + rc = zmq_send_const (connectSocket, "foobar", 6, 0); + assert (rc == 6); + + // Now bind + void *bindSocket = zmq_socket (ctx, ZMQ_PAIR); + assert (bindSocket); + rc = zmq_bind (bindSocket, "inproc://a"); + assert (rc == 0); + + // Read pending message + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, bindSocket, 0); + assert (rc == 6); + void *data = zmq_msg_data (&msg); + assert (memcmp ("foobar", data, 6) == 0); + + // Cleanup + rc = zmq_close (connectSocket); + assert (rc == 0); + + rc = zmq_close (bindSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_connect_before_bind_pub_sub() +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Connect first + void *connectSocket = zmq_socket (ctx, ZMQ_PUB); + assert (connectSocket); + int rc = zmq_connect (connectSocket, "inproc://a"); + assert (rc == 0); + + // Queue up some data, this will be dropped + rc = zmq_send_const (connectSocket, "before", 6, 0); + assert (rc == 6); + + // Now bind + void *bindSocket = zmq_socket (ctx, ZMQ_SUB); + assert (bindSocket); + rc = zmq_setsockopt (bindSocket, ZMQ_SUBSCRIBE, "", 0); + assert (rc == 0); + rc = zmq_bind (bindSocket, "inproc://a"); + assert (rc == 0); + + // Wait for pub-sub connection to happen + msleep (SETTLE_TIME); + + // Queue up some data, this not will be dropped + rc = zmq_send_const (connectSocket, "after", 6, 0); + assert (rc == 6); + + // Read pending message + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, bindSocket, 0); + assert (rc == 6); + void *data = zmq_msg_data (&msg); + assert (memcmp ("after", data, 5) == 0); + + // Cleanup + rc = zmq_close (connectSocket); + assert (rc == 0); + + rc = zmq_close (bindSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_multiple_connects() +{ + const unsigned int no_of_connects = 10; + void *ctx = zmq_ctx_new (); + assert (ctx); + + int rc; + void *connectSocket[no_of_connects]; + + // Connect first + for (unsigned int i = 0; i < no_of_connects; ++i) + { + connectSocket [i] = zmq_socket (ctx, ZMQ_PUSH); + assert (connectSocket [i]); + rc = zmq_connect (connectSocket [i], "inproc://a"); + assert (rc == 0); + + // Queue up some data + rc = zmq_send_const (connectSocket [i], "foobar", 6, 0); + assert (rc == 6); + } + + // Now bind + void *bindSocket = zmq_socket (ctx, ZMQ_PULL); + assert (bindSocket); + rc = zmq_bind (bindSocket, "inproc://a"); + assert (rc == 0); + + for (unsigned int i = 0; i < no_of_connects; ++i) + { + // Read pending message + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, bindSocket, 0); + assert (rc == 6); + void *data = zmq_msg_data (&msg); + assert (memcmp ("foobar", data, 6) == 0); + } + + // Cleanup + for (unsigned int i = 0; i < no_of_connects; ++i) + { + rc = zmq_close (connectSocket [i]); + assert (rc == 0); + } + + rc = zmq_close (bindSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_multiple_threads() +{ + const unsigned int no_of_threads = 30; + void *ctx = zmq_ctx_new (); + assert (ctx); + + int rc; + void *threads [no_of_threads]; + + // Connect first + for (unsigned int i = 0; i < no_of_threads; ++i) + { + threads [i] = zmq_threadstart (&pusher, ctx); + } + + // Now bind + void *bindSocket = zmq_socket (ctx, ZMQ_PULL); + assert (bindSocket); + rc = zmq_bind (bindSocket, "inproc://a"); + assert (rc == 0); + + for (unsigned int i = 0; i < no_of_threads; ++i) + { + // Read pending message + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, bindSocket, 0); + assert (rc == 6); + void *data = zmq_msg_data (&msg); + assert (memcmp ("foobar", data, 6) == 0); + } + + // Cleanup + for (unsigned int i = 0; i < no_of_threads; ++i) + { + zmq_threadclose (threads [i]); + } + + rc = zmq_close (bindSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_simultaneous_connect_bind_threads () +{ + const unsigned int no_of_times = 50; + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *threads[no_of_times*2]; + void *thr_args[no_of_times][2]; + char endpts[no_of_times][20]; + + // Set up thread arguments: context followed by endpoint string + for (unsigned int i = 0; i < no_of_times; ++i) + { + thr_args[i][0] = (void*) ctx; + thr_args[i][1] = (void*) endpts[i]; + sprintf (endpts[i], "inproc://foo_%d", i); + } + + // Spawn all threads as simultaneously as possible + for (unsigned int i = 0; i < no_of_times; ++i) + { + threads[i*2+0] = zmq_threadstart (&simult_conn, (void*)thr_args[i]); + threads[i*2+1] = zmq_threadstart (&simult_bind, (void*)thr_args[i]); + } + + // Close all threads + for (unsigned int i = 0; i < no_of_times; ++i) + { + zmq_threadclose (threads[i*2+0]); + zmq_threadclose (threads[i*2+1]); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +void test_identity() +{ + // Create the infrastructure + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sc = zmq_socket (ctx, ZMQ_DEALER); + assert (sc); + + int rc = zmq_connect (sc, "inproc://a"); + assert (rc == 0); + + void *sb = zmq_socket (ctx, ZMQ_ROUTER); + assert (sb); + + rc = zmq_bind (sb, "inproc://a"); + assert (rc == 0); + + // 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); + + // Identity 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); + + // 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); + + // 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); + + // 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); +} + +void test_connect_only () +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *connectSocket = zmq_socket (ctx, ZMQ_PUSH); + assert (connectSocket); + int rc = zmq_connect (connectSocket, "inproc://a"); + assert (rc == 0); + + rc = zmq_close (connectSocket); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + + test_bind_before_connect (); + test_connect_before_bind (); + test_connect_before_bind_pub_sub (); + test_multiple_connects (); + test_multiple_threads (); + test_simultaneous_connect_bind_threads (); + test_identity (); + test_connect_only (); + + return 0; +} diff --git a/tests/test_invalid_rep.cpp b/tests/test_invalid_rep.cpp new file mode 100644 index 0000000..8f16642 --- /dev/null +++ b/tests/test_invalid_rep.cpp @@ -0,0 +1,88 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + // Create REQ/ROUTER wiring. + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *router_socket = zmq_socket (ctx, ZMQ_ROUTER); + assert (router_socket); + + void *req_socket = zmq_socket (ctx, ZMQ_REQ); + assert (req_socket); + + int linger = 0; + int rc = zmq_setsockopt (router_socket, ZMQ_LINGER, &linger, sizeof (int)); + assert (rc == 0); + rc = zmq_setsockopt (req_socket, ZMQ_LINGER, &linger, sizeof (int)); + assert (rc == 0); + rc = zmq_bind (router_socket, "inproc://hi"); + assert (rc == 0); + rc = zmq_connect (req_socket, "inproc://hi"); + assert (rc == 0); + + // Initial request. + rc = zmq_send (req_socket, "r", 1, 0); + assert (rc == 1); + + // Receive the request. + char addr [32]; + int addr_size; + char bottom [1]; + char body [1]; + addr_size = zmq_recv (router_socket, addr, sizeof (addr), 0); + assert (addr_size >= 0); + rc = zmq_recv (router_socket, bottom, sizeof (bottom), 0); + assert (rc == 0); + rc = zmq_recv (router_socket, body, sizeof (body), 0); + assert (rc == 1); + + // Send invalid reply. + rc = zmq_send (router_socket, addr, addr_size, 0); + assert (rc == addr_size); + + // Send valid reply. + rc = zmq_send (router_socket, addr, addr_size, ZMQ_SNDMORE); + assert (rc == addr_size); + rc = zmq_send (router_socket, bottom, 0, ZMQ_SNDMORE); + assert (rc == 0); + rc = zmq_send (router_socket, "b", 1, 0); + assert (rc == 1); + + // Check whether we've got the valid reply. + rc = zmq_recv (req_socket, body, sizeof (body), 0); + assert (rc == 1); + assert (body [0] == 'b'); + + // Tear down the wiring. + rc = zmq_close (router_socket); + assert (rc == 0); + rc = zmq_close (req_socket); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0; +} + diff --git a/tests/test_iov.cpp b/tests/test_iov.cpp new file mode 100644 index 0000000..718b318 --- /dev/null +++ b/tests/test_iov.cpp @@ -0,0 +1,106 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +// XSI vector I/O +#if defined ZMQ_HAVE_UIO +#include +#else +struct iovec { + void *iov_base; + size_t iov_len; +}; +#endif + +void do_check(void* sb, void* sc, unsigned int msgsz) +{ + setup_test_environment(); + int rc; + int sum =0; + for (int i = 0; i < 10; i++) + { + zmq_msg_t msg; + zmq_msg_init_size(&msg, msgsz); + void * data = zmq_msg_data(&msg); + memcpy(data,&i, sizeof(int)); + rc = zmq_msg_send(&msg,sc,i==9 ? 0 :ZMQ_SNDMORE); + assert (rc == (int)msgsz); + zmq_msg_close(&msg); + sum += i; + } + + struct iovec ibuffer[32] ; + memset(&ibuffer[0], 0, sizeof(ibuffer)); + + size_t count = 10; + rc = zmq_recviov(sb,&ibuffer[0],&count,0); + assert (rc == 10); + + int rsum=0; + for(;count;--count) + { + int v; + memcpy(&v,ibuffer[count-1].iov_base,sizeof(int)); + rsum += v; + assert(ibuffer[count-1].iov_len == msgsz); + // free up the memory + free(ibuffer[count-1].iov_base); + } + + assert ( sum == rsum ); + +} + +int main (void) +{ + void *ctx = zmq_ctx_new (); + assert (ctx); + int rc; + + void *sb = zmq_socket (ctx, ZMQ_PULL); + assert (sb); + + rc = zmq_bind (sb, "inproc://a"); + assert (rc == 0); + + msleep (SETTLE_TIME); + void *sc = zmq_socket (ctx, ZMQ_PUSH); + + rc = zmq_connect (sc, "inproc://a"); + assert (rc == 0); + + + // message bigger than vsm max + do_check(sb,sc,100); + + // message smaller than vsm max + do_check(sb,sc,10); + + rc = zmq_close (sc); + assert (rc == 0); + + rc = zmq_close (sb); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0; +} diff --git a/tests/test_issue_566.cpp b/tests/test_issue_566.cpp new file mode 100644 index 0000000..068f45b --- /dev/null +++ b/tests/test_issue_566.cpp @@ -0,0 +1,85 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +// Issue 566 describes a problem in libzmq v4.0.0 where a dealer to router +// connection would fail randomly. The test works when the two sockets are +// on the same context, and failed when they were on separate contexts. +// Fixed by https://github.com/zeromq/libzmq/commit/be25cf. + +int main (void) +{ + setup_test_environment(); + + void *ctx1 = zmq_ctx_new (); + assert (ctx1); + + void *ctx2 = zmq_ctx_new (); + assert (ctx2); + + void *router = zmq_socket (ctx1, ZMQ_ROUTER); + int on = 1; + int rc = zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY, &on, sizeof (on)); + assert (rc == 0); + rc = zmq_bind (router, "tcp://127.0.0.1:5555"); + assert (rc != -1); + + // Repeat often enough to be sure this works as it should + for (int cycle = 0; cycle < 100; cycle++) { + // Create dealer with unique explicit identity + // We assume the router learns this out-of-band + void *dealer = zmq_socket (ctx2, ZMQ_DEALER); + char identity [10]; + sprintf (identity, "%09d", cycle); + rc = zmq_setsockopt (dealer, ZMQ_IDENTITY, identity, 10); + assert (rc == 0); + int rcvtimeo = 1000; + rc = zmq_setsockopt (dealer, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int)); + assert (rc == 0); + rc = zmq_connect (dealer, "tcp://127.0.0.1:5555"); + assert (rc == 0); + + // Router will try to send to dealer, at short intervals. + // It typically takes 2-5 msec for the connection to establish + // on a loopback interface, but we'll allow up to one second + // before failing the test (e.g. for running on a debugger or + // a very slow system). + for (int attempt = 0; attempt < 500; attempt++) { + zmq_poll (0, 0, 2); + rc = zmq_send (router, identity, 10, ZMQ_SNDMORE); + if (rc == -1 && errno == EHOSTUNREACH) + continue; + assert (rc == 10); + rc = zmq_send (router, "HELLO", 5, 0); + assert (rc == 5); + break; + } + uint8_t buffer [5]; + rc = zmq_recv (dealer, buffer, 5, 0); + assert (rc == 5); + assert (memcmp (buffer, "HELLO", 5) == 0); + close_zero_linger (dealer); + } + zmq_close (router); + zmq_ctx_destroy (ctx1); + zmq_ctx_destroy (ctx2); + + return 0; +} diff --git a/tests/test_last_endpoint.cpp b/tests/test_last_endpoint.cpp new file mode 100644 index 0000000..2343c75 --- /dev/null +++ b/tests/test_last_endpoint.cpp @@ -0,0 +1,56 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +static void do_bind_and_verify (void *s, const char *endpoint) +{ + int rc = zmq_bind (s, endpoint); + assert (rc == 0); + char reported [255]; + size_t size = 255; + rc = zmq_getsockopt (s, ZMQ_LAST_ENDPOINT, reported, &size); + assert (rc == 0 && strcmp (reported, endpoint) == 0); +} + +int main (void) +{ + setup_test_environment(); + // Create the infrastructure + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_ROUTER); + assert (sb); + int val = 0; + int rc = zmq_setsockopt (sb, ZMQ_LINGER, &val, sizeof (val)); + assert (rc == 0); + + do_bind_and_verify (sb, "tcp://127.0.0.1:5560"); + do_bind_and_verify (sb, "tcp://127.0.0.1:5561"); + + rc = zmq_close (sb); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} + diff --git a/tests/test_many_sockets.cpp b/tests/test_many_sockets.cpp new file mode 100644 index 0000000..e98a030 --- /dev/null +++ b/tests/test_many_sockets.cpp @@ -0,0 +1,90 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" +#include +#include +#include +#include + +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); + std::vector sockets; + + while (true) { + void *socket = zmq_socket (ctx, ZMQ_PAIR); + if (!socket) + break; + sockets.push_back (socket); + } + assert ((int) sockets.size () < no_of_sockets); + + // 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); + } + // Clean up. + for (unsigned int i = 0; i < sockets.size (); ++i) + zmq_close (sockets [i]); + + zmq_ctx_destroy (ctx); +} + +void test_zmq_default_max () +{ + // Keep allocating sockets until we hit the default limit + void *ctx = zmq_ctx_new (); + std::vector sockets; + + while (true) { + void *socket = zmq_socket (ctx, 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); + + // 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); + } + + // Clean up + for (unsigned int i = 0; i < sockets.size (); ++i) + zmq_close (sockets [i]); + + zmq_ctx_destroy (ctx); +} + +int main (void) +{ + setup_test_environment (); + + test_system_max (); + test_zmq_default_max (); + + return 0; +} diff --git a/tests/test_monitor.cpp b/tests/test_monitor.cpp new file mode 100644 index 0000000..8437619 --- /dev/null +++ b/tests/test_monitor.cpp @@ -0,0 +1,272 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +// REQ socket events handled +static int req_socket_events; +// 2nd REQ socket events handled +static int req2_socket_events; +// REP socket events handled +static int rep_socket_events; + +std::string addr ; + +static bool read_msg(void* s, zmq_event_t& event, std::string& ep) +{ + int rc ; + zmq_msg_t msg1; // binary part + zmq_msg_init (&msg1); + zmq_msg_t msg2; // address part + zmq_msg_init (&msg2); + rc = zmq_msg_recv (&msg1, s, 0); + if (rc == -1 && zmq_errno() == ETERM) + return true ; + + assert (rc != -1); + assert (zmq_msg_more(&msg1) != 0); + rc = zmq_msg_recv (&msg2, s, 0); + if (rc == -1 && zmq_errno() == ETERM) + return true; + + assert (rc != -1); + assert (zmq_msg_more(&msg2) == 0); + // copy binary data to event struct + const char* data = (char*)zmq_msg_data(&msg1); + memcpy(&event.event, data, sizeof(event.event)); + memcpy(&event.value, data+sizeof(event.event), sizeof(event.value)); + // copy address part + ep = std::string((char*)zmq_msg_data(&msg2), zmq_msg_size(&msg2)); + + if (event.event == ZMQ_EVENT_MONITOR_STOPPED) + return true; + + return false; +} + + +// REQ socket monitor thread +static void req_socket_monitor (void *ctx) +{ + zmq_event_t event; + std::string ep ; + int rc; + + void *s = zmq_socket (ctx, ZMQ_PAIR); + assert (s); + + rc = zmq_connect (s, "inproc://monitor.req"); + assert (rc == 0); + while (!read_msg(s, event, ep)) { + assert (ep == addr); + switch (event.event) { + case ZMQ_EVENT_CONNECTED: + assert (event.value > 0); + req_socket_events |= ZMQ_EVENT_CONNECTED; + req2_socket_events |= ZMQ_EVENT_CONNECTED; + break; + case ZMQ_EVENT_CONNECT_DELAYED: + assert (event.value != 0); + req_socket_events |= ZMQ_EVENT_CONNECT_DELAYED; + break; + case ZMQ_EVENT_CLOSE_FAILED: + assert (event.value != 0); + req_socket_events |= ZMQ_EVENT_CLOSE_FAILED; + break; + case ZMQ_EVENT_CLOSED: + assert (event.value != 0); + req_socket_events |= ZMQ_EVENT_CLOSED; + break; + case ZMQ_EVENT_DISCONNECTED: + assert (event.value != 0); + req_socket_events |= ZMQ_EVENT_DISCONNECTED; + break; + } + } + zmq_close (s); +} + +// 2nd REQ socket monitor thread +static void req2_socket_monitor (void *ctx) +{ + zmq_event_t event; + std::string ep ; + int rc; + + void *s = zmq_socket (ctx, ZMQ_PAIR); + assert (s); + + rc = zmq_connect (s, "inproc://monitor.req2"); + assert (rc == 0); + while (!read_msg(s, event, ep)) { + assert (ep == addr); + switch (event.event) { + case ZMQ_EVENT_CONNECTED: + assert (event.value > 0); + req2_socket_events |= ZMQ_EVENT_CONNECTED; + break; + case ZMQ_EVENT_CLOSED: + assert (event.value != 0); + req2_socket_events |= ZMQ_EVENT_CLOSED; + break; + } + } + zmq_close (s); +} + +// REP socket monitor thread +static void rep_socket_monitor (void *ctx) +{ + zmq_event_t event; + std::string ep ; + int rc; + + void *s = zmq_socket (ctx, ZMQ_PAIR); + assert (s); + + rc = zmq_connect (s, "inproc://monitor.rep"); + assert (rc == 0); + while (!read_msg(s, event, ep)) { + assert (ep == addr); + switch (event.event) { + case ZMQ_EVENT_LISTENING: + assert (event.value > 0); + rep_socket_events |= ZMQ_EVENT_LISTENING; + break; + case ZMQ_EVENT_ACCEPTED: + assert (event.value > 0); + rep_socket_events |= ZMQ_EVENT_ACCEPTED; + break; + case ZMQ_EVENT_CLOSE_FAILED: + assert (event.value != 0); + rep_socket_events |= ZMQ_EVENT_CLOSE_FAILED; + break; + case ZMQ_EVENT_CLOSED: + assert (event.value != 0); + rep_socket_events |= ZMQ_EVENT_CLOSED; + break; + case ZMQ_EVENT_DISCONNECTED: + assert (event.value != 0); + rep_socket_events |= ZMQ_EVENT_DISCONNECTED; + break; + } + } + zmq_close (s); +} + +int main (void) +{ + setup_test_environment(); + int rc; + void *req; + void *req2; + void *rep; + void* threads [3]; + + addr = "tcp://127.0.0.1:5560"; + + // Create the infrastructure + void *ctx = zmq_ctx_new (); + assert (ctx); + + // REP socket + rep = zmq_socket (ctx, ZMQ_REP); + assert (rep); + + // Assert supported protocols + rc = zmq_socket_monitor (rep, addr.c_str(), 0); + assert (rc == -1); + assert (zmq_errno() == EPROTONOSUPPORT); + + // Deregister monitor + rc = zmq_socket_monitor (rep, NULL, 0); + assert (rc == 0); + + // REP socket monitor, all events + rc = zmq_socket_monitor (rep, "inproc://monitor.rep", ZMQ_EVENT_ALL); + assert (rc == 0); + threads [0] = zmq_threadstart(&rep_socket_monitor, ctx); + + // REQ socket + req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + // REQ socket monitor, all events + rc = zmq_socket_monitor (req, "inproc://monitor.req", ZMQ_EVENT_ALL); + assert (rc == 0); + threads [1] = zmq_threadstart(&req_socket_monitor, ctx); + msleep (SETTLE_TIME); + + // Bind REQ and REP + rc = zmq_bind (rep, addr.c_str()); + assert (rc == 0); + + rc = zmq_connect (req, addr.c_str()); + assert (rc == 0); + + bounce (rep, req); + + // 2nd REQ socket + req2 = zmq_socket (ctx, ZMQ_REQ); + assert (req2); + + // 2nd REQ socket monitor, connected event only + rc = zmq_socket_monitor (req2, "inproc://monitor.req2", ZMQ_EVENT_CONNECTED); + assert (rc == 0); + threads [2] = zmq_threadstart(&req2_socket_monitor, ctx); + + rc = zmq_connect (req2, addr.c_str()); + assert (rc == 0); + + // Close the REP socket + rc = zmq_close (rep); + assert (rc == 0); + + // Allow enough time for detecting error states + msleep (250); + + // Close the REQ socket + rc = zmq_close (req); + assert (rc == 0); + + // Close the 2nd REQ socket + rc = zmq_close (req2); + assert (rc == 0); + + zmq_ctx_term (ctx); + + // Expected REP socket events + assert (rep_socket_events & ZMQ_EVENT_LISTENING); + assert (rep_socket_events & ZMQ_EVENT_ACCEPTED); + assert (rep_socket_events & ZMQ_EVENT_CLOSED); + + // Expected REQ socket events + assert (req_socket_events & ZMQ_EVENT_CONNECTED); + assert (req_socket_events & ZMQ_EVENT_DISCONNECTED); + assert (req_socket_events & ZMQ_EVENT_CLOSED); + + // Expected 2nd REQ socket events + assert (req2_socket_events & ZMQ_EVENT_CONNECTED); + assert (!(req2_socket_events & ZMQ_EVENT_CLOSED)); + + for (unsigned int i = 0; i < 3; ++i) + zmq_threadclose(threads [i]); + + return 0 ; +} diff --git a/tests/test_msg_flags.cpp b/tests/test_msg_flags.cpp new file mode 100644 index 0000000..9bdd9c4 --- /dev/null +++ b/tests/test_msg_flags.cpp @@ -0,0 +1,79 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + // Create the infrastructure + void *ctx = zmq_ctx_new (); + assert (ctx); + + 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); + + // 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); + + // Identity 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); + + // 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); + + // 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); + + // 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 ; +} + diff --git a/tests/test_pair_inproc.cpp b/tests/test_pair_inproc.cpp new file mode 100644 index 0000000..4eac5f5 --- /dev/null +++ b/tests/test_pair_inproc.cpp @@ -0,0 +1,71 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_PAIR); + assert (sb); + int rc = zmq_bind (sb, "inproc://a"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_PAIR); + assert (sc); + rc = zmq_connect (sc, "inproc://a"); + assert (rc == 0); + + bounce (sb, sc); + + // Test zmq_send_const + rc = zmq_send_const (sb, "foo", 3, ZMQ_SNDMORE); + assert (rc == 3); + rc = zmq_send_const (sb, "foobar", 6, 0); + assert (rc == 6); + + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, sc, 0); + assert (rc == 3); + assert (zmq_msg_size (&msg) == 3); + void* data = zmq_msg_data (&msg); + assert (memcmp ("foo", data, 3) == 0); + rc = zmq_msg_recv (&msg, sc, 0); + assert (rc == 6); + data = zmq_msg_data (&msg); + assert (memcmp ("foobar", data, 6) == 0); + + // 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 ; +} diff --git a/tests/test_pair_ipc.cpp b/tests/test_pair_ipc.cpp new file mode 100644 index 0000000..31b534b --- /dev/null +++ b/tests/test_pair_ipc.cpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_PAIR); + assert (sb); + int rc = zmq_bind (sb, "ipc:///tmp/tester"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_PAIR); + assert (sc); + rc = zmq_connect (sc, "ipc:///tmp/tester"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_pair_tcp.cpp b/tests/test_pair_tcp.cpp new file mode 100644 index 0000000..f7e5aee --- /dev/null +++ b/tests/test_pair_tcp.cpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_PAIR); + assert (sb); + int rc = zmq_bind (sb, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_PAIR); + assert (sc); + rc = zmq_connect (sc, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_probe_router.cpp b/tests/test_probe_router.cpp new file mode 100644 index 0000000..7188457 --- /dev/null +++ b/tests/test_probe_router.cpp @@ -0,0 +1,72 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Create server and bind to endpoint + void *server = zmq_socket (ctx, ZMQ_ROUTER); + assert (server); + int rc = zmq_bind (server, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Create client and connect to server, doing a probe + void *client = zmq_socket (ctx, ZMQ_ROUTER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_IDENTITY, "X", 1); + assert (rc == 0); + int probe = 1; + rc = zmq_setsockopt (client, ZMQ_PROBE_ROUTER, &probe, sizeof (probe)); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:5560"); + assert (rc == 0); + + // We expect an identity=X + empty message from client + unsigned char buffer [255]; + rc = zmq_recv (server, buffer, 255, 0); + assert (rc == 1); + assert (buffer [0] == 'X'); + rc = zmq_recv (server, buffer, 255, 0); + assert (rc == 0); + + // Send a message to client now + rc = zmq_send (server, "X", 1, ZMQ_SNDMORE); + assert (rc == 1); + rc = zmq_send (server, "Hello", 5, 0); + assert (rc == 5); + + rc = zmq_recv (client, buffer, 255, 0); + assert (rc == 5); + + rc = zmq_close (server); + assert (rc == 0); + + rc = zmq_close (client); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_req_correlate.cpp b/tests/test_req_correlate.cpp new file mode 100644 index 0000000..344926c --- /dev/null +++ b/tests/test_req_correlate.cpp @@ -0,0 +1,177 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + void *router = zmq_socket (ctx, ZMQ_ROUTER); + assert (router); + + int enabled = 1; + int rc = zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int)); + assert (rc == 0); + + int rcvtimeo = 100; + rc = zmq_setsockopt (req, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (req, "tcp://localhost:5555"); + assert (rc == 0); + + rc = zmq_bind (router, "tcp://127.0.0.1:5555"); + assert (rc == 0); + + // Send a multi-part request. + s_send_seq (req, "ABC", "DEF", SEQ_END); + + zmq_msg_t msg; + zmq_msg_init (&msg); + + // Receive peer identity + rc = zmq_msg_recv (&msg, router, 0); + assert (rc != -1); + assert (zmq_msg_size (&msg) > 0); + zmq_msg_t peer_id_msg; + zmq_msg_init (&peer_id_msg); + zmq_msg_copy (&peer_id_msg, &msg); + + int more = 0; + size_t more_size = sizeof (more); + rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size); + assert (rc == 0); + assert (more); + + // Receive request id 1 + rc = zmq_msg_recv (&msg, router, 0); + assert (rc != -1); + assert (zmq_msg_size (&msg) == sizeof(uint32_t)); + uint32_t req_id = *static_cast (zmq_msg_data (&msg)); + zmq_msg_t req_id_msg; + zmq_msg_init (&req_id_msg); + zmq_msg_copy (&req_id_msg, &msg); + + more = 0; + more_size = sizeof (more); + rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size); + assert (rc == 0); + assert (more); + + // Receive the rest. + s_recv_seq (router, 0, "ABC", "DEF", SEQ_END); + + // Send back a bad reply: correct req id + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_copy (&msg, &req_id_msg); + rc = zmq_msg_send (&msg, router, 0); + assert (rc != -1); + + // Send back a bad reply: wrong req id + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + uint32_t bad_req_id = req_id + 1; + zmq_msg_init_data (&msg, &bad_req_id, sizeof (uint32_t), NULL, NULL); + rc = zmq_msg_send (&msg, router, 0); + assert (rc != -1); + + // Send back a bad reply: correct req id, 0 + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_copy (&msg, &req_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, 0, SEQ_END); + + // Send back a bad reply: correct req id, garbage + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_copy (&msg, &req_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, "FOO", SEQ_END); + + // Send back a bad reply: wrong req id, 0 + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_init_data (&msg, &bad_req_id, sizeof (uint32_t), NULL, NULL); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, 0, SEQ_END); + + // Send back a bad reply: correct req id, garbage, data + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_copy (&msg, &req_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, "FOO", "DATA", SEQ_END); + + // Send back a bad reply: wrong req id, 0, data + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_init_data (&msg, &bad_req_id, sizeof (uint32_t), NULL, NULL); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, 0, "DATA", SEQ_END); + + // Send back a good reply. + zmq_msg_copy (&msg, &peer_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + zmq_msg_copy (&msg, &req_id_msg); + rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, 0, "GHI", SEQ_END); + + // Receive reply. If any of the other messages got through, we wouldn't see + // this particular data. + s_recv_seq (req, "GHI", SEQ_END); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + rc = zmq_msg_close (&peer_id_msg); + assert (rc == 0); + + rc = zmq_msg_close (&req_id_msg); + assert (rc == 0); + + close_zero_linger (req); + close_zero_linger (router); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0; +} diff --git a/tests/test_req_relaxed.cpp b/tests/test_req_relaxed.cpp new file mode 100644 index 0000000..7970ed4 --- /dev/null +++ b/tests/test_req_relaxed.cpp @@ -0,0 +1,116 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + int enabled = 1; + int rc = zmq_setsockopt (req, ZMQ_REQ_RELAXED, &enabled, sizeof (int)); + assert (rc == 0); + + rc = zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int)); + assert (rc == 0); + + rc = zmq_bind (req, "tcp://127.0.0.1:5555"); + assert (rc == 0); + + const size_t services = 5; + void *rep [services]; + for (size_t peer = 0; peer < services; peer++) { + rep [peer] = zmq_socket (ctx, ZMQ_REP); + assert (rep [peer]); + + int timeout = 100; + rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (rep [peer], "tcp://localhost:5555"); + assert (rc == 0); + } + // We have to give the connects time to finish otherwise the requests + // will not properly round-robin. We could alternatively connect the + // REQ sockets to the REP sockets. + msleep (SETTLE_TIME); + + // Case 1: Second send() before a reply arrives in a pipe. + + // Send a request, ensure it arrives, don't send a reply + s_send_seq (req, "A", "B", SEQ_END); + s_recv_seq (rep [0], "A", "B", SEQ_END); + + // Send another request on the REQ socket + s_send_seq (req, "C", "D", SEQ_END); + s_recv_seq (rep [1], "C", "D", SEQ_END); + + // Send a reply to the first request - that should be discarded by the REQ + s_send_seq (rep [0], "WRONG", SEQ_END); + + // Send the expected reply + s_send_seq (rep [1], "OK", SEQ_END); + s_recv_seq (req, "OK", SEQ_END); + + + // Another standard req-rep cycle, just to check + s_send_seq (req, "E", SEQ_END); + s_recv_seq (rep [2], "E", SEQ_END); + s_send_seq (rep [2], "F", "G", SEQ_END); + s_recv_seq (req, "F", "G", SEQ_END); + + + // Case 2: Second send() after a reply is already in a pipe on the REQ. + + // Send a request, ensure it arrives, send a reply + s_send_seq (req, "H", SEQ_END); + s_recv_seq (rep [3], "H", SEQ_END); + s_send_seq (rep [3], "BAD", SEQ_END); + + // Wait for message to be there. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + // Without receiving that reply, send another request on the REQ socket + s_send_seq (req, "I", SEQ_END); + s_recv_seq (rep [4], "I", SEQ_END); + + // Send the expected reply + s_send_seq (rep [4], "GOOD", SEQ_END); + s_recv_seq (req, "GOOD", SEQ_END); + + + close_zero_linger (req); + for (size_t peer = 0; peer < services; peer++) + close_zero_linger (rep [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_reqrep_device.cpp b/tests/test_reqrep_device.cpp new file mode 100644 index 0000000..9eb1db1 --- /dev/null +++ b/tests/test_reqrep_device.cpp @@ -0,0 +1,135 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Create a req/rep device. + void *dealer = zmq_socket (ctx, ZMQ_DEALER); + assert (dealer); + int rc = zmq_bind (dealer, "tcp://127.0.0.1:5560"); + assert (rc == 0); + void *router = zmq_socket (ctx, ZMQ_ROUTER); + assert (router); + rc = zmq_bind (router, "tcp://127.0.0.1:5561"); + assert (rc == 0); + + // Create a worker. + void *rep = zmq_socket (ctx, ZMQ_REP); + assert (rep); + rc = zmq_connect (rep, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Create a client. + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + rc = zmq_connect (req, "tcp://127.0.0.1:5561"); + assert (rc == 0); + + // Send a request. + rc = zmq_send (req, "ABC", 3, ZMQ_SNDMORE); + assert (rc == 3); + rc = zmq_send (req, "DEF", 3, 0); + assert (rc == 3); + + // Pass the request through the device. + for (int i = 0; i != 4; i++) { + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, router, 0); + assert (rc >= 0); + int rcvmore; + size_t sz = sizeof (rcvmore); + rc = zmq_getsockopt (router, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + rc = zmq_msg_send (&msg, dealer, rcvmore? ZMQ_SNDMORE: 0); + assert (rc >= 0); + } + + // Receive the request. + char buff [3]; + rc = zmq_recv (rep, buff, 3, 0); + assert (rc == 3); + assert (memcmp (buff, "ABC", 3) == 0); + int rcvmore; + size_t sz = sizeof (rcvmore); + rc = zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + assert (rcvmore); + rc = zmq_recv (rep, buff, 3, 0); + assert (rc == 3); + assert (memcmp (buff, "DEF", 3) == 0); + rc = zmq_getsockopt (rep, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + assert (!rcvmore); + + // Send the reply. + rc = zmq_send (rep, "GHI", 3, ZMQ_SNDMORE); + assert (rc == 3); + rc = zmq_send (rep, "JKL", 3, 0); + assert (rc == 3); + + // Pass the reply through the device. + for (int i = 0; i != 4; i++) { + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + rc = zmq_msg_recv (&msg, dealer, 0); + assert (rc >= 0); + int rcvmore; + rc = zmq_getsockopt (dealer, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + rc = zmq_msg_send (&msg, router, rcvmore? ZMQ_SNDMORE: 0); + assert (rc >= 0); + } + + // Receive the reply. + rc = zmq_recv (req, buff, 3, 0); + assert (rc == 3); + assert (memcmp (buff, "GHI", 3) == 0); + rc = zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + assert (rcvmore); + rc = zmq_recv (req, buff, 3, 0); + assert (rc == 3); + assert (memcmp (buff, "JKL", 3) == 0); + rc = zmq_getsockopt (req, ZMQ_RCVMORE, &rcvmore, &sz); + assert (rc == 0); + assert (!rcvmore); + + // Clean up. + rc = zmq_close (req); + assert (rc == 0); + rc = zmq_close (rep); + assert (rc == 0); + rc = zmq_close (router); + assert (rc == 0); + rc = zmq_close (dealer); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_reqrep_inproc.cpp b/tests/test_reqrep_inproc.cpp new file mode 100644 index 0000000..addf2f7 --- /dev/null +++ b/tests/test_reqrep_inproc.cpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_REP); + assert (sb); + int rc = zmq_bind (sb, "inproc://a"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_REQ); + assert (sc); + rc = zmq_connect (sc, "inproc://a"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_reqrep_ipc.cpp b/tests/test_reqrep_ipc.cpp new file mode 100644 index 0000000..f05f0e0 --- /dev/null +++ b/tests/test_reqrep_ipc.cpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_REP); + assert (sb); + int rc = zmq_bind (sb, "ipc:///tmp/tester"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_REQ); + assert (sc); + rc = zmq_connect (sc, "ipc:///tmp/tester"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_reqrep_tcp.cpp b/tests/test_reqrep_tcp.cpp new file mode 100644 index 0000000..275f753 --- /dev/null +++ b/tests/test_reqrep_tcp.cpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *sb = zmq_socket (ctx, ZMQ_REP); + assert (sb); + int rc = zmq_bind (sb, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + void *sc = zmq_socket (ctx, ZMQ_REQ); + assert (sc); + rc = zmq_connect (sc, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + 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 ; +} diff --git a/tests/test_router_mandatory.cpp b/tests/test_router_mandatory.cpp new file mode 100644 index 0000000..dcc6114 --- /dev/null +++ b/tests/test_router_mandatory.cpp @@ -0,0 +1,81 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + void *router = zmq_socket (ctx, ZMQ_ROUTER); + assert (router); + + int rc = zmq_bind (router, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Send a message to an unknown peer with the default setting + // This will not report any error + rc = zmq_send (router, "UNKNOWN", 7, ZMQ_SNDMORE); + assert (rc == 7); + rc = zmq_send (router, "DATA", 4, 0); + assert (rc == 4); + + // Send a message to an unknown peer with mandatory routing + // This will fail + int mandatory = 1; + rc = zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY, &mandatory, sizeof (mandatory)); + assert (rc == 0); + rc = zmq_send (router, "UNKNOWN", 7, ZMQ_SNDMORE); + assert (rc == -1 && errno == EHOSTUNREACH); + + // Create dealer called "X" and connect it to our router + void *dealer = zmq_socket (ctx, ZMQ_DEALER); + assert (dealer); + rc = zmq_setsockopt (dealer, ZMQ_IDENTITY, "X", 1); + assert (rc == 0); + rc = zmq_connect (dealer, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Get message from dealer to know when connection is ready + char buffer [255]; + rc = zmq_send (dealer, "Hello", 5, 0); + assert (rc == 5); + rc = zmq_recv (router, buffer, 255, 0); + assert (rc == 1); + assert (buffer [0] == 'X'); + + // Send a message to connected dealer now + // It should work + rc = zmq_send (router, "X", 1, ZMQ_SNDMORE); + assert (rc == 1); + rc = zmq_send (router, "Hello", 5, 0); + assert (rc == 5); + + rc = zmq_close (router); + assert (rc == 0); + + rc = zmq_close (dealer); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_router_raw_empty.cpp b/tests/test_router_raw_empty.cpp new file mode 100644 index 0000000..83dc10c --- /dev/null +++ b/tests/test_router_raw_empty.cpp @@ -0,0 +1,65 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) { + setup_test_environment(); + void *ctx = zmq_ctx_new(); + assert(ctx); + + void *router = zmq_socket(ctx, ZMQ_ROUTER); + assert(router); + void *dealer = zmq_socket(ctx, ZMQ_DEALER); + assert(dealer); + + int one=1; + int rc = zmq_setsockopt(router, ZMQ_ROUTER_RAW, &one, sizeof(int)); + assert(rc >= 0); + rc = zmq_setsockopt(router, ZMQ_ROUTER_MANDATORY, &one, sizeof(int)); + assert(rc >= 0); + + rc = zmq_bind(router, "tcp://127.0.0.1:5555"); + rc = zmq_connect(dealer, "tcp://127.0.0.1:5555"); + zmq_send(dealer, "", 0, 0); + + + zmq_msg_t ident, empty; + zmq_msg_init(&ident); + rc = zmq_msg_recv(&ident, router, 0); + assert(rc >= 0); + rc = zmq_msg_init_data(&empty, (void*)"", 0, NULL, NULL); + assert(rc >= 0); + + rc = zmq_msg_send(&ident, router, ZMQ_SNDMORE); + assert(rc >= 0); + rc = zmq_msg_close(&ident); + assert(rc >= 0); + + rc = zmq_msg_send(&empty, router, 0); + assert(rc >= 0); + + // This close used to fail with Bad Address + rc = zmq_msg_close(&empty); + assert(rc >= 0); + + close_zero_linger(dealer); + close_zero_linger(router); + zmq_ctx_term(ctx); +} diff --git a/tests/test_security_curve.cpp b/tests/test_security_curve.cpp new file mode 100644 index 0000000..a24466f --- /dev/null +++ b/tests/test_security_curve.cpp @@ -0,0 +1,231 @@ +/* + Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +// We'll generate random test keys at startup +static char client_public [40]; +static char client_secret [40]; +static char server_public [40]; +static char server_secret [40]; + +// -------------------------------------------------------------------------- +// This methods receives and validates ZAP requestes (allowing or denying +// each client connection). + +static void zap_handler (void *handler) +{ + // Process ZAP requests forever + while (true) { + char *version = s_recv (handler); + if (!version) + break; // Terminating + + char *sequence = s_recv (handler); + char *domain = s_recv (handler); + char *address = s_recv (handler); + char *identity = s_recv (handler); + char *mechanism = s_recv (handler); + uint8_t client_key [32]; + int size = zmq_recv (handler, client_key, 32, 0); + assert (size == 32); + + char client_key_text [40]; + zmq_z85_encode (client_key_text, client_key, 32); + + assert (streq (version, "1.0")); + assert (streq (mechanism, "CURVE")); + assert (streq (identity, "IDENT")); + + s_sendmore (handler, version); + s_sendmore (handler, sequence); + + if (streq (client_key_text, client_public)) { + s_sendmore (handler, "200"); + s_sendmore (handler, "OK"); + s_sendmore (handler, "anonymous"); + s_send (handler, ""); + } + else { + s_sendmore (handler, "400"); + s_sendmore (handler, "Invalid client public key"); + s_sendmore (handler, ""); + s_send (handler, ""); + } + free (version); + free (sequence); + free (domain); + free (address); + free (identity); + free (mechanism); + } + zmq_close (handler); +} + + +int main (void) +{ +#ifndef HAVE_LIBSODIUM + printf ("libsodium not installed, skipping CURVE test\n"); + return 0; +#endif + + // Generate new keypairs for this test + int rc = zmq_curve_keypair (client_public, client_secret); + assert (rc == 0); + rc = zmq_curve_keypair (server_public, server_secret); + assert (rc == 0); + + setup_test_environment (); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // 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); + 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_CURVE_SERVER, &as_server, sizeof (int)); + assert (rc == 0); + rc = zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 40); + assert (rc == 0); + rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6); + assert (rc == 0); + rc = zmq_bind (server, "tcp://127.0.0.1:9998"); + assert (rc == 0); + + // Check CURVE security with valid credentials + void *client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + bounce (server, client); + rc = zmq_close (client); + assert (rc == 0); + + // Check CURVE security with a garbage server key + // This will be caught by the curve_server class, not passed to ZAP + char garbage_key [] = "0000111122223333444455556666777788889999"; + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, garbage_key, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check CURVE security with a garbage client public key + // This will be caught by the curve_server class, not passed to ZAP + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, garbage_key, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check CURVE security with a garbage client secret key + // This will be caught by the curve_server class, not passed to ZAP + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, garbage_key, 40); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check CURVE security with bogus client credentials + // This must be caught by the ZAP handler + char bogus_public [40]; + char bogus_secret [40]; + zmq_curve_keypair (bogus_public, bogus_secret); + + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, bogus_public, 40); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, bogus_secret, 40); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check CURVE security with NULL client credentials + // This must be caught by the curve_server class, not passed to ZAP + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check CURVE security with PLAIN client credentials + // This must be caught by the curve_server class, not passed to ZAP + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, "admin", 5); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, "password", 8); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Shutdown + rc = zmq_close (server); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + // Wait until ZAP handler terminates + zmq_threadclose (zap_thread); + + return 0; +} diff --git a/tests/test_security_null.cpp b/tests/test_security_null.cpp new file mode 100644 index 0000000..8a55632 --- /dev/null +++ b/tests/test_security_null.cpp @@ -0,0 +1,148 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +static void +zap_handler (void *handler) +{ + // Process ZAP requests forever + while (true) { + char *version = s_recv (handler); + if (!version) + break; // Terminating + char *sequence = s_recv (handler); + char *domain = s_recv (handler); + char *address = s_recv (handler); + char *identity = s_recv (handler); + char *mechanism = s_recv (handler); + + assert (streq (version, "1.0")); + assert (streq (mechanism, "NULL")); + + s_sendmore (handler, version); + s_sendmore (handler, sequence); + if (streq (domain, "TEST")) { + s_sendmore (handler, "200"); + s_sendmore (handler, "OK"); + s_sendmore (handler, "anonymous"); + s_send (handler, ""); + } + else { + s_sendmore (handler, "400"); + s_sendmore (handler, "BAD DOMAIN"); + s_sendmore (handler, ""); + s_send (handler, ""); + } + free (version); + free (sequence); + free (domain); + free (address); + free (identity); + free (mechanism); + } + zmq_close (handler); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // 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); + + // We bounce between a binding server and a connecting client + void *server = zmq_socket (ctx, ZMQ_DEALER); + assert (server); + void *client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + + // We first test client/server with no ZAP domain + // Libzmq does not call our ZAP handler, the connect must succeed + rc = zmq_bind (server, "tcp://127.0.0.1:9000"); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9000"); + assert (rc == 0); + bounce (server, client); + zmq_unbind (server, "tcp://127.0.0.1:9000"); + zmq_disconnect (client, "tcp://localhost:9000"); + + // Now define a ZAP domain for the server; this enables + // authentication. We're using the wrong domain so this test + // must fail. + // ************************************************************** + // PH: the following causes libzmq to get confused, so that the + // next step fails. To reproduce, uncomment this block. Note that + // even creating a new client/server socket pair, the behaviour + // does not change. + // ************************************************************** + // Destroying the old sockets and creating new ones isn't needed, + // but it shows that the problem isn't related to specific sockets. + //close_zero_linger (client); + //close_zero_linger (server); + //server = zmq_socket (ctx, ZMQ_DEALER); + //assert (server); + //client = zmq_socket (ctx, ZMQ_DEALER); + //assert (client); + //// The above code should not be required + //rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "WRONG", 5); + //assert (rc == 0); + //rc = zmq_bind (server, "tcp://127.0.0.1:9001"); + //assert (rc == 0); + //rc = zmq_connect (client, "tcp://localhost:9001"); + //assert (rc == 0); + //expect_bounce_fail (server, client); + //zmq_unbind (server, "tcp://127.0.0.1:9001"); + //zmq_disconnect (client, "tcp://localhost:9001"); + + // Now use the right domain, the test must pass + rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "TEST", 4); + assert (rc == 0); + rc = zmq_bind (server, "tcp://127.0.0.1:9002"); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9002"); + assert (rc == 0); + // ************************************************************** + // PH: it fails here; though the ZAP reply is 200 OK, and + // null_mechanism.cpp correctly parses that, the connection + // never succeeds and the test hangs. + // ************************************************************** + bounce (server, client); + zmq_unbind (server, "tcp://127.0.0.1:9002"); + zmq_disconnect (client, "tcp://localhost:9002"); + + // Shutdown + close_zero_linger (client); + close_zero_linger (server); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + // Wait until ZAP handler terminates. + zmq_threadclose (zap_thread); + + return 0; +} diff --git a/tests/test_security_plain.cpp b/tests/test_security_plain.cpp new file mode 100644 index 0000000..74973fd --- /dev/null +++ b/tests/test_security_plain.cpp @@ -0,0 +1,150 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +static void +zap_handler (void *ctx) +{ + // Create and bind ZAP socket + void *zap = zmq_socket (ctx, ZMQ_REP); + assert (zap); + int rc = zmq_bind (zap, "inproc://zeromq.zap.01"); + assert (rc == 0); + + // Process ZAP requests forever + while (true) { + char *version = s_recv (zap); + if (!version) + break; // Terminating + char *sequence = s_recv (zap); + char *domain = s_recv (zap); + char *address = s_recv (zap); + char *identity = s_recv (zap); + char *mechanism = s_recv (zap); + char *username = s_recv (zap); + char *password = s_recv (zap); + + assert (streq (version, "1.0")); + assert (streq (mechanism, "PLAIN")); + assert (streq (identity, "IDENT")); + + s_sendmore (zap, version); + s_sendmore (zap, sequence); + if (streq (username, "admin") + && streq (password, "password")) { + s_sendmore (zap, "200"); + s_sendmore (zap, "OK"); + s_sendmore (zap, "anonymous"); + s_send (zap, ""); + } + else { + s_sendmore (zap, "400"); + s_sendmore (zap, "Invalid username or password"); + s_sendmore (zap, ""); + s_send (zap, ""); + } + free (version); + free (sequence); + free (domain); + free (address); + free (identity); + free (mechanism); + free (username); + free (password); + } + rc = zmq_close (zap); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // Spawn ZAP handler + void *zap_thread = zmq_threadstart (&zap_handler, ctx); + + // Server socket will accept connections + void *server = zmq_socket (ctx, ZMQ_DEALER); + assert (server); + int rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6); + assert (rc == 0); + int as_server = 1; + rc = zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)); + assert (rc == 0); + rc = zmq_bind (server, "tcp://127.0.0.1:9998"); + assert (rc == 0); + + char username [256]; + char password [256]; + + // Check PLAIN security with correct username/password + void *client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + strcpy (username, "admin"); + rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)); + assert (rc == 0); + strcpy (password, "password"); + rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password)); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + bounce (server, client); + rc = zmq_close (client); + assert (rc == 0); + + // Check PLAIN security with badly configured client (as_server) + // This will be caught by the plain_server class, not passed to ZAP + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + as_server = 1; + rc = zmq_setsockopt (client, ZMQ_PLAIN_SERVER, &as_server, sizeof (int)); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Check PLAIN security -- failed authentication + client = zmq_socket (ctx, ZMQ_DEALER); + assert (client); + strcpy (username, "wronguser"); + strcpy (password, "wrongpass"); + rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username)); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password)); + assert (rc == 0); + rc = zmq_connect (client, "tcp://localhost:9998"); + assert (rc == 0); + expect_bounce_fail (server, client); + close_zero_linger (client); + + // Shutdown + rc = zmq_close (server); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + // Wait until ZAP handler terminates + zmq_threadclose (zap_thread); + + return 0; +} diff --git a/tests/test_shutdown_stress.cpp b/tests/test_shutdown_stress.cpp new file mode 100644 index 0000000..39b42da --- /dev/null +++ b/tests/test_shutdown_stress.cpp @@ -0,0 +1,80 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +#define THREAD_COUNT 100 + +extern "C" +{ + static void worker (void *s) + { + int rc; + + rc = zmq_connect (s, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Start closing the socket while the connecting process is underway. + rc = zmq_close (s); + assert (rc == 0); + } +} + +int main (void) +{ + setup_test_environment(); + void *s1; + void *s2; + int i; + int j; + int rc; + void* threads [THREAD_COUNT]; + + for (j = 0; j != 10; j++) { + + // Check the shutdown with many parallel I/O threads. + void *ctx = zmq_ctx_new (); + assert (ctx); + zmq_ctx_set (ctx, ZMQ_IO_THREADS, 7); + + s1 = zmq_socket (ctx, ZMQ_PUB); + assert (s1); + + rc = zmq_bind (s1, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + for (i = 0; i != THREAD_COUNT; i++) { + s2 = zmq_socket (ctx, ZMQ_SUB); + assert (s2); + threads [i] = zmq_threadstart(&worker, s2); + } + + for (i = 0; i != THREAD_COUNT; i++) { + zmq_threadclose(threads [i]); + } + + rc = zmq_close (s1); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + } + + return 0; +} diff --git a/tests/test_spec_dealer.cpp b/tests/test_spec_dealer.cpp new file mode 100644 index 0000000..7d36d86 --- /dev/null +++ b/tests/test_spec_dealer.cpp @@ -0,0 +1,254 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *bind_address = 0; +const char *connect_address = 0; + +void test_round_robin_out (void *ctx) +{ + void *dealer = zmq_socket (ctx, ZMQ_DEALER); + assert (dealer); + + int rc = zmq_bind (dealer, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *rep [services]; + for (size_t peer = 0; peer < services; ++peer) { + rep [peer] = zmq_socket (ctx, ZMQ_REP); + assert (rep [peer]); + + int timeout = 100; + rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (rep [peer], connect_address); + assert (rc == 0); + } + + // Wait for connections. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + // Send all requests + for (size_t i = 0; i < services; ++i) + s_send_seq (dealer, 0, "ABC", SEQ_END); + + // Expect every REP got one message + zmq_msg_t msg; + zmq_msg_init (&msg); + + for (size_t peer = 0; peer < services; ++peer) + s_recv_seq (rep [peer], "ABC", SEQ_END); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (dealer); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (rep [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_fair_queue_in (void *ctx) +{ + void *receiver = zmq_socket (ctx, ZMQ_DEALER); + assert (receiver); + + int timeout = 100; + int rc = zmq_setsockopt (receiver, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_bind (receiver, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *senders [services]; + for (size_t peer = 0; peer < services; ++peer) { + senders [peer] = zmq_socket (ctx, ZMQ_DEALER); + assert (senders [peer]); + + rc = zmq_setsockopt (senders [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (senders [peer], connect_address); + assert (rc == 0); + } + + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + + s_send_seq (senders [0], "A", SEQ_END); + s_recv_seq (receiver, "A", SEQ_END); + + s_send_seq (senders [0], "A", SEQ_END); + s_recv_seq (receiver, "A", SEQ_END); + + // send our requests + for (size_t peer = 0; peer < services; ++peer) + s_send_seq (senders [peer], "B", SEQ_END); + + // Wait for data. + rc = zmq_poll (0, 0, 50); + assert (rc == 0); + + // handle the requests + for (size_t peer = 0; peer < services; ++peer) + s_recv_seq (receiver, "B", SEQ_END); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (receiver); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (senders [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_destroy_queue_on_disconnect (void *ctx) +{ + void *A = zmq_socket (ctx, ZMQ_DEALER); + assert (A); + + int rc = zmq_bind (A, bind_address); + assert (rc == 0); + + void *B = zmq_socket (ctx, ZMQ_DEALER); + assert (B); + + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + // Send a message in both directions + s_send_seq (A, "ABC", SEQ_END); + s_send_seq (B, "DEF", SEQ_END); + + rc = zmq_disconnect (B, connect_address); + assert (rc == 0); + + // Disconnect may take time and need command processing. + zmq_pollitem_t poller [2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } }; + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + + // No messages should be available, sending should fail. + zmq_msg_t msg; + zmq_msg_init (&msg); + + rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + // After a reconnect of B, the messages should still be gone + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (A); + close_zero_linger (B); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_block_on_send_no_peers (void *ctx) +{ + void *sc = zmq_socket (ctx, ZMQ_DEALER); + assert (sc); + + int timeout = 100; + int rc = zmq_setsockopt (sc, ZMQ_SNDTIMEO, &timeout, sizeof (timeout)); + assert (rc == 0); + + rc = zmq_send (sc, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_send (sc, 0, 0, 0); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_close (sc); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + const char *binds [] = { "inproc://a", "tcp://127.0.0.1:5555" }; + const char *connects [] = { "inproc://a", "tcp://localhost:5555" }; + + for (int transports = 0; transports < 2; ++transports) { + bind_address = binds [transports]; + connect_address = connects [transports]; + + // SHALL route outgoing messages to available peers using a round-robin + // strategy. + test_round_robin_out (ctx); + + // SHALL receive incoming messages from its peers using a fair-queuing + // strategy. + test_fair_queue_in (ctx); + + // SHALL block on sending, or return a suitable error, when it has no connected peers. + test_block_on_send_no_peers (ctx); + + // SHALL create a double queue when a peer connects to it. If this peer + // disconnects, the DEALER socket SHALL destroy its double queue and SHALL + // discard any messages it contains. + // *** Test disabled until libzmq does this properly *** + // test_destroy_queue_on_disconnect (ctx); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_spec_pushpull.cpp b/tests/test_spec_pushpull.cpp new file mode 100644 index 0000000..42305d9 --- /dev/null +++ b/tests/test_spec_pushpull.cpp @@ -0,0 +1,293 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *bind_address = 0; +const char *connect_address = 0; + +void test_push_round_robin_out (void *ctx) +{ + void *push = zmq_socket (ctx, ZMQ_PUSH); + assert (push); + + int rc = zmq_bind (push, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *pulls [services]; + for (size_t peer = 0; peer < services; ++peer) { + pulls [peer] = zmq_socket (ctx, ZMQ_PULL); + assert (pulls [peer]); + + int timeout = 100; + rc = zmq_setsockopt (pulls [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (pulls [peer], connect_address); + assert (rc == 0); + } + + // Wait for connections. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + // Send 2N messages + for (size_t peer = 0; peer < services; ++peer) + s_send_seq (push, "ABC", SEQ_END); + for (size_t peer = 0; peer < services; ++peer) + s_send_seq (push, "DEF", SEQ_END); + + // Expect every PULL got one of each + for (size_t peer = 0; peer < services; ++peer) { + s_recv_seq (pulls [peer], "ABC", SEQ_END); + s_recv_seq (pulls [peer], "DEF", SEQ_END); + } + + close_zero_linger (push); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (pulls [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_pull_fair_queue_in (void *ctx) +{ + void *pull = zmq_socket (ctx, ZMQ_PULL); + assert (pull); + + int rc = zmq_bind (pull, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *pushs [services]; + for (size_t peer = 0; peer < services; ++peer) + { + pushs [peer] = zmq_socket (ctx, ZMQ_PUSH); + assert (pushs [peer]); + + rc = zmq_connect (pushs [peer], connect_address); + assert (rc == 0); + } + + // Wait for connections. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + int first_half = 0; + int second_half = 0; + + // Send 2N messages + for (size_t peer = 0; peer < services; ++peer) { + char *str = strdup("A"); + + str [0] += peer; + s_send_seq (pushs [peer], str, SEQ_END); + first_half += str [0]; + + str [0] += services; + s_send_seq (pushs [peer], str, SEQ_END); + second_half += str [0]; + + free (str); + } + + // Wait for data. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + + // Expect to pull one from each first + for (size_t peer = 0; peer < services; ++peer) { + rc = zmq_msg_recv (&msg, pull, 0); + assert (rc == 2); + const char *str = (const char *)zmq_msg_data (&msg); + first_half -= str [0]; + } + assert (first_half == 0); + + // And then get the second batch + for (size_t peer = 0; peer < services; ++peer) { + rc = zmq_msg_recv (&msg, pull, 0); + assert (rc == 2); + const char *str = (const char *)zmq_msg_data (&msg); + second_half -= str [0]; + } + assert (second_half == 0); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (pull); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (pushs [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_push_block_on_send_no_peers (void *ctx) +{ + void *sc = zmq_socket (ctx, ZMQ_PUSH); + assert (sc); + + int timeout = 100; + int rc = zmq_setsockopt (sc, ZMQ_SNDTIMEO, &timeout, sizeof (timeout)); + assert (rc == 0); + + rc = zmq_send (sc, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_send (sc, 0, 0, 0); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_close (sc); + assert (rc == 0); +} + +void test_destroy_queue_on_disconnect (void *ctx) +{ + void *A = zmq_socket (ctx, ZMQ_PUSH); + assert (A); + + int hwm = 1; + int rc = zmq_setsockopt (A, ZMQ_SNDHWM, &hwm, sizeof (hwm)); + assert (rc == 0); + + rc = zmq_bind (A, bind_address); + assert (rc == 0); + + void *B = zmq_socket (ctx, ZMQ_PULL); + assert (B); + + rc = zmq_setsockopt (B, ZMQ_RCVHWM, &hwm, sizeof (hwm)); + assert (rc == 0); + + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + // Send two messages, one should be stuck in A's outgoing queue, the other + // arrives at B. + s_send_seq (A, "ABC", SEQ_END); + s_send_seq (A, "DEF", SEQ_END); + + // Both queues should now be full, indicated by A blocking on send. + rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_disconnect (B, connect_address); + assert (rc == 0); + + // Disconnect may take time and need command processing. + zmq_pollitem_t poller [2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } }; + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + + // Can't receive old data on B. + rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + // Sending fails. + rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + // Reconnect B + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + // Still can't receive old data on B. + rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + // two messages should be sendable before the queues are filled up. + s_send_seq (A, "ABC", SEQ_END); + s_send_seq (A, "DEF", SEQ_END); + + rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (A); + close_zero_linger (B); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + const char *binds [] = { "inproc://a", "tcp://127.0.0.1:5555" }; + const char *connects [] = { "inproc://a", "tcp://localhost:5555" }; + + for (int transport = 0; transport < 2; ++transport) { + bind_address = binds [transport]; + connect_address = connects [transport]; + + // PUSH: SHALL route outgoing messages to connected peers using a + // round-robin strategy. + test_push_round_robin_out (ctx); + + // PULL: SHALL receive incoming messages from its peers using a fair-queuing + // strategy. + test_pull_fair_queue_in (ctx); + + // PUSH: SHALL block on sending, or return a suitable error, when it has no + // available peers. + test_push_block_on_send_no_peers (ctx); + + // PUSH and PULL: SHALL create this queue when a peer connects to it. If + // this peer disconnects, the socket SHALL destroy its queue and SHALL + // discard any messages it contains. + // *** Test disabled until libzmq does this properly *** + // test_destroy_queue_on_disconnect (ctx); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_spec_rep.cpp b/tests/test_spec_rep.cpp new file mode 100644 index 0000000..c5b291e --- /dev/null +++ b/tests/test_spec_rep.cpp @@ -0,0 +1,155 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *bind_address = 0; +const char *connect_address = 0; + +void test_fair_queue_in (void *ctx) +{ + void *rep = zmq_socket (ctx, ZMQ_REP); + assert (rep); + + int timeout = 100; + int rc = zmq_setsockopt (rep, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_bind (rep, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *reqs [services]; + for (size_t peer = 0; peer < services; ++peer) { + reqs [peer] = zmq_socket (ctx, ZMQ_REQ); + assert (reqs [peer]); + + rc = zmq_setsockopt (reqs [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (reqs [peer], connect_address); + assert (rc == 0); + } + + s_send_seq (reqs [0], "A", SEQ_END); + s_recv_seq (rep, "A", SEQ_END); + s_send_seq (rep, "A", SEQ_END); + s_recv_seq (reqs [0], "A", SEQ_END); + + s_send_seq (reqs [0], "A", SEQ_END); + s_recv_seq (rep, "A", SEQ_END); + s_send_seq (rep, "A", SEQ_END); + s_recv_seq (reqs [0], "A", SEQ_END); + + // TODO: following test fails randomly on some boxes +#ifdef SOMEONE_FIXES_THIS + // send N requests + for (size_t peer = 0; peer < services; ++peer) { + char * str = strdup("A"); + str [0] += peer; + s_send_seq (reqs [peer], str, SEQ_END); + free (str); + } + + // handle N requests + for (size_t peer = 0; peer < services; ++peer) { + char * str = strdup("A"); + str [0] += peer; + // Test fails here + s_recv_seq (rep, str, SEQ_END); + s_send_seq (rep, str, SEQ_END); + s_recv_seq (reqs [peer], str, SEQ_END); + free (str); + } +#endif + close_zero_linger (rep); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (reqs [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_envelope (void *ctx) +{ + void *rep = zmq_socket (ctx, ZMQ_REP); + assert (rep); + + int rc = zmq_bind (rep, bind_address); + assert (rc == 0); + + void *dealer = zmq_socket (ctx, ZMQ_DEALER); + assert (dealer); + + rc = zmq_connect (dealer, connect_address); + assert (rc == 0); + + // minimal envelope + s_send_seq (dealer, 0, "A", SEQ_END); + s_recv_seq (rep, "A", SEQ_END); + s_send_seq (rep, "A", SEQ_END); + s_recv_seq (dealer, 0, "A", SEQ_END); + + // big envelope + s_send_seq (dealer, "X", "Y", 0, "A", SEQ_END); + s_recv_seq (rep, "A", SEQ_END); + s_send_seq (rep, "A", SEQ_END); + s_recv_seq (dealer, "X", "Y", 0, "A", SEQ_END); + + close_zero_linger (rep); + close_zero_linger (dealer); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + const char *binds [] = { "inproc://a", "tcp://127.0.0.1:5555" }; + const char *connects [] = { "inproc://a", "tcp://localhost:5555" }; + + for (int transport = 0; transport < 2; ++transport) { + bind_address = binds [transport]; + connect_address = connects [transport]; + + // SHALL receive incoming messages from its peers using a fair-queuing + // strategy. + test_fair_queue_in (ctx); + + // For an incoming message: + // SHALL remove and store the address envelope, including the delimiter. + // SHALL pass the remaining data frames to its calling application. + // SHALL wait for a single reply message from its calling application. + // SHALL prepend the address envelope and delimiter. + // SHALL deliver this message back to the originating peer. + test_envelope (ctx); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_spec_req.cpp b/tests/test_spec_req.cpp new file mode 100644 index 0000000..8e3e721 --- /dev/null +++ b/tests/test_spec_req.cpp @@ -0,0 +1,253 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *bind_address = 0; +const char *connect_address = 0; + +void test_round_robin_out (void *ctx) +{ + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + int rc = zmq_bind (req, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *rep [services]; + for (size_t peer = 0; peer < services; peer++) { + rep [peer] = zmq_socket (ctx, ZMQ_REP); + assert (rep [peer]); + + int timeout = 100; + rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_connect (rep [peer], connect_address); + assert (rc == 0); + } + // We have to give the connects time to finish otherwise the requests + // will not properly round-robin. We could alternatively connect the + // REQ sockets to the REP sockets. + msleep (SETTLE_TIME); + + // Send our peer-replies, and expect every REP it used once in order + for (size_t peer = 0; peer < services; peer++) { + s_send_seq (req, "ABC", SEQ_END); + s_recv_seq (rep [peer], "ABC", SEQ_END); + s_send_seq (rep [peer], "DEF", SEQ_END); + s_recv_seq (req, "DEF", SEQ_END); + } + + close_zero_linger (req); + for (size_t peer = 0; peer < services; peer++) + close_zero_linger (rep [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_req_only_listens_to_current_peer (void *ctx) +{ + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + int rc = zmq_setsockopt(req, ZMQ_IDENTITY, "A", 2); + assert (rc == 0); + + rc = zmq_bind (req, bind_address); + assert (rc == 0); + + const size_t services = 3; + void *router [services]; + + for (size_t i = 0; i < services; ++i) { + router [i] = zmq_socket (ctx, ZMQ_ROUTER); + assert (router [i]); + + int timeout = 100; + rc = zmq_setsockopt (router [i], ZMQ_RCVTIMEO, &timeout, sizeof (timeout)); + assert (rc == 0); + + int enabled = 1; + rc = zmq_setsockopt (router [i], ZMQ_ROUTER_MANDATORY, &enabled, sizeof (enabled)); + assert (rc == 0); + + rc = zmq_connect (router [i], connect_address); + assert (rc == 0); + } + + // Wait for connects to finish. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + for (size_t i = 0; i < services; ++i) { + // There still is a race condition when a stale peer's message + // arrives at the REQ just after a request was sent to that peer. + // To avoid that happening in the test, sleep for a bit. + rc = zmq_poll (0, 0, 10); + assert (rc == 0); + + s_send_seq (req, "ABC", SEQ_END); + + // Receive on router i + s_recv_seq (router [i], "A", 0, "ABC", SEQ_END); + + // Send back replies on all routers + for (size_t j = 0; j < services; ++j) { + const char *replies [] = { "WRONG", "GOOD" }; + const char *reply = replies [i == j ? 1 : 0]; + s_send_seq (router [j], "A", 0, reply, SEQ_END); + } + + // Receive only the good reply + s_recv_seq (req, "GOOD", SEQ_END); + } + + close_zero_linger (req); + for (size_t i = 0; i < services; ++i) + close_zero_linger (router [i]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_req_message_format (void *ctx) +{ + void *req = zmq_socket (ctx, ZMQ_REQ); + assert (req); + + void *router = zmq_socket (ctx, ZMQ_ROUTER); + assert (router); + + int rc = zmq_bind (req, bind_address); + assert (rc == 0); + + rc = zmq_connect (router, connect_address); + assert (rc == 0); + + // Send a multi-part request. + s_send_seq (req, "ABC", "DEF", SEQ_END); + + zmq_msg_t msg; + zmq_msg_init (&msg); + + // Receive peer identity + rc = zmq_msg_recv (&msg, router, 0); + assert (rc != -1); + assert (zmq_msg_size (&msg) > 0); + zmq_msg_t peer_id_msg; + zmq_msg_init (&peer_id_msg); + zmq_msg_copy (&peer_id_msg, &msg); + + int more = 0; + size_t more_size = sizeof (more); + rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size); + assert (rc == 0); + assert (more); + + // Receive the rest. + s_recv_seq (router, 0, "ABC", "DEF", SEQ_END); + + // Send back a single-part reply. + rc = zmq_msg_send (&peer_id_msg, router, ZMQ_SNDMORE); + assert (rc != -1); + s_send_seq (router, 0, "GHI", SEQ_END); + + // Receive reply. + s_recv_seq (req, "GHI", SEQ_END); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + rc = zmq_msg_close (&peer_id_msg); + assert (rc == 0); + + close_zero_linger (req); + close_zero_linger (router); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_block_on_send_no_peers (void *ctx) +{ + void *sc = zmq_socket (ctx, ZMQ_REQ); + assert (sc); + + int timeout = 100; + int rc = zmq_setsockopt (sc, ZMQ_SNDTIMEO, &timeout, sizeof (timeout)); + assert (rc == 0); + + rc = zmq_send (sc, 0, 0, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_send (sc, 0, 0, 0); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_close (sc); + assert (rc == 0); +} + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + const char *binds [] = { "inproc://a", "tcp://127.0.0.1:5555" }; + const char *connects [] = { "inproc://a", "tcp://localhost:5555" }; + + for (int transport = 0; transport < 2; transport++) { + bind_address = binds [transport]; + connect_address = connects [transport]; + + // SHALL route outgoing messages to connected peers using a round-robin + // strategy. + test_round_robin_out (ctx); + + // The request and reply messages SHALL have this format on the wire: + // * A delimiter, consisting of an empty frame, added by the REQ socket. + // * One or more data frames, comprising the message visible to the + // application. + test_req_message_format (ctx); + + // SHALL block on sending, or return a suitable error, when it has no + // connected peers. + test_block_on_send_no_peers (ctx); + + // SHALL accept an incoming message only from the last peer that it sent a + // request to. + // SHALL discard silently any messages received from other peers. + // PH: this test is still failing; disabled for now to allow build to + // complete. + // test_req_only_listens_to_current_peer (ctx); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_spec_router.cpp b/tests/test_spec_router.cpp new file mode 100644 index 0000000..e85d3c9 --- /dev/null +++ b/tests/test_spec_router.cpp @@ -0,0 +1,204 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +const char *bind_address = 0; +const char *connect_address = 0; + +void test_fair_queue_in (void *ctx) +{ + void *receiver = zmq_socket (ctx, ZMQ_ROUTER); + assert (receiver); + + int timeout = 100; + int rc = zmq_setsockopt (receiver, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_bind (receiver, bind_address); + assert (rc == 0); + + const size_t services = 5; + void *senders [services]; + for (size_t peer = 0; peer < services; ++peer) { + senders [peer] = zmq_socket (ctx, ZMQ_DEALER); + assert (senders [peer]); + + rc = zmq_setsockopt (senders [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + char *str = strdup("A"); + str [0] += peer; + rc = zmq_setsockopt (senders [peer], ZMQ_IDENTITY, str, 2); + assert (rc == 0); + free (str); + + rc = zmq_connect (senders [peer], connect_address); + assert (rc == 0); + } + + zmq_msg_t msg; + rc = zmq_msg_init (&msg); + assert (rc == 0); + + s_send_seq (senders [0], "M", SEQ_END); + s_recv_seq (receiver, "A", "M", SEQ_END); + + s_send_seq (senders [0], "M", SEQ_END); + s_recv_seq (receiver, "A", "M", SEQ_END); + + int sum = 0; + + // send N requests + for (size_t peer = 0; peer < services; ++peer) { + s_send_seq (senders [peer], "M", SEQ_END); + sum += 'A' + peer; + } + + assert (sum == services * 'A' + services * (services - 1) / 2); + + // handle N requests + for (size_t peer = 0; peer < services; ++peer) { + rc = zmq_msg_recv (&msg, receiver, 0); + assert (rc == 2); + const char *id = (const char *)zmq_msg_data (&msg); + sum -= id [0]; + + s_recv_seq (receiver, "M", SEQ_END); + } + + assert (sum == 0); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (receiver); + + for (size_t peer = 0; peer < services; ++peer) + close_zero_linger (senders [peer]); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + +void test_destroy_queue_on_disconnect (void *ctx) +{ + void *A = zmq_socket (ctx, ZMQ_ROUTER); + assert (A); + + int enabled = 1; + int rc = zmq_setsockopt (A, ZMQ_ROUTER_MANDATORY, &enabled, sizeof (enabled)); + assert (rc == 0); + + rc = zmq_bind (A, bind_address); + assert (rc == 0); + + void *B = zmq_socket (ctx, ZMQ_DEALER); + assert (B); + + rc = zmq_setsockopt (B, ZMQ_IDENTITY, "B", 2); + assert (rc == 0); + + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + // Wait for connection. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); + + // Send a message in both directions + s_send_seq (A, "B", "ABC", SEQ_END); + s_send_seq (B, "DEF", SEQ_END); + + rc = zmq_disconnect (B, connect_address); + assert (rc == 0); + + // Disconnect may take time and need command processing. + zmq_pollitem_t poller [2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } }; + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + rc = zmq_poll (poller, 2, 100); + assert (rc == 0); + + // No messages should be available, sending should fail. + zmq_msg_t msg; + zmq_msg_init (&msg); + + rc = zmq_send (A, "B", 2, ZMQ_SNDMORE | ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EHOSTUNREACH); + + rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + // After a reconnect of B, the messages should still be gone + rc = zmq_connect (B, connect_address); + assert (rc == 0); + + rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT); + assert (rc == -1); + assert (errno == EAGAIN); + + rc = zmq_msg_close (&msg); + assert (rc == 0); + + close_zero_linger (A); + close_zero_linger (B); + + // Wait for disconnects. + rc = zmq_poll (0, 0, 100); + assert (rc == 0); +} + + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + const char *binds [] = { "inproc://a", "tcp://127.0.0.1:5555" }; + const char *connects [] = { "inproc://a", "tcp://localhost:5555" }; + + for (int transport = 0; transport < 2; ++transport) { + bind_address = binds [transport]; + connect_address = connects [transport]; + + // SHALL receive incoming messages from its peers using a fair-queuing + // strategy. + test_fair_queue_in (ctx); + + // SHALL create a double queue when a peer connects to it. If this peer + // disconnects, the ROUTER socket SHALL destroy its double queue and SHALL + // discard any messages it contains. + // *** Test disabled until libzmq does this properly *** + // test_destroy_queue_on_disconnect (ctx); + } + + int rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_stream.cpp b/tests/test_stream.cpp new file mode 100644 index 0000000..5e80f01 --- /dev/null +++ b/tests/test_stream.cpp @@ -0,0 +1,227 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +// ZMTP protocol greeting structure + +typedef unsigned char byte; +typedef struct { + byte signature [10]; // 0xFF 8*0x00 0x7F + byte version [2]; // 0x03 0x00 for ZMTP/3.0 + byte mechanism [20]; // "NULL" + byte as_server; + byte filler [31]; +} zmtp_greeting_t; + +#define ZMTP_DEALER 5 // Socket type constants + +// This is a greeting matching what 0MQ will send us; note the +// 8-byte size is set to 1 for backwards compatibility + +static zmtp_greeting_t greeting + = { { 0xFF, 0, 0, 0, 0, 0, 0, 0, 1, 0x7F }, { 3, 0 }, { 'N', 'U', 'L', 'L'} }; + +static void +test_stream_to_dealer (void) +{ + int rc; + + // Set up our context and sockets + void *ctx = zmq_ctx_new (); + assert (ctx); + + // We'll be using this socket in raw mode + void *stream = zmq_socket (ctx, ZMQ_STREAM); + assert (stream); + + int zero = 0; + rc = zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero)); + assert (rc == 0); + rc = zmq_bind (stream, "tcp://127.0.0.1:5556"); + assert (rc == 0); + + // We'll be using this socket as the other peer + void *dealer = zmq_socket (ctx, ZMQ_DEALER); + assert (dealer); + rc = zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero)); + assert (rc == 0); + rc = zmq_connect (dealer, "tcp://localhost:5556"); + + // Send a message on the dealer socket + rc = zmq_send (dealer, "Hello", 5, 0); + assert (rc == 5); + + // First frame is identity + zmq_msg_t identity; + rc = zmq_msg_init (&identity); + assert (rc == 0); + rc = zmq_msg_recv (&identity, stream, 0); + assert (rc > 0); + assert (zmq_msg_more (&identity)); + + // Second frame is greeting signature + byte buffer [255]; + rc = zmq_recv (stream, buffer, 255, 0); + assert (rc == 10); + assert (memcmp (buffer, greeting.signature, 10) == 0); + + // Send our own protocol greeting + rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); + assert (rc > 0); + rc = zmq_send (stream, &greeting, sizeof (greeting), 0); + assert (rc == sizeof (greeting)); + + // Now we expect the data from the DEALER socket + // We want the rest of greeting along with the Ready command + int bytes_read = 0; + while (bytes_read < 97) { + // First frame is the identity of the connection (each time) + rc = zmq_msg_recv (&identity, stream, 0); + assert (rc > 0); + assert (zmq_msg_more (&identity)); + // Second frame contains the next chunk of data + rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0); + assert (rc >= 0); + bytes_read += rc; + } + + // First two bytes are major and minor version numbers. + assert (buffer [0] == 3); // ZMTP/3.0 + assert (buffer [1] == 0); + + // Mechanism is "NULL" + assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0); + assert (memcmp (buffer + 54, "\4\51\5READY", 8) == 0); + assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0); + assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0); + + // Announce we are ready + memcpy (buffer, "\4\51\5READY", 8); + memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22); + memcpy (buffer + 30, "\10Identity\0\0\0\0", 13); + + // Send Ready command + rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); + assert (rc > 0); + rc = zmq_send (stream, buffer, 43, 0); + assert (rc == 43); + + // Now we expect the data from the DEALER socket + // First frame is, again, the identity of the connection + rc = zmq_msg_recv (&identity, stream, 0); + assert (rc > 0); + assert (zmq_msg_more (&identity)); + + // Third frame contains Hello message from DEALER + rc = zmq_recv (stream, buffer, sizeof buffer, 0); + assert (rc == 7); + + // Then we have a 5-byte message "Hello" + assert (buffer [0] == 0); // Flags = 0 + assert (buffer [1] == 5); // Size = 5 + assert (memcmp (buffer + 2, "Hello", 5) == 0); + + // Send "World" back to DEALER + rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); + assert (rc > 0); + byte world [] = { 0, 5, 'W', 'o', 'r', 'l', 'd' }; + rc = zmq_send (stream, world, sizeof (world), 0); + assert (rc == sizeof (world)); + + // Expect response on DEALER socket + rc = zmq_recv (dealer, buffer, 255, 0); + assert (rc == 5); + assert (memcmp (buffer, "World", 5) == 0); + + rc = zmq_close (dealer); + assert (rc == 0); + + rc = zmq_close (stream); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); +} + + +static void +test_stream_to_stream (void) +{ + int rc; + // Set-up our context and sockets + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *server = zmq_socket (ctx, ZMQ_STREAM); + assert (server); + rc = zmq_bind (server, "tcp://127.0.0.1:9080"); + assert (rc == 0); + + void *client = zmq_socket (ctx, ZMQ_STREAM); + assert (client); + rc = zmq_connect (client, "tcp://localhost:9080"); + assert (rc == 0); + // It would be less surprising to get an empty message instead + // of having to fetch the identity like this [PH 2013/06/27] + uint8_t id [256]; + size_t id_size = 256; + rc = zmq_getsockopt (client, ZMQ_IDENTITY, id, &id_size); + assert (rc == 0); + + // Sent HTTP request on client socket + // First frame is server identity + rc = zmq_send (client, id, id_size, ZMQ_SNDMORE); + assert (rc == (int) id_size); + // Second frame is HTTP GET request + rc = zmq_send (client, "GET /\n\n", 7, 0); + assert (rc == 7); + + // Get HTTP request; ID frame and then request + id_size = zmq_recv (server, id, 256, 0); + assert (id_size > 0); + uint8_t buffer [256]; + rc = zmq_recv (server, buffer, 256, 0); + assert (rc > 0); + assert (memcmp (buffer, "GET /\n\n", 7) == 0); + + // Send reply back to client + char http_response [] = + "HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + "Hello, World!"; + zmq_send (server, id, id_size, ZMQ_SNDMORE); + zmq_send (server, http_response, sizeof (http_response), 0); + + // Get reply at client and check that it's complete + id_size = zmq_recv (client, id, 256, 0); + assert (id_size > 0); + rc = zmq_recv (client, buffer, 256, 0); + assert (rc == sizeof (http_response)); + assert (memcmp (buffer, http_response, sizeof (http_response)) == 0); +} + + +int main (void) +{ + setup_test_environment(); + test_stream_to_dealer (); + test_stream_to_stream (); +} diff --git a/tests/test_sub_forward.cpp b/tests/test_sub_forward.cpp new file mode 100644 index 0000000..e77ed3b --- /dev/null +++ b/tests/test_sub_forward.cpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + // First, create an intermediate device + void *xpub = zmq_socket (ctx, ZMQ_XPUB); + assert (xpub); + int rc = zmq_bind (xpub, "tcp://127.0.0.1:5560"); + assert (rc == 0); + void *xsub = zmq_socket (ctx, ZMQ_XSUB); + assert (xsub); + rc = zmq_bind (xsub, "tcp://127.0.0.1:5561"); + assert (rc == 0); + + // Create a publisher + void *pub = zmq_socket (ctx, ZMQ_PUB); + assert (pub); + rc = zmq_connect (pub, "tcp://127.0.0.1:5561"); + assert (rc == 0); + + // Create a subscriber + void *sub = zmq_socket (ctx, ZMQ_SUB); + assert (sub); + rc = zmq_connect (sub, "tcp://127.0.0.1:5560"); + assert (rc == 0); + + // Subscribe for all messages. + rc = zmq_setsockopt (sub, ZMQ_SUBSCRIBE, "", 0); + assert (rc == 0); + + // Pass the subscription upstream through the device + char buff [32]; + rc = zmq_recv (xpub, buff, sizeof (buff), 0); + assert (rc >= 0); + rc = zmq_send (xsub, buff, rc, 0); + assert (rc >= 0); + + // Wait a bit till the subscription gets to the publisher + msleep (SETTLE_TIME); + + // Send an empty message + rc = zmq_send (pub, NULL, 0, 0); + assert (rc == 0); + + // Pass the message downstream through the device + rc = zmq_recv (xsub, buff, sizeof (buff), 0); + assert (rc >= 0); + rc = zmq_send (xpub, buff, rc, 0); + assert (rc >= 0); + + // Receive the message in the subscriber + rc = zmq_recv (sub, buff, sizeof (buff), 0); + assert (rc == 0); + + // Clean up. + rc = zmq_close (xpub); + assert (rc == 0); + rc = zmq_close (xsub); + assert (rc == 0); + rc = zmq_close (pub); + assert (rc == 0); + rc = zmq_close (sub); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/test_system.cpp b/tests/test_system.cpp new file mode 100644 index 0000000..bbea654 --- /dev/null +++ b/tests/test_system.cpp @@ -0,0 +1,82 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +#if defined (ZMQ_HAVE_WINDOWS) +# include +# include +#else +# include +# include +# include +#endif + +#if defined (ZMQ_HAVE_WINDOWS) + +void initialise_network() +{ + WSADATA info; + if (WSAStartup(MAKEWORD(2,0), &info) != 0) + { + throw std::runtime_error("Could not start WSA"); + } +} + +int close(int fd) +{ + return closesocket(fd); +} + +#else + +void initialise_network() +{ +} + +#endif + +// This test case stresses the system to shake out known configuration +// problems. We're not using libzmq here but direct system calls. Note +// that code may need wrapping to be properly portable. + +int main (void) +{ + initialise_network(); + + // Check that we can create 1,000 sockets + int handle [1000]; + int count; + for (count = 0; count < 1000; 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_OSX) + printf ("I: On OS/X, run 'ulimit -n 1200' in bash"); +#elif defined (ZMQ_HAVE_LINUX) + printf ("I: On Linux, run 'ulimit -n 1200' in bash"); +#endif + return -1; + } + } + // Release the socket handles + while (count) + close (handle [count--]); +} diff --git a/tests/test_term_endpoint.cpp b/tests/test_term_endpoint.cpp new file mode 100644 index 0000000..186d377 --- /dev/null +++ b/tests/test_term_endpoint.cpp @@ -0,0 +1,104 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + int rc; + char buf[32]; + const char *ep = "tcp://127.0.0.1:5560"; + + // Create infrastructure. + void *ctx = zmq_ctx_new (); + 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, ep); + assert (rc == 0); + + // 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); + + // Unbind the listening endpoint + rc = zmq_unbind (push, ep); + assert (rc == 0); + + // Allow unbind to settle + 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); + + // Clean up + rc = zmq_close (pull); + assert (rc == 0); + rc = zmq_close (push); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + // Create infrastructure + ctx = zmq_ctx_new (); + assert (ctx); + push = zmq_socket (ctx, ZMQ_PUSH); + assert (push); + rc = zmq_connect (push, ep); + assert (rc == 0); + pull = zmq_socket (ctx, ZMQ_PULL); + assert (pull); + rc = zmq_bind (pull, ep); + assert (rc == 0); + + // 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); + + // Disconnect the bound endpoint + rc = zmq_disconnect (push, ep); + assert (rc == 0); + + // Allow disconnect to settle + 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); + + // 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; +} diff --git a/tests/test_timeo.cpp b/tests/test_timeo.cpp new file mode 100644 index 0000000..f47e0b5 --- /dev/null +++ b/tests/test_timeo.cpp @@ -0,0 +1,75 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "testutil.hpp" + +int main (void) +{ + setup_test_environment(); + void *ctx = zmq_ctx_new (); + assert (ctx); + + void *frontend = zmq_socket (ctx, ZMQ_DEALER); + assert (frontend); + int rc = zmq_bind (frontend, "inproc://timeout_test"); + assert (rc == 0); + + // Receive on disconnected socket returns immediately + char buffer [32]; + rc = zmq_recv (frontend, buffer, 32, ZMQ_DONTWAIT); + assert (rc == -1); + assert (zmq_errno() == EAGAIN); + + // Check whether receive timeout is honored + int timeout = 250; + rc = zmq_setsockopt (frontend, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + void* stopwatch = zmq_stopwatch_start(); + rc = zmq_recv (frontend, buffer, 32, 0); + assert (rc == -1); + assert (zmq_errno () == EAGAIN); + unsigned int elapsed = zmq_stopwatch_stop(stopwatch) / 1000; + assert (elapsed > 200 && elapsed < 300); + + // Check that normal message flow works as expected + void *backend = zmq_socket (ctx, ZMQ_DEALER); + assert (backend); + rc = zmq_connect (backend, "inproc://timeout_test"); + assert (rc == 0); + rc = zmq_setsockopt (backend, ZMQ_SNDTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + rc = zmq_send (backend, "Hello", 5, 0); + assert (rc == 5); + rc = zmq_recv (frontend, buffer, 32, 0); + assert (rc == 5); + + // Clean-up + rc = zmq_close (backend); + assert (rc == 0); + + rc = zmq_close (frontend); + assert (rc == 0); + + rc = zmq_ctx_term (ctx); + assert (rc == 0); + + return 0 ; +} diff --git a/tests/testutil.hpp b/tests/testutil.hpp new file mode 100644 index 0000000..7a42379 --- /dev/null +++ b/tests/testutil.hpp @@ -0,0 +1,294 @@ +/* + Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file + + This file is part of 0MQ. + + 0MQ is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + 0MQ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef __TESTUTIL_HPP_INCLUDED__ +#define __TESTUTIL_HPP_INCLUDED__ + +#include "../include/zmq.h" +#include "../include/zmq_utils.h" +#include "platform.hpp" + +// This defines the settle time used in tests; raise this if we +// get test failures on slower systems due to binds/connects not +// settled. Tested to work reliably at 1 msec on a fast PC. +#define SETTLE_TIME 10 // In msec + +#undef NDEBUG +#include +#include +#include +#include + +#if defined _WIN32 +# if defined _MSC_VER +# include +# pragma warning(disable:4996) +# endif +#else +# include +# include +# include +# include +#endif + +// 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); +} + +// 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 = 150; + int rc; + rc = zmq_setsockopt (client, ZMQ_SNDTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + rc = zmq_setsockopt (client, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + rc = zmq_setsockopt (server, ZMQ_SNDTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + rc = zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (int)); + assert (rc == 0); + + // Send message from client to server (may fail) + rc = zmq_send (client, content, 32, ZMQ_SNDMORE); + if (rc == -1 && zmq_errno () == EAGAIN) + return; + assert (rc == 32); + rc = zmq_send (client, content, 32, 0); + if (rc == -1 && zmq_errno () == EAGAIN) + return; + assert (rc == 32); + + // Receive message at server side (should not succeed) + rc = zmq_recv (server, buffer, 32, 0); + assert (rc == -1); + assert (zmq_errno () == EAGAIN); + + // Send message from server to client to test other direction + rc = zmq_send (server, content, 32, ZMQ_SNDMORE); + assert (rc == 32); + rc = zmq_send (server, content, 32, 0); + assert (rc == 32); + + // Receive message at client side (should not succeed) + rc = zmq_recv (client, buffer, 32, 0); + assert (rc == -1); + assert (zmq_errno () == EAGAIN); +} + +// 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); +} + +// 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; +} + +// 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; +} + +#define streq(s1,s2) (!strcmp ((s1), (s2))) +#define strneq(s1,s2) (strcmp ((s1), (s2))) + +const char *SEQ_END = (const char *) 1; + +// 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); +} + +// 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); +} + + +// 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 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 +#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 +} + +// 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 (milliseconds) * 1000); +#endif +} + + +#endif -- cgit v1.2.3