1/*
2 Copyright (c) 2007-2017 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#include <string.h>
34
35SETUP_TEARDOWN_TESTCONTEXT
36
37void test_single_connect (int ipv6_)
38{
39 size_t len = MAX_SOCKET_STRING;
40 char my_endpoint[MAX_SOCKET_STRING];
41
42 void *sb = test_context_socket (ZMQ_REP);
43 bind_loopback (sb, ipv6_, my_endpoint, len);
44
45 void *sc = test_context_socket (ZMQ_REQ);
46 TEST_ASSERT_SUCCESS_ERRNO (
47 zmq_setsockopt (sc, ZMQ_IPV6, &ipv6_, sizeof (int)));
48 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint));
49
50 bounce (sb, sc);
51
52 // the sockets are disconnected and unbound explicitly in this test case
53 // to check that this can be done successfully with the expected
54 // endpoints/addresses
55
56 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint));
57
58 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb, my_endpoint));
59
60 test_context_socket_close (sc);
61 test_context_socket_close (sb);
62}
63
64void make_connect_address (char *connect_address_,
65 const int ipv6_,
66 const int port_,
67 const char *bind_address_)
68{
69 sprintf (connect_address_, "tcp://%s:%i;%s", ipv6_ ? "[::1]" : "127.0.0.1",
70 port_, strrchr (bind_address_, '/') + 1);
71}
72
73void test_multi_connect (int ipv6_)
74{
75 size_t len = MAX_SOCKET_STRING;
76 char my_endpoint_0[MAX_SOCKET_STRING];
77 char my_endpoint_1[MAX_SOCKET_STRING];
78 char my_endpoint_2[MAX_SOCKET_STRING];
79 char my_endpoint_3[MAX_SOCKET_STRING * 2];
80
81 void *sb0 = test_context_socket (ZMQ_REP);
82 bind_loopback (sb0, ipv6_, my_endpoint_0, len);
83
84 void *sb1 = test_context_socket (ZMQ_REP);
85 bind_loopback (sb1, ipv6_, my_endpoint_1, len);
86
87 void *sb2 = test_context_socket (ZMQ_REP);
88 bind_loopback (sb2, ipv6_, my_endpoint_2, len);
89
90 void *sc = test_context_socket (ZMQ_REQ);
91 TEST_ASSERT_SUCCESS_ERRNO (
92 zmq_setsockopt (sc, ZMQ_IPV6, &ipv6_, sizeof (int)));
93 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_0));
94 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_1));
95 make_connect_address (my_endpoint_3, ipv6_, 5564, my_endpoint_2);
96 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, my_endpoint_3));
97
98 bounce (sb0, sc);
99 bounce (sb1, sc);
100 bounce (sb2, sc);
101 bounce (sb0, sc);
102 bounce (sb1, sc);
103 bounce (sb2, sc);
104 bounce (sb0, sc);
105
106 /// see comment on zmq_disconnect/zmq_unbind in test_single_connect
107
108 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_0));
109 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_3));
110 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc, my_endpoint_1));
111
112 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb0, my_endpoint_0));
113 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb1, my_endpoint_1));
114 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb2, my_endpoint_2));
115
116 test_context_socket_close (sc);
117 test_context_socket_close (sb0);
118 test_context_socket_close (sb1);
119 test_context_socket_close (sb2);
120}
121
122void test_multi_connect_same_port (int ipv6_)
123{
124 size_t len = MAX_SOCKET_STRING;
125 char my_endpoint_0[MAX_SOCKET_STRING];
126 char my_endpoint_1[MAX_SOCKET_STRING];
127 char my_endpoint_2[MAX_SOCKET_STRING * 2];
128 char my_endpoint_3[MAX_SOCKET_STRING * 2];
129 char my_endpoint_4[MAX_SOCKET_STRING * 2];
130 char my_endpoint_5[MAX_SOCKET_STRING * 2];
131
132 void *sb0 = test_context_socket (ZMQ_REP);
133 bind_loopback (sb0, ipv6_, my_endpoint_0, len);
134
135 void *sb1 = test_context_socket (ZMQ_REP);
136 bind_loopback (sb1, ipv6_, my_endpoint_1, len);
137
138 void *sc0 = test_context_socket (ZMQ_REQ);
139 TEST_ASSERT_SUCCESS_ERRNO (
140 zmq_setsockopt (sc0, ZMQ_IPV6, &ipv6_, sizeof (int)));
141 make_connect_address (my_endpoint_2, ipv6_, 5564, my_endpoint_0);
142 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc0, my_endpoint_2));
143 make_connect_address (my_endpoint_3, ipv6_, 5565, my_endpoint_1);
144 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc0, my_endpoint_3));
145
146 void *sc1 = test_context_socket (ZMQ_REQ);
147 TEST_ASSERT_SUCCESS_ERRNO (
148 zmq_setsockopt (sc1, ZMQ_IPV6, &ipv6_, sizeof (int)));
149 make_connect_address (my_endpoint_4, ipv6_, 5565, my_endpoint_0);
150 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc1, my_endpoint_4));
151 make_connect_address (my_endpoint_5, ipv6_, 5564, my_endpoint_1);
152 TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc1, my_endpoint_5));
153
154 bounce (sb0, sc0);
155 bounce (sb1, sc0);
156 bounce (sb0, sc1);
157 bounce (sb1, sc1);
158 bounce (sb0, sc0);
159 bounce (sb1, sc0);
160
161 /// see comment on zmq_disconnect/zmq_unbind in test_single_connect
162
163 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc1, my_endpoint_4));
164 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc1, my_endpoint_5));
165 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc0, my_endpoint_2));
166 TEST_ASSERT_SUCCESS_ERRNO (zmq_disconnect (sc0, my_endpoint_3));
167
168 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb0, my_endpoint_0));
169 TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (sb1, my_endpoint_1));
170
171 test_context_socket_close (sc0);
172 test_context_socket_close (sc1);
173 test_context_socket_close (sb0);
174 test_context_socket_close (sb1);
175}
176
177void test_single_connect_ipv4 ()
178{
179 test_single_connect (false);
180}
181
182void test_multi_connect_ipv4 ()
183{
184 test_multi_connect (false);
185}
186
187void test_multi_connect_same_port_ipv4 ()
188{
189 test_multi_connect_same_port (false);
190}
191
192void test_single_connect_ipv6 ()
193{
194 test_single_connect (true);
195}
196
197void test_multi_connect_ipv6 ()
198{
199 test_multi_connect (true);
200}
201
202void test_multi_connect_same_port_ipv6 ()
203{
204 test_multi_connect_same_port (true);
205}
206
207int main (void)
208{
209 setup_test_environment ();
210
211 UNITY_BEGIN ();
212 RUN_TEST (test_single_connect_ipv4);
213 RUN_TEST (test_multi_connect_ipv4);
214 RUN_TEST (test_multi_connect_same_port_ipv4);
215 RUN_TEST (test_single_connect_ipv6);
216 RUN_TEST (test_multi_connect_ipv6);
217 RUN_TEST (test_multi_connect_same_port_ipv6);
218
219 return UNITY_END ();
220}
221