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