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 | |
33 | SETUP_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 | |
39 | const char *ep_wc_tcp = "tcp://127.0.0.1:*" ; |
40 | #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS |
41 | const char *ep_wc_ipc = "ipc://*" ; |
42 | #endif |
43 | #if defined ZMQ_HAVE_VMCI |
44 | const char *ep_wc_vmci = "vmci://*:*" ; |
45 | #endif |
46 | |
47 | void 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 | |
76 | void 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 | |
104 | void 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 | |
145 | void 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 | |
173 | int 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 | |