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
35const int MAX_SENDS = 10000;
36
37enum TestType
38{
39 BIND_FIRST,
40 CONNECT_FIRST
41};
42
43void test_defaults ()
44{
45 // Set up bind socket
46 void *bind_socket = test_context_socket (ZMQ_PULL);
47 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
48
49 // Set up connect socket
50 void *connect_socket = test_context_socket (ZMQ_PUSH);
51 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
52
53 // Send until we block
54 int send_count = 0;
55 while (send_count < MAX_SENDS
56 && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
57 ++send_count;
58
59 msleep (SETTLE_TIME);
60
61 // Now receive all sent messages
62 int recv_count = 0;
63 while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
64 ++recv_count;
65
66 TEST_ASSERT_EQUAL_INT (send_count, recv_count);
67
68 // Clean up
69 test_context_socket_close (connect_socket);
70 test_context_socket_close (bind_socket);
71
72 // Default values are 1000 on send and 1000 one receive, so 2000 total
73 TEST_ASSERT_EQUAL_INT (2000, send_count);
74}
75
76int count_msg (int send_hwm_, int recv_hwm_, TestType test_type_)
77{
78 void *bind_socket;
79 void *connect_socket;
80 if (test_type_ == BIND_FIRST) {
81 // Set up bind socket
82 bind_socket = test_context_socket (ZMQ_PULL);
83 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
84 bind_socket, ZMQ_RCVHWM, &recv_hwm_, sizeof (recv_hwm_)));
85 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
86
87 // Set up connect socket
88 connect_socket = test_context_socket (ZMQ_PUSH);
89 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
90 connect_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
91 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
92
93 // we must wait for the connect to succeed here, unfortunately we don't
94 // have monitoring events for inproc, so we just hope SETTLE_TIME suffices
95 msleep (SETTLE_TIME);
96 } else {
97 // Set up connect socket
98 connect_socket = test_context_socket (ZMQ_PUSH);
99 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
100 connect_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
101 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
102
103 // Set up bind socket
104 bind_socket = test_context_socket (ZMQ_PULL);
105 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
106 bind_socket, ZMQ_RCVHWM, &recv_hwm_, sizeof (recv_hwm_)));
107 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
108 }
109
110 // Send until we block
111 int send_count = 0;
112 while (send_count < MAX_SENDS
113 && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
114 ++send_count;
115
116 // Now receive all sent messages
117 int recv_count = 0;
118 while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
119 ++recv_count;
120
121 TEST_ASSERT_EQUAL_INT (send_count, recv_count);
122
123 // Now it should be possible to send one more.
124 send_string_expect_success (connect_socket, NULL, 0);
125
126 // Consume the remaining message.
127 recv_string_expect_success (bind_socket, NULL, 0);
128
129 // Clean up
130 test_context_socket_close (connect_socket);
131 test_context_socket_close (bind_socket);
132
133 return send_count;
134}
135
136int test_inproc_bind_first (int send_hwm_, int recv_hwm_)
137{
138 return count_msg (send_hwm_, recv_hwm_, BIND_FIRST);
139}
140
141int test_inproc_connect_first (int send_hwm_, int recv_hwm_)
142{
143 return count_msg (send_hwm_, recv_hwm_, CONNECT_FIRST);
144}
145
146int test_inproc_connect_and_close_first (int send_hwm_, int recv_hwm_)
147{
148 // Set up connect socket
149 void *connect_socket = test_context_socket (ZMQ_PUSH);
150 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (connect_socket, ZMQ_SNDHWM,
151 &send_hwm_, sizeof (send_hwm_)));
152 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
153
154 // Send until we block
155 int send_count = 0;
156 while (send_count < MAX_SENDS
157 && zmq_send (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
158 ++send_count;
159
160 // Close connect
161 test_context_socket_close (connect_socket);
162
163 // Set up bind socket
164 void *bind_socket = test_context_socket (ZMQ_PULL);
165 TEST_ASSERT_SUCCESS_ERRNO (
166 zmq_setsockopt (bind_socket, ZMQ_RCVHWM, &recv_hwm_, sizeof (recv_hwm_)));
167 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
168
169 // Now receive all sent messages
170 int recv_count = 0;
171 while (zmq_recv (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
172 ++recv_count;
173
174 TEST_ASSERT_EQUAL_INT (send_count, recv_count);
175
176 // Clean up
177 test_context_socket_close (bind_socket);
178
179 return send_count;
180}
181
182int test_inproc_bind_and_close_first (int send_hwm_, int /* recv_hwm */)
183{
184 // Set up bind socket
185 void *bind_socket = test_context_socket (ZMQ_PUSH);
186 TEST_ASSERT_SUCCESS_ERRNO (
187 zmq_setsockopt (bind_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
188 TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://a"));
189
190 // Send until we block
191 int send_count = 0;
192 while (send_count < MAX_SENDS
193 && zmq_send (bind_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
194 ++send_count;
195
196 // Close bind
197 test_context_socket_close (bind_socket);
198
199 /* TODO Can't currently do connect without then wiring up a bind as things hang, this needs top be fixed.
200 // Set up connect socket
201 void *connect_socket = test_context_socket (ZMQ_PULL);
202 TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (connect_socket, ZMQ_RCVHWM, &recv_hwm, sizeof (recv_hwm)));
203 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://a"));
204
205 // Now receive all sent messages
206 int recv_count = 0;
207 while (zmq_recv (connect_socket, NULL, 0, ZMQ_DONTWAIT) == 0)
208 ++recv_count;
209
210 TEST_ASSERT_EQUAL_INT(send_count, recv_count);
211 */
212
213 // Clean up
214 //test_context_socket_close (connect_socket);
215
216 return send_count;
217}
218
219void test_infinite_both_inproc_bind_first ()
220{
221 int count = test_inproc_bind_first (0, 0);
222 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
223}
224
225void test_infinite_both_inproc_connect_first ()
226{
227 int count = test_inproc_connect_first (0, 0);
228 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
229}
230
231void test_infinite_receive_inproc_bind_first ()
232{
233 int count = test_inproc_bind_first (1, 0);
234 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
235}
236
237void test_infinite_receive_inproc_connect_first ()
238{
239 int count = test_inproc_connect_first (1, 0);
240 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
241}
242
243void test_infinite_send_inproc_bind_first ()
244{
245 int count = test_inproc_bind_first (0, 1);
246 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
247}
248
249void test_infinite_send_inproc_connect_first ()
250{
251 int count = test_inproc_connect_first (0, 1);
252 TEST_ASSERT_EQUAL_INT (MAX_SENDS, count);
253}
254
255void test_finite_both_bind_first ()
256{
257 // Send and recv buffers hwm 1, so total that can be queued is 2
258 int count = test_inproc_bind_first (1, 1);
259 TEST_ASSERT_EQUAL_INT (2, count);
260}
261void test_finite_both_connect_first ()
262{
263 // Send and recv buffers hwm 1, so total that can be queued is 2
264 int count = test_inproc_connect_first (1, 1);
265 TEST_ASSERT_EQUAL_INT (2, count);
266}
267
268void test_infinite_recv_connect_and_close_first ()
269{
270 // Send hwm of 1, send before bind so total that can be queued is 1
271 int count = test_inproc_connect_and_close_first (1, 0);
272 TEST_ASSERT_EQUAL_INT (1, count);
273}
274
275void test_infinite_recv_bind_and_close_first ()
276{
277 // Send hwm of 1, send from bind side before connect so total that can be queued should be 1,
278 // however currently all messages get thrown away before the connect. BUG?
279 /*int count = */ test_inproc_bind_and_close_first (1, 0);
280 // TEST_ASSERT_EQUAL_INT (1, count);
281}
282
283int main (void)
284{
285 setup_test_environment ();
286
287 UNITY_BEGIN ();
288 RUN_TEST (test_defaults);
289
290 RUN_TEST (test_infinite_both_inproc_bind_first);
291 RUN_TEST (test_infinite_both_inproc_connect_first);
292
293 RUN_TEST (test_infinite_receive_inproc_bind_first);
294 RUN_TEST (test_infinite_receive_inproc_connect_first);
295
296 RUN_TEST (test_infinite_send_inproc_bind_first);
297 RUN_TEST (test_infinite_send_inproc_connect_first);
298
299 RUN_TEST (test_finite_both_bind_first);
300 RUN_TEST (test_finite_both_connect_first);
301
302 RUN_TEST (test_infinite_recv_connect_and_close_first);
303 RUN_TEST (test_infinite_recv_bind_and_close_first);
304
305 return UNITY_END ();
306}
307