1/*
2 Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#include "testutil.hpp"
31#include "testutil_unity.hpp"
32
33SETUP_TEARDOWN_TESTCONTEXT
34
35/* Use the worst case filename size for the buffer (+1 for trailing NUL), this
36 * is larger than MAX_SOCKET_STRING, which is not large enough for IPC */
37#define BUF_SIZE (FILENAME_MAX + 1)
38
39const char *ep_wc_tcp = "tcp://127.0.0.1:*";
40#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
41const char *ep_wc_ipc = "ipc://*";
42#endif
43#if defined ZMQ_HAVE_VMCI
44const char *ep_wc_vmci = "vmci://*:*";
45#endif
46
47void test_send_after_unbind_fails ()
48{
49 char my_endpoint[BUF_SIZE];
50
51 // Create infrastructure.
52 void *push = test_context_socket (ZMQ_PUSH);
53 bind_loopback_ipv4 (push, my_endpoint, BUF_SIZE);
54
55 void *pull = test_context_socket (ZMQ_PULL);
56 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pull, my_endpoint));
57
58 // Pass one message through to ensure the connection is established
59 send_string_expect_success (push, "ABC", 0);
60 recv_string_expect_success (pull, "ABC", 0);
61
62 // Unbind the listening endpoint
63 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (push, my_endpoint));
64
65 // Allow unbind to settle
66 msleep (SETTLE_TIME);
67
68 // Check that sending would block (there's no outbound connection)
69 TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_send (push, "ABC", 3, ZMQ_DONTWAIT));
70
71 // Clean up
72 test_context_socket_close (pull);
73 test_context_socket_close (push);
74}
75
76void test_send_after_disconnect_fails ()
77{
78 // Create infrastructure
79 void *pull = test_context_socket (ZMQ_PULL);
80 char my_endpoint[BUF_SIZE];
81 bind_loopback_ipv4 (pull, my_endpoint, BUF_SIZE);
82
83 void *push = test_context_socket (ZMQ_PUSH);
84 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (push, my_endpoint));
85
86 // Pass one message through to ensure the connection is established.
87 send_string_expect_success (push, "ABC", 0);
88 recv_string_expect_success (pull, "ABC", 0);
89
90 // Disconnect the bound endpoint
91 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (push, my_endpoint));
92
93 // Allow disconnect to settle
94 msleep (SETTLE_TIME);
95
96 // Check that sending would block (there's no inbound connections).
97 TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_send (push, "ABC", 3, ZMQ_DONTWAIT));
98
99 // Clean up
100 test_context_socket_close (pull);
101 test_context_socket_close (push);
102}
103
104void test_unbind_via_last_endpoint ()
105{
106 // Create infrastructure (wild-card binding)
107 void *push = test_context_socket (ZMQ_PUSH);
108 char my_endpoint[BUF_SIZE];
109 bind_loopback_ipv4 (push, my_endpoint, BUF_SIZE);
110
111 void *pull = test_context_socket (ZMQ_PULL);
112
113#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
114 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pull, ep_wc_ipc));
115#endif
116#if defined ZMQ_HAVE_VMCI
117 void *req = test_context_socket (ZMQ_REQ);
118 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (req, ep_wc_vmci));
119#endif
120
121 // Unbind sockets binded by wild-card address
122 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (push, my_endpoint));
123
124 size_t buf_size = 0;
125 (void) buf_size;
126
127#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
128 buf_size = sizeof (my_endpoint);
129 TEST_ASSERT_SUCCESS_ERRNO (
130 zmq_getsockopt (pull, ZMQ_LAST_ENDPOINT, my_endpoint, &buf_size));
131 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (pull, my_endpoint));
132#endif
133#if defined ZMQ_HAVE_VMCI
134 buf_size = sizeof (my_endpoint);
135 TEST_ASSERT_SUCCESS_ERRNO (
136 zmq_getsockopt (req, ZMQ_LAST_ENDPOINT, my_endpoint, &buf_size));
137 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (req, my_endpoint));
138#endif
139
140 // Clean up
141 test_context_socket_close (pull);
142 test_context_socket_close (push);
143}
144
145void test_wildcard_unbind_fails ()
146{
147 // Create infrastructure (wild-card binding)
148 void *push = test_context_socket (ZMQ_PUSH);
149 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (push, ep_wc_tcp));
150 void *pull = test_context_socket (ZMQ_PULL);
151#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
152 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pull, ep_wc_ipc));
153#endif
154#if defined ZMQ_HAVE_VMCI
155 void *req = test_context_socket (ZMQ_REQ);
156 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (req, ep_wc_vmci));
157#endif
158
159 // Sockets binded by wild-card address can't be unbinded by wild-card address
160 TEST_ASSERT_FAILURE_ERRNO (ENOENT, zmq_unbind (push, ep_wc_tcp));
161#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
162 TEST_ASSERT_FAILURE_ERRNO (ENOENT, zmq_unbind (pull, ep_wc_ipc));
163#endif
164#if defined ZMQ_HAVE_VMCI
165 TEST_ASSERT_FAILURE_ERRNO (ENOENT, zmq_unbind (req, ep_wc_vmci));
166#endif
167
168 // Clean up
169 test_context_socket_close (pull);
170 test_context_socket_close (push);
171}
172
173int main ()
174{
175 setup_test_environment ();
176
177 UNITY_BEGIN ();
178 RUN_TEST (test_send_after_unbind_fails);
179 RUN_TEST (test_send_after_disconnect_fails);
180 RUN_TEST (test_unbind_via_last_endpoint);
181 RUN_TEST (test_wildcard_unbind_fails);
182 return UNITY_END ();
183}
184