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