Home | History | Annotate | Line # | Download | only in unittests
parse-connection-spec-selftests.c revision 1.1
      1  1.1  christos /* Self tests for parsing connection specs for GDB, the GNU debugger.
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 2018-2019 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GDB.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19  1.1  christos 
     20  1.1  christos #include "defs.h"
     21  1.1  christos #include "common/selftest.h"
     22  1.1  christos #include "common/netstuff.h"
     23  1.1  christos #include "diagnostics.h"
     24  1.1  christos #ifdef USE_WIN32API
     25  1.1  christos #if _WIN32_WINNT < 0x0501
     26  1.1  christos # undef _WIN32_WINNT
     27  1.1  christos # define _WIN32_WINNT 0x0501
     28  1.1  christos #endif
     29  1.1  christos #include <ws2tcpip.h>
     30  1.1  christos #else
     31  1.1  christos #include <netinet/in.h>
     32  1.1  christos #include <arpa/inet.h>
     33  1.1  christos #include <netdb.h>
     34  1.1  christos #include <sys/socket.h>
     35  1.1  christos #include <netinet/tcp.h>
     36  1.1  christos #endif
     37  1.1  christos 
     38  1.1  christos namespace selftests {
     39  1.1  christos namespace parse_connection_spec_tests {
     40  1.1  christos 
     41  1.1  christos /* Auxiliary struct that holds info about a specific test for a
     42  1.1  christos    connection spec.  */
     43  1.1  christos 
     44  1.1  christos struct parse_conn_test
     45  1.1  christos {
     46  1.1  christos   /* The connection spec.  */
     47  1.1  christos   const char *connspec;
     48  1.1  christos 
     49  1.1  christos   /* Expected result from 'parse_connection_spec'.  */
     50  1.1  christos   parsed_connection_spec expected_result;
     51  1.1  christos 
     52  1.1  christos   /* True if this test should fail, false otherwise.  If true, only
     53  1.1  christos      the CONNSPEC field should be considered as valid.  */
     54  1.1  christos   bool should_fail;
     55  1.1  christos 
     56  1.1  christos   /* The expected AI_FAMILY to be found on the 'struct addrinfo'
     57  1.1  christos      HINT.  */
     58  1.1  christos   int exp_ai_family;
     59  1.1  christos 
     60  1.1  christos   /* The expected AI_SOCKTYPE to be found on the 'struct addrinfo'
     61  1.1  christos      HINT.  */
     62  1.1  christos   int exp_ai_socktype;
     63  1.1  christos 
     64  1.1  christos   /* The expected AI_PROTOCOL to be found on the 'struct addrinfo'
     65  1.1  christos      HINT.  */
     66  1.1  christos   int exp_ai_protocol;
     67  1.1  christos };
     68  1.1  christos 
     69  1.1  christos /* Some defines to help us fill a 'struct parse_conn_test'.  */
     70  1.1  christos 
     71  1.1  christos /* Initialize a full entry.  */
     72  1.1  christos #define INIT_ENTRY(ADDR, EXP_HOST, EXP_PORT, SHOULD_FAIL, EXP_AI_FAMILY, \
     73  1.1  christos 		   EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL)			\
     74  1.1  christos   { ADDR, { EXP_HOST, EXP_PORT }, SHOULD_FAIL, EXP_AI_FAMILY, \
     75  1.1  christos     EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL }
     76  1.1  christos 
     77  1.1  christos /* Initialize an unprefixed entry.  In this case, we don't expect
     78  1.1  christos    anything on the 'struct addrinfo' HINT.  */
     79  1.1  christos #define INIT_UNPREFIXED_ENTRY(ADDR, EXP_HOST, EXP_PORT) \
     80  1.1  christos   INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, 0, 0, 0)
     81  1.1  christos 
     82  1.1  christos /* Initialized an unprefixed IPv6 entry.  In this case, we don't
     83  1.1  christos    expect anything on the 'struct addrinfo' HINT.  */
     84  1.1  christos #define INIT_UNPREFIXED_IPV6_ENTRY(ADDR, EXP_HOST, EXP_PORT) \
     85  1.1  christos   INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, AF_INET6, 0, 0)
     86  1.1  christos 
     87  1.1  christos /* Initialize a prefixed entry.  */
     88  1.1  christos #define INIT_PREFIXED_ENTRY(ADDR, EXP_HOST, EXP_PORT, EXP_AI_FAMILY, \
     89  1.1  christos 			    EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL) \
     90  1.1  christos   INIT_ENTRY (ADDR, EXP_HOST, EXP_PORT, false, EXP_AI_FAMILY, \
     91  1.1  christos 	      EXP_AI_SOCKTYPE, EXP_AI_PROTOCOL)
     92  1.1  christos 
     93  1.1  christos /* Initialize an entry prefixed with "tcp4:".  */
     94  1.1  christos #define INIT_PREFIXED_IPV4_TCP(ADDR, EXP_HOST, EXP_PORT) \
     95  1.1  christos   INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET, SOCK_STREAM, \
     96  1.1  christos 		       IPPROTO_TCP)
     97  1.1  christos 
     98  1.1  christos /* Initialize an entry prefixed with "tcp6:".  */
     99  1.1  christos #define INIT_PREFIXED_IPV6_TCP(ADDR, EXP_HOST, EXP_PORT) \
    100  1.1  christos   INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET6, SOCK_STREAM, \
    101  1.1  christos 		       IPPROTO_TCP)
    102  1.1  christos 
    103  1.1  christos /* Initialize an entry prefixed with "udp4:".  */
    104  1.1  christos #define INIT_PREFIXED_IPV4_UDP(ADDR, EXP_HOST, EXP_PORT) \
    105  1.1  christos   INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET, SOCK_DGRAM, \
    106  1.1  christos 		       IPPROTO_UDP)
    107  1.1  christos 
    108  1.1  christos /* Initialize an entry prefixed with "udp6:".  */
    109  1.1  christos #define INIT_PREFIXED_IPV6_UDP(ADDR, EXP_HOST, EXP_PORT) \
    110  1.1  christos   INIT_PREFIXED_ENTRY (ADDR, EXP_HOST, EXP_PORT, AF_INET6, SOCK_DGRAM, \
    111  1.1  christos 		       IPPROTO_UDP)
    112  1.1  christos 
    113  1.1  christos /* Initialize a bogus entry, i.e., a connection spec that should
    114  1.1  christos    fail.  */
    115  1.1  christos #define INIT_BOGUS_ENTRY(ADDR) \
    116  1.1  christos   INIT_ENTRY (ADDR, "", "", true, 0, 0, 0)
    117  1.1  christos 
    118  1.1  christos /* The variable which holds all of our tests.  */
    119  1.1  christos 
    120  1.1  christos static const parse_conn_test conn_test[] =
    121  1.1  christos   {
    122  1.1  christos     /* Unprefixed addresses.  */
    123  1.1  christos 
    124  1.1  christos     /* IPv4, host and port present.  */
    125  1.1  christos     INIT_UNPREFIXED_ENTRY ("127.0.0.1:1234", "127.0.0.1", "1234"),
    126  1.1  christos     /* IPv4, only host.  */
    127  1.1  christos     INIT_UNPREFIXED_ENTRY ("127.0.0.1", "127.0.0.1", ""),
    128  1.1  christos     /* IPv4, missing port.  */
    129  1.1  christos     INIT_UNPREFIXED_ENTRY ("127.0.0.1:", "127.0.0.1", ""),
    130  1.1  christos 
    131  1.1  christos     /* IPv6, host and port present, no brackets.  */
    132  1.1  christos     INIT_UNPREFIXED_ENTRY ("::1:1234", "::1", "1234"),
    133  1.1  christos     /* IPv6, missing port, no brackets.  */
    134  1.1  christos     INIT_UNPREFIXED_ENTRY ("::1:", "::1", ""),
    135  1.1  christos     /* IPv6, host and port present, with brackets.  */
    136  1.1  christos     INIT_UNPREFIXED_IPV6_ENTRY ("[::1]:1234", "::1", "1234"),
    137  1.1  christos     /* IPv6, only host, with brackets.  */
    138  1.1  christos     INIT_UNPREFIXED_IPV6_ENTRY ("[::1]", "::1", ""),
    139  1.1  christos     /* IPv6, missing port, with brackets.  */
    140  1.1  christos     INIT_UNPREFIXED_IPV6_ENTRY ("[::1]:", "::1", ""),
    141  1.1  christos 
    142  1.1  christos     /* Unspecified, only port.  */
    143  1.1  christos     INIT_UNPREFIXED_ENTRY (":1234", "localhost", "1234"),
    144  1.1  christos 
    145  1.1  christos     /* Prefixed addresses.  */
    146  1.1  christos 
    147  1.1  christos     /* Prefixed "tcp4:" IPv4, host and port presents.  */
    148  1.1  christos     INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1:1234", "127.0.0.1", "1234"),
    149  1.1  christos     /* Prefixed "tcp4:" IPv4, only port.  */
    150  1.1  christos     INIT_PREFIXED_IPV4_TCP ("tcp4::1234", "localhost", "1234"),
    151  1.1  christos     /* Prefixed "tcp4:" IPv4, only host.  */
    152  1.1  christos     INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1", "127.0.0.1", ""),
    153  1.1  christos     /* Prefixed "tcp4:" IPv4, missing port.  */
    154  1.1  christos     INIT_PREFIXED_IPV4_TCP ("tcp4:127.0.0.1:", "127.0.0.1", ""),
    155  1.1  christos 
    156  1.1  christos     /* Prefixed "udp4:" IPv4, host and port present.  */
    157  1.1  christos     INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1:1234", "127.0.0.1", "1234"),
    158  1.1  christos     /* Prefixed "udp4:" IPv4, only port.  */
    159  1.1  christos     INIT_PREFIXED_IPV4_UDP ("udp4::1234", "localhost", "1234"),
    160  1.1  christos     /* Prefixed "udp4:" IPv4, only host.  */
    161  1.1  christos     INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1", "127.0.0.1", ""),
    162  1.1  christos     /* Prefixed "udp4:" IPv4, missing port.  */
    163  1.1  christos     INIT_PREFIXED_IPV4_UDP ("udp4:127.0.0.1:", "127.0.0.1", ""),
    164  1.1  christos 
    165  1.1  christos 
    166  1.1  christos     /* Prefixed "tcp6:" IPv6, host and port present.  */
    167  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6:::1:1234", "::1", "1234"),
    168  1.1  christos     /* Prefixed "tcp6:" IPv6, only port.  */
    169  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6::1234", "localhost", "1234"),
    170  1.1  christos     /* Prefixed "tcp6:" IPv6, only host.  */
    171  1.1  christos     //INIT_PREFIXED_IPV6_TCP ("tcp6:::1", "::1", ""),
    172  1.1  christos     /* Prefixed "tcp6:" IPv6, missing port.  */
    173  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6:::1:", "::1", ""),
    174  1.1  christos 
    175  1.1  christos     /* Prefixed "udp6:" IPv6, host and port present.  */
    176  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6:::1:1234", "::1", "1234"),
    177  1.1  christos     /* Prefixed "udp6:" IPv6, only port.  */
    178  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6::1234", "localhost", "1234"),
    179  1.1  christos     /* Prefixed "udp6:" IPv6, only host.  */
    180  1.1  christos     //INIT_PREFIXED_IPV6_UDP ("udp6:::1", "::1", ""),
    181  1.1  christos     /* Prefixed "udp6:" IPv6, missing port.  */
    182  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6:::1:", "::1", ""),
    183  1.1  christos 
    184  1.1  christos     /* Prefixed "tcp6:" IPv6 with brackets, host and port present.  */
    185  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]:1234", "::1", "1234"),
    186  1.1  christos     /* Prefixed "tcp6:" IPv6 with brackets, only host.  */
    187  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]", "::1", ""),
    188  1.1  christos     /* Prefixed "tcp6:" IPv6 with brackets, missing port.  */
    189  1.1  christos     INIT_PREFIXED_IPV6_TCP ("tcp6:[::1]:", "::1", ""),
    190  1.1  christos 
    191  1.1  christos     /* Prefixed "udp6:" IPv6 with brackets, host and port present.  */
    192  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6:[::1]:1234", "::1", "1234"),
    193  1.1  christos     /* Prefixed "udp6:" IPv6 with brackets, only host.  */
    194  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6:[::1]", "::1", ""),
    195  1.1  christos     /* Prefixed "udp6:" IPv6 with brackets, missing port.  */
    196  1.1  christos     INIT_PREFIXED_IPV6_UDP ("udp6:[::1]:", "::1", ""),
    197  1.1  christos 
    198  1.1  christos 
    199  1.1  christos     /* Bogus addresses.  */
    200  1.1  christos     INIT_BOGUS_ENTRY ("tcp6:[::1]123:44"),
    201  1.1  christos     INIT_BOGUS_ENTRY ("[::1"),
    202  1.1  christos     INIT_BOGUS_ENTRY ("tcp6:::1]:"),
    203  1.1  christos   };
    204  1.1  christos 
    205  1.1  christos /* Test a connection spec C.  */
    206  1.1  christos 
    207  1.1  christos static void
    208  1.1  christos test_conn (const parse_conn_test &c)
    209  1.1  christos {
    210  1.1  christos   struct addrinfo hint;
    211  1.1  christos   parsed_connection_spec ret;
    212  1.1  christos 
    213  1.1  christos   memset (&hint, 0, sizeof (hint));
    214  1.1  christos 
    215  1.1  christos   TRY
    216  1.1  christos     {
    217  1.1  christos       ret = parse_connection_spec (c.connspec, &hint);
    218  1.1  christos     }
    219  1.1  christos   CATCH (ex, RETURN_MASK_ERROR)
    220  1.1  christos     {
    221  1.1  christos       /* If we caught an error, we should check if this connection
    222  1.1  christos 	 spec was supposed to fail.  */
    223  1.1  christos       SELF_CHECK (c.should_fail);
    224  1.1  christos       return;
    225  1.1  christos     }
    226  1.1  christos   END_CATCH
    227  1.1  christos 
    228  1.1  christos   SELF_CHECK (!c.should_fail);
    229  1.1  christos   SELF_CHECK (ret.host_str == c.expected_result.host_str);
    230  1.1  christos   SELF_CHECK (ret.port_str == c.expected_result.port_str);
    231  1.1  christos   SELF_CHECK (hint.ai_family == c.exp_ai_family);
    232  1.1  christos   SELF_CHECK (hint.ai_socktype == c.exp_ai_socktype);
    233  1.1  christos   SELF_CHECK (hint.ai_protocol == c.exp_ai_protocol);
    234  1.1  christos }
    235  1.1  christos 
    236  1.1  christos /* Run the tests associated with parsing connection specs.  */
    237  1.1  christos 
    238  1.1  christos static void
    239  1.1  christos run_tests ()
    240  1.1  christos {
    241  1.1  christos   for (const parse_conn_test &c : conn_test)
    242  1.1  christos     test_conn (c);
    243  1.1  christos }
    244  1.1  christos } /* namespace parse_connection_spec_tests */
    245  1.1  christos } /* namespace selftests */
    246  1.1  christos 
    247  1.1  christos void
    248  1.1  christos _initialize_parse_connection_spec_selftests ()
    249  1.1  christos {
    250  1.1  christos   selftests::register_test ("parse_connection_spec",
    251  1.1  christos 			    selftests::parse_connection_spec_tests::run_tests);
    252  1.1  christos }
    253