Home | History | Annotate | Line # | Download | only in test
      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 connect_cb_called = 0;
     29 static int close_cb_called = 0;
     30 
     31 
     32 static void close_cb(uv_handle_t* handle) {
     33   ASSERT_NOT_NULL(handle);
     34   close_cb_called++;
     35 }
     36 
     37 
     38 static void connect_cb(uv_connect_t* req, int status) {
     39   ASSERT_EQ(status, UV_EADDRINUSE);
     40   uv_close((uv_handle_t*) req->handle, close_cb);
     41   connect_cb_called++;
     42 }
     43 
     44 
     45 TEST_IMPL(tcp_bind_error_addrinuse_connect) {
     46   struct sockaddr_in addr;
     47   int addrlen;
     48   uv_connect_t req;
     49   uv_tcp_t conn;
     50 
     51   /* 127.0.0.1:<TEST_PORT> is already taken by tcp4_echo_server running in
     52    * another process. uv_tcp_bind() and uv_tcp_connect() should still succeed
     53    * (greatest common denominator across platforms) but the connect callback
     54    * should receive an UV_EADDRINUSE error.
     55    */
     56   ASSERT_OK(uv_tcp_init(uv_default_loop(), &conn));
     57   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
     58   ASSERT_OK(uv_tcp_bind(&conn, (const struct sockaddr*) &addr, 0));
     59 
     60   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT + 1, &addr));
     61   ASSERT_OK(uv_tcp_connect(&req,
     62                            &conn,
     63                            (const struct sockaddr*) &addr,
     64                            connect_cb));
     65 
     66   addrlen = sizeof(addr);
     67   ASSERT_EQ(UV_EADDRINUSE, uv_tcp_getsockname(&conn,
     68                                               (struct sockaddr*) &addr,
     69                                               &addrlen));
     70 
     71   ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
     72   ASSERT_EQ(1, connect_cb_called);
     73   ASSERT_EQ(1, close_cb_called);
     74 
     75   MAKE_VALGRIND_HAPPY(uv_default_loop());
     76   return 0;
     77 }
     78 
     79 
     80 TEST_IMPL(tcp_bind_error_addrinuse_listen) {
     81   struct sockaddr_in addr;
     82   uv_tcp_t server1, server2;
     83   int r;
     84 
     85   ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
     86   r = uv_tcp_init(uv_default_loop(), &server1);
     87   ASSERT_OK(r);
     88   r = uv_tcp_bind(&server1, (const struct sockaddr*) &addr, 0);
     89   ASSERT_OK(r);
     90 
     91   r = uv_tcp_init(uv_default_loop(), &server2);
     92   ASSERT_OK(r);
     93   r = uv_tcp_bind(&server2, (const struct sockaddr*) &addr, 0);
     94   ASSERT_OK(r);
     95 
     96   r = uv_listen((uv_stream_t*)&server1, 128, NULL);
     97   ASSERT_OK(r);
     98   r = uv_listen((uv_stream_t*)&server2, 128, NULL);
     99   ASSERT_EQ(r, UV_EADDRINUSE);
    100 
    101   uv_close((uv_handle_t*)&server1, close_cb);
    102   uv_close((uv_handle_t*)&server2, close_cb);
    103 
    104   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    105 
    106   ASSERT_EQ(2, close_cb_called);
    107 
    108   MAKE_VALGRIND_HAPPY(uv_default_loop());
    109   return 0;
    110 }
    111 
    112 
    113 TEST_IMPL(tcp_bind_error_addrnotavail_1) {
    114   struct sockaddr_in addr;
    115   uv_tcp_t server;
    116   int r;
    117 
    118   ASSERT_OK(uv_ip4_addr("127.255.255.255", TEST_PORT, &addr));
    119 
    120   r = uv_tcp_init(uv_default_loop(), &server);
    121   ASSERT_OK(r);
    122 
    123   /* It seems that Linux is broken here - bind succeeds. */
    124   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
    125   ASSERT(r == 0 || r == UV_EADDRNOTAVAIL);
    126 
    127   uv_close((uv_handle_t*)&server, close_cb);
    128 
    129   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    130 
    131   ASSERT_EQ(1, close_cb_called);
    132 
    133   MAKE_VALGRIND_HAPPY(uv_default_loop());
    134   return 0;
    135 }
    136 
    137 
    138 TEST_IMPL(tcp_bind_error_addrnotavail_2) {
    139   struct sockaddr_in addr;
    140   uv_tcp_t server;
    141   int r;
    142 
    143   ASSERT_OK(uv_ip4_addr("4.4.4.4", TEST_PORT, &addr));
    144 
    145   r = uv_tcp_init(uv_default_loop(), &server);
    146   ASSERT_OK(r);
    147   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
    148   ASSERT_EQ(r, UV_EADDRNOTAVAIL);
    149 
    150   uv_close((uv_handle_t*)&server, close_cb);
    151 
    152   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    153 
    154   ASSERT_EQ(1, close_cb_called);
    155 
    156   MAKE_VALGRIND_HAPPY(uv_default_loop());
    157   return 0;
    158 }
    159 
    160 
    161 TEST_IMPL(tcp_bind_error_fault) {
    162   char garbage[] =
    163       "blah blah blah blah blah blah blah blah blah blah blah blah";
    164   struct sockaddr_in* garbage_addr;
    165   uv_tcp_t server;
    166   int r;
    167 
    168   garbage_addr = (struct sockaddr_in*) &garbage;
    169 
    170   r = uv_tcp_init(uv_default_loop(), &server);
    171   ASSERT_OK(r);
    172   r = uv_tcp_bind(&server, (const struct sockaddr*) garbage_addr, 0);
    173   ASSERT_EQ(r, UV_EINVAL);
    174 
    175   uv_close((uv_handle_t*)&server, close_cb);
    176 
    177   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    178 
    179   ASSERT_EQ(1, close_cb_called);
    180 
    181   MAKE_VALGRIND_HAPPY(uv_default_loop());
    182   return 0;
    183 }
    184 
    185 /* Notes: On Linux uv_bind(server, NULL) will segfault the program.  */
    186 
    187 TEST_IMPL(tcp_bind_error_inval) {
    188   struct sockaddr_in addr1;
    189   struct sockaddr_in addr2;
    190   uv_tcp_t server;
    191   int r;
    192 
    193   ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr1));
    194   ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT_2, &addr2));
    195 
    196   r = uv_tcp_init(uv_default_loop(), &server);
    197   ASSERT_OK(r);
    198   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr1, 0);
    199   ASSERT_OK(r);
    200   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr2, 0);
    201   ASSERT_EQ(r, UV_EINVAL);
    202 
    203   uv_close((uv_handle_t*)&server, close_cb);
    204 
    205   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    206 
    207   ASSERT_EQ(1, close_cb_called);
    208 
    209   MAKE_VALGRIND_HAPPY(uv_default_loop());
    210   return 0;
    211 }
    212 
    213 
    214 TEST_IMPL(tcp_bind_localhost_ok) {
    215   struct sockaddr_in addr;
    216   uv_tcp_t server;
    217   int r;
    218 
    219   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
    220 
    221   r = uv_tcp_init(uv_default_loop(), &server);
    222   ASSERT_OK(r);
    223   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
    224   ASSERT_OK(r);
    225 
    226   MAKE_VALGRIND_HAPPY(uv_default_loop());
    227   return 0;
    228 }
    229 
    230 
    231 TEST_IMPL(tcp_bind_invalid_flags) {
    232   struct sockaddr_in addr;
    233   uv_tcp_t server;
    234   int r;
    235 
    236   ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
    237 
    238   r = uv_tcp_init(uv_default_loop(), &server);
    239   ASSERT_OK(r);
    240   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, UV_TCP_IPV6ONLY);
    241   ASSERT_EQ(r, UV_EINVAL);
    242 
    243   MAKE_VALGRIND_HAPPY(uv_default_loop());
    244   return 0;
    245 }
    246 
    247 
    248 TEST_IMPL(tcp_listen_without_bind) {
    249   int r;
    250   uv_tcp_t server;
    251 
    252   r = uv_tcp_init(uv_default_loop(), &server);
    253   ASSERT_OK(r);
    254   r = uv_listen((uv_stream_t*)&server, 128, NULL);
    255   ASSERT_OK(r);
    256 
    257   MAKE_VALGRIND_HAPPY(uv_default_loop());
    258   return 0;
    259 }
    260 
    261 
    262 TEST_IMPL(tcp_bind_writable_flags) {
    263   struct sockaddr_in addr;
    264   uv_tcp_t server;
    265   uv_buf_t buf;
    266   uv_write_t write_req;
    267   uv_shutdown_t shutdown_req;
    268   int r;
    269 
    270   ASSERT_OK(uv_ip4_addr("0.0.0.0", TEST_PORT, &addr));
    271   r = uv_tcp_init(uv_default_loop(), &server);
    272   ASSERT_OK(r);
    273   r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
    274   ASSERT_OK(r);
    275   r = uv_listen((uv_stream_t*)&server, 128, NULL);
    276   ASSERT_OK(r);
    277 
    278   ASSERT_OK(uv_is_writable((uv_stream_t*) &server));
    279   ASSERT_OK(uv_is_readable((uv_stream_t*) &server));
    280 
    281   buf = uv_buf_init("PING", 4);
    282   r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL);
    283   ASSERT_EQ(r, UV_EPIPE);
    284   r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL);
    285   ASSERT_EQ(r, UV_ENOTCONN);
    286   r = uv_read_start((uv_stream_t*) &server,
    287                     (uv_alloc_cb) abort,
    288                     (uv_read_cb) abort);
    289   ASSERT_EQ(r, UV_ENOTCONN);
    290 
    291   uv_close((uv_handle_t*)&server, close_cb);
    292 
    293   uv_run(uv_default_loop(), UV_RUN_DEFAULT);
    294 
    295   ASSERT_EQ(1, close_cb_called);
    296 
    297   MAKE_VALGRIND_HAPPY(uv_default_loop());
    298   return 0;
    299 }
    300 
    301 TEST_IMPL(tcp_bind_or_listen_error_after_close) {
    302   uv_tcp_t tcp;
    303   struct sockaddr_in addr;
    304 
    305   memset(&addr, 0, sizeof(addr));
    306   addr.sin_addr.s_addr = htonl(INADDR_ANY);
    307   addr.sin_port = htons(9999);
    308   addr.sin_family = AF_INET;
    309 
    310   ASSERT_OK(uv_tcp_init(uv_default_loop(), &tcp));
    311   uv_close((uv_handle_t*) &tcp, NULL);
    312   ASSERT_EQ(uv_tcp_bind(&tcp, (struct sockaddr*) &addr, 0), UV_EINVAL);
    313   ASSERT_EQ(uv_listen((uv_stream_t*) &tcp, 5, NULL), UV_EINVAL);
    314   ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
    315   MAKE_VALGRIND_HAPPY(uv_default_loop());
    316   return 0;
    317 }
    318