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