parse-connection-spec-selftests.c revision 1.1.1.4 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