xref: /netbsd-src/external/mit/libuv/dist/test/test-tcp-bind-error.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "task.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 
28 static int close_cb_called = 0;
29 
30 
31 static void close_cb(uv_handle_t* handle) {
32   ASSERT(handle != NULL);
33   close_cb_called++;
34 }
35 
36 
37 TEST_IMPL(tcp_bind_error_addrinuse) {
38   struct sockaddr_in addr;
39   uv_tcp_t server1, server2;
40   int r;
41 
42   ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
43   r = uv_tcp_init(uv_default_loop(), &server1);
44   ASSERT(r == 0);
45   r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0);
46   ASSERT(r == 0);
47 
48   r = uv_tcp_init(uv_default_loop(), &server2);
49   ASSERT(r == 0);
50   r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0);
51   ASSERT(r == 0);
52 
53   r = uv_listen((uv_stream_t*)&server1, 128, NULL);
54   ASSERT(r == 0);
55   r = uv_listen((uv_stream_t*)&server2, 128, NULL);
56   ASSERT(r == UV_EADDRINUSE);
57 
58   uv_close((uv_handle_t*)&server1, close_cb);
59   uv_close((uv_handle_t*)&server2, close_cb);
60 
61   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
62 
63   ASSERT(close_cb_called == 2);
64 
65   MAKE_VALGRIND_HAPPY();
66   return 0;
67 }
68 
69 
70 TEST_IMPL(tcp_bind_error_addrnotavail_1) {
71   struct sockaddr_in addr;
72   uv_tcp_t server;
73   int r;
74 
75   ASSERT(0 == uv_ip4_addr("127.255.255.255", TEST_PORT, &addr));
76 
77   r = uv_tcp_init(uv_default_loop(), &server);
78   ASSERT(r == 0);
79 
80   /* It seems that Linux is broken here - bind succeeds. */
81   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
82   ASSERT(r == 0 || r == UV_EADDRNOTAVAIL);
83 
84   uv_close((uv_handle_t*)&server, close_cb);
85 
86   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
87 
88   ASSERT(close_cb_called == 1);
89 
90   MAKE_VALGRIND_HAPPY();
91   return 0;
92 }
93 
94 
95 TEST_IMPL(tcp_bind_error_addrnotavail_2) {
96   struct sockaddr_in addr;
97   uv_tcp_t server;
98   int r;
99 
100   ASSERT(0 == uv_ip4_addr("4.4.4.4", TEST_PORT, &addr));
101 
102   r = uv_tcp_init(uv_default_loop(), &server);
103   ASSERT(r == 0);
104   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
105   ASSERT(r == UV_EADDRNOTAVAIL);
106 
107   uv_close((uv_handle_t*)&server, close_cb);
108 
109   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
110 
111   ASSERT(close_cb_called == 1);
112 
113   MAKE_VALGRIND_HAPPY();
114   return 0;
115 }
116 
117 
118 TEST_IMPL(tcp_bind_error_fault) {
119   char garbage[] =
120       "blah blah blah blah blah blah blah blah blah blah blah blah";
121   struct sockaddr_in* garbage_addr;
122   uv_tcp_t server;
123   int r;
124 
125   garbage_addr = (struct sockaddr_in*) &garbage;
126 
127   r = uv_tcp_init(uv_default_loop(), &server);
128   ASSERT(r == 0);
129   r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0);
130   ASSERT(r == UV_EINVAL);
131 
132   uv_close((uv_handle_t*)&server, close_cb);
133 
134   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
135 
136   ASSERT(close_cb_called == 1);
137 
138   MAKE_VALGRIND_HAPPY();
139   return 0;
140 }
141 
142 /* Notes: On Linux uv_bind(server, NULL) will segfault the program.  */
143 
144 TEST_IMPL(tcp_bind_error_inval) {
145   struct sockaddr_in addr1;
146   struct sockaddr_in addr2;
147   uv_tcp_t server;
148   int r;
149 
150   ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1));
151   ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2));
152 
153   r = uv_tcp_init(uv_default_loop(), &server);
154   ASSERT(r == 0);
155   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0);
156   ASSERT(r == 0);
157   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0);
158   ASSERT(r == UV_EINVAL);
159 
160   uv_close((uv_handle_t*)&server, close_cb);
161 
162   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
163 
164   ASSERT(close_cb_called == 1);
165 
166   MAKE_VALGRIND_HAPPY();
167   return 0;
168 }
169 
170 
171 TEST_IMPL(tcp_bind_localhost_ok) {
172   struct sockaddr_in addr;
173   uv_tcp_t server;
174   int r;
175 
176   ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
177 
178   r = uv_tcp_init(uv_default_loop(), &server);
179   ASSERT(r == 0);
180   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
181   ASSERT(r == 0);
182 
183   MAKE_VALGRIND_HAPPY();
184   return 0;
185 }
186 
187 
188 TEST_IMPL(tcp_bind_invalid_flags) {
189   struct sockaddr_in addr;
190   uv_tcp_t server;
191   int r;
192 
193   ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
194 
195   r = uv_tcp_init(uv_default_loop(), &server);
196   ASSERT(r == 0);
197   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY);
198   ASSERT(r == UV_EINVAL);
199 
200   MAKE_VALGRIND_HAPPY();
201   return 0;
202 }
203 
204 
205 TEST_IMPL(tcp_listen_without_bind) {
206   int r;
207   uv_tcp_t server;
208 
209   r = uv_tcp_init(uv_default_loop(), &server);
210   ASSERT(r == 0);
211   r = uv_listen((uv_stream_t*)&server, 128, NULL);
212   ASSERT(r == 0);
213 
214   MAKE_VALGRIND_HAPPY();
215   return 0;
216 }
217 
218 
219 TEST_IMPL(tcp_bind_writable_flags) {
220   struct sockaddr_in addr;
221   uv_tcp_t server;
222   uv_buf_t buf;
223   uv_write_t write_req;
224   uv_shutdown_t shutdown_req;
225   int r;
226 
227   ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
228   r = uv_tcp_init(uv_default_loop(), &server);
229   ASSERT(r == 0);
230   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
231   ASSERT(r == 0);
232   r = uv_listen((uv_stream_t*)&server, 128, NULL);
233   ASSERT(r == 0);
234 
235   ASSERT(0 == uv_is_writable((uv_stream_t*) &server));
236   ASSERT(0 == uv_is_readable((uv_stream_t*) &server));
237 
238   buf = uv_buf_init("PING", 4);
239   r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL);
240   ASSERT(r == UV_EPIPE);
241   r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL);
242   ASSERT(r == UV_ENOTCONN);
243   r = uv_read_start((uv_stream_t*) &server, NULL, NULL);
244   ASSERT(r == UV_ENOTCONN);
245 
246   uv_close((uv_handle_t*)&server, close_cb);
247 
248   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
249 
250   ASSERT(close_cb_called == 1);
251 
252   MAKE_VALGRIND_HAPPY();
253   return 0;
254 }
255