1#include "config.h"
2#include "mock-resolver.h"
3
4#include <gio/gio.h>
5#include <gio/gnetworking.h>
6
7static void
8test_basic (void)
9{
10 GNetworkAddress *address;
11 guint port;
12 gchar *hostname;
13 gchar *scheme;
14
15 address = (GNetworkAddress*)g_network_address_new (hostname: "www.gnome.org", port: 8080);
16
17 g_assert_cmpstr (g_network_address_get_hostname (address), ==, "www.gnome.org");
18 g_assert_cmpint (g_network_address_get_port (address), ==, 8080);
19
20 g_object_get (object: address, first_property_name: "hostname", &hostname, "port", &port, "scheme", &scheme, NULL);
21 g_assert_cmpstr (hostname, ==, "www.gnome.org");
22 g_assert_cmpint (port, ==, 8080);
23 g_assert (scheme == NULL);
24 g_free (mem: hostname);
25
26 g_object_unref (object: address);
27}
28
29typedef struct {
30 const gchar *input;
31 const gchar *scheme;
32 const gchar *hostname;
33 guint16 port;
34 gint error_code;
35} ParseTest;
36
37static ParseTest uri_tests[] = {
38 { "http://www.gnome.org:2020/start", "http", "www.gnome.org", 2020, -1 },
39 { "ftp://joe~:(*)%46@ftp.gnome.org:2020/start", "ftp", "ftp.gnome.org", 2020, -1 },
40 { "ftp://[fec0::abcd]/start", "ftp", "fec0::abcd", 8080, -1 },
41 { "ftp://[fec0::abcd]:999/start", "ftp", "fec0::abcd", 999, -1 },
42 { "ftp://joe%x-@ftp.gnome.org:2020/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
43 { "http://[fec0::abcd%em1]/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
44 { "http://[fec0::abcd%25em1]/start", "http", "fec0::abcd%em1", 8080, -1 },
45 { "http://[fec0::abcd%10]/start", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
46 { "http://[fec0::abcd%25em%31]/start", "http", "fec0::abcd%em1", 8080, -1 },
47 { "ftp://ftp.gnome.org/start?foo=bar@baz", "ftp", "ftp.gnome.org", 8080, -1 }
48};
49
50static void
51test_parse_uri (gconstpointer d)
52{
53 const ParseTest *test = d;
54 GNetworkAddress *address;
55 GError *error;
56
57 error = NULL;
58 address = (GNetworkAddress*)g_network_address_parse_uri (uri: test->input, default_port: 8080, error: &error);
59
60 if (address)
61 {
62 g_assert_cmpstr (g_network_address_get_scheme (address), ==, test->scheme);
63 g_assert_cmpstr (g_network_address_get_hostname (address), ==, test->hostname);
64 g_assert_cmpint (g_network_address_get_port (address), ==, test->port);
65 g_assert_no_error (error);
66 }
67 else
68 g_assert_error (error, G_IO_ERROR, test->error_code);
69
70 if (address)
71 g_object_unref (object: address);
72 if (error)
73 g_error_free (error);
74}
75
76static ParseTest host_tests[] =
77{
78 { "www.gnome.org", NULL, "www.gnome.org", 1234, -1 },
79 { "www.gnome.org:8080", NULL, "www.gnome.org", 8080, -1 },
80 { "[2001:db8::1]", NULL, "2001:db8::1", 1234, -1 },
81 { "[2001:db8::1]:888", NULL, "2001:db8::1", 888, -1 },
82 { "[2001:db8::1%em1]", NULL, "2001:db8::1%em1", 1234, -1 },
83 { "[2001:db8::1%25em1]", NULL, "2001:db8::1%25em1", 1234, -1 },
84 { "[hostname", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
85 { "[hostnam]e", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
86 { "hostname:", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
87 { "hostname:-1", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT },
88 { "hostname:9999999", NULL, NULL, 0, G_IO_ERROR_INVALID_ARGUMENT }
89};
90
91static void
92test_parse_host (gconstpointer d)
93{
94 const ParseTest *test = d;
95 GNetworkAddress *address;
96 GError *error;
97
98 error = NULL;
99 address = (GNetworkAddress*)g_network_address_parse (host_and_port: test->input, default_port: 1234, error: &error);
100
101 if (address)
102 {
103 g_assert_null (g_network_address_get_scheme (address));
104 g_assert_cmpstr (g_network_address_get_hostname (address), ==, test->hostname);
105 g_assert_cmpint (g_network_address_get_port (address), ==, test->port);
106 g_assert_no_error (error);
107 }
108 else
109 {
110 g_assert_error (error, G_IO_ERROR, test->error_code);
111 }
112
113 if (address)
114 g_object_unref (object: address);
115 if (error)
116 g_error_free (error);
117}
118
119typedef struct {
120 const gchar *input;
121 gboolean valid_parse, valid_resolve, valid_ip;
122} ResolveTest;
123
124static ResolveTest address_tests[] = {
125 { "192.168.1.2", TRUE, TRUE, TRUE },
126 { "fe80::42", TRUE, TRUE, TRUE },
127
128 /* g_network_address_parse() accepts these, but they are not
129 * (just) IP addresses.
130 */
131 { "192.168.1.2:80", TRUE, FALSE, FALSE },
132 { "[fe80::42]", TRUE, FALSE, FALSE },
133 { "[fe80::42]:80", TRUE, FALSE, FALSE },
134
135 /* These should not be considered IP addresses by anyone. */
136 { "192.168.258", FALSE, FALSE, FALSE },
137 { "192.11010306", FALSE, FALSE, FALSE },
138 { "3232235778", FALSE, FALSE, FALSE },
139 { "0300.0250.0001.0001", FALSE, FALSE, FALSE },
140 { "0xC0.0xA8.0x01.0x02", FALSE, FALSE, FALSE },
141 { "0xc0.0xa8.0x01.0x02", FALSE, FALSE, FALSE },
142 { "0xc0a80102", FALSE, FALSE, FALSE }
143};
144
145static void
146test_resolve_address (gconstpointer d)
147{
148 const ResolveTest *test = d;
149 GSocketConnectable *connectable;
150 GSocketAddressEnumerator *addr_enum;
151 GSocketAddress *addr;
152 GError *error = NULL;
153
154 g_test_message (format: "Input: %s", test->input);
155
156 g_assert_cmpint (test->valid_ip, ==, g_hostname_is_ip_address (test->input));
157
158 connectable = g_network_address_parse (host_and_port: test->input, default_port: 1234, error: &error);
159 g_assert_no_error (error);
160
161 addr_enum = g_socket_connectable_enumerate (connectable);
162 addr = g_socket_address_enumerator_next (enumerator: addr_enum, NULL, error: &error);
163 g_object_unref (object: addr_enum);
164 g_object_unref (object: connectable);
165
166 if (addr)
167 {
168 g_assert_true (test->valid_parse);
169 g_assert_true (G_IS_INET_SOCKET_ADDRESS (addr));
170 g_object_unref (object: addr);
171 }
172 else
173 {
174 g_assert_false (test->valid_parse);
175 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
176 g_error_free (error);
177 return;
178 }
179}
180
181/* Technically this should be in a GResolver test program, but we don't
182 * have one of those since it's mostly impossible to test programmatically.
183 * So it goes here so it can share the tests.
184 */
185static void
186test_resolve_address_gresolver (gconstpointer d)
187{
188 const ResolveTest *test = d;
189 GResolver *resolver;
190 GList *addrs;
191 GInetAddress *iaddr;
192 GError *error = NULL;
193
194 g_test_message (format: "Input: %s", test->input);
195
196 resolver = g_resolver_get_default ();
197 addrs = g_resolver_lookup_by_name (resolver, hostname: test->input, NULL, error: &error);
198 g_object_unref (object: resolver);
199
200 if (addrs)
201 {
202 g_assert_true (test->valid_resolve);
203 g_assert_cmpint (g_list_length (addrs), ==, 1);
204
205 iaddr = addrs->data;
206 g_assert_true (G_IS_INET_ADDRESS (iaddr));
207
208 g_object_unref (object: iaddr);
209 g_list_free (list: addrs);
210 }
211 else
212 {
213 g_assert_nonnull (error);
214 g_test_message (format: "Error: %s", error->message);
215 g_assert_false (test->valid_resolve);
216
217 if (!test->valid_parse)
218 {
219 /* GResolver should have rejected the address internally, in
220 * which case we're guaranteed to get G_RESOLVER_ERROR_NOT_FOUND.
221 */
222 g_assert_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND);
223 }
224 else
225 {
226 /* If GResolver didn't reject the string itself, then we
227 * might have attempted to send it over the network. If that
228 * attempt succeeded, we'd get back NOT_FOUND, but if
229 * there's no network available we might have gotten some
230 * other error instead.
231 */
232 }
233
234 g_error_free (error);
235 return;
236 }
237}
238
239#define SCOPE_ID_TEST_ADDR "fe80::42"
240#define SCOPE_ID_TEST_PORT 99
241
242#if defined (HAVE_IF_INDEXTONAME) && defined (HAVE_IF_NAMETOINDEX)
243static char SCOPE_ID_TEST_IFNAME[IF_NAMESIZE];
244static int SCOPE_ID_TEST_INDEX;
245#else
246#define SCOPE_ID_TEST_IFNAME "1"
247#define SCOPE_ID_TEST_INDEX 1
248#endif
249
250static void
251find_ifname_and_index (void)
252{
253 if (SCOPE_ID_TEST_INDEX != 0)
254 return;
255
256#if defined (HAVE_IF_INDEXTONAME) && defined (HAVE_IF_NAMETOINDEX)
257 SCOPE_ID_TEST_INDEX = if_nametoindex (ifname: "lo");
258 if (SCOPE_ID_TEST_INDEX != 0)
259 {
260 g_strlcpy (dest: SCOPE_ID_TEST_IFNAME, src: "lo", dest_size: sizeof (SCOPE_ID_TEST_IFNAME));
261 return;
262 }
263
264 for (SCOPE_ID_TEST_INDEX = 1; SCOPE_ID_TEST_INDEX < 1024; SCOPE_ID_TEST_INDEX++) {
265 if (if_indextoname (ifindex: SCOPE_ID_TEST_INDEX, ifname: SCOPE_ID_TEST_IFNAME))
266 break;
267 }
268 g_assert_cmpstr (SCOPE_ID_TEST_IFNAME, !=, "");
269#endif
270}
271
272static void
273test_scope_id (GSocketConnectable *addr)
274{
275#ifndef G_OS_WIN32
276 GSocketAddressEnumerator *addr_enum;
277 GSocketAddress *saddr;
278 GInetSocketAddress *isaddr;
279 GInetAddress *iaddr;
280 char *tostring;
281 GError *error = NULL;
282
283 addr_enum = g_socket_connectable_enumerate (connectable: addr);
284 saddr = g_socket_address_enumerator_next (enumerator: addr_enum, NULL, error: &error);
285 g_assert_no_error (error);
286
287 g_assert (saddr != NULL);
288 g_assert (G_IS_INET_SOCKET_ADDRESS (saddr));
289
290 isaddr = G_INET_SOCKET_ADDRESS (saddr);
291 g_assert_cmpint (g_inet_socket_address_get_scope_id (isaddr), ==, SCOPE_ID_TEST_INDEX);
292 g_assert_cmpint (g_inet_socket_address_get_port (isaddr), ==, SCOPE_ID_TEST_PORT);
293
294 iaddr = g_inet_socket_address_get_address (address: isaddr);
295 tostring = g_inet_address_to_string (address: iaddr);
296 g_assert_cmpstr (tostring, ==, SCOPE_ID_TEST_ADDR);
297 g_free (mem: tostring);
298
299 g_object_unref (object: saddr);
300 saddr = g_socket_address_enumerator_next (enumerator: addr_enum, NULL, error: &error);
301 g_assert_no_error (error);
302 g_assert (saddr == NULL);
303
304 g_object_unref (object: addr_enum);
305#else
306 g_test_skip ("winsock2 getaddrinfo() can’t understand scope IDs");
307#endif
308}
309
310static void
311test_host_scope_id (void)
312{
313 GSocketConnectable *addr;
314 char *str;
315
316 find_ifname_and_index ();
317
318 str = g_strdup_printf (format: "%s%%%s", SCOPE_ID_TEST_ADDR, SCOPE_ID_TEST_IFNAME);
319 addr = g_network_address_new (hostname: str, SCOPE_ID_TEST_PORT);
320 g_free (mem: str);
321
322 test_scope_id (addr);
323 g_object_unref (object: addr);
324}
325
326static void
327test_uri_scope_id (void)
328{
329 GSocketConnectable *addr;
330 char *uri;
331 GError *error = NULL;
332
333 find_ifname_and_index ();
334
335 uri = g_strdup_printf (format: "http://[%s%%%s]:%d/foo",
336 SCOPE_ID_TEST_ADDR,
337 SCOPE_ID_TEST_IFNAME,
338 SCOPE_ID_TEST_PORT);
339 addr = g_network_address_parse_uri (uri, default_port: 0, error: &error);
340 g_free (mem: uri);
341 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
342 g_assert_null (addr);
343 g_clear_error (err: &error);
344
345 uri = g_strdup_printf (format: "http://[%s%%25%s]:%d/foo",
346 SCOPE_ID_TEST_ADDR,
347 SCOPE_ID_TEST_IFNAME,
348 SCOPE_ID_TEST_PORT);
349 addr = g_network_address_parse_uri (uri, default_port: 0, error: &error);
350 g_free (mem: uri);
351 g_assert_no_error (error);
352
353 test_scope_id (addr);
354 g_object_unref (object: addr);
355}
356
357static void
358test_loopback_basic (void)
359{
360 GNetworkAddress *addr; /* owned */
361
362 addr = G_NETWORK_ADDRESS (g_network_address_new_loopback (666));
363
364 /* Test basic properties. */
365 g_assert_cmpstr (g_network_address_get_hostname (addr), ==, "localhost");
366 g_assert_cmpuint (g_network_address_get_port (addr), ==, 666);
367 g_assert_null (g_network_address_get_scheme (addr));
368
369 g_object_unref (object: addr);
370}
371
372static void
373assert_socket_address_matches (GSocketAddress *a,
374 const gchar *expected_address,
375 guint16 expected_port)
376{
377 GInetSocketAddress *sa;
378 gchar *str; /* owned */
379
380 g_assert (G_IS_INET_SOCKET_ADDRESS (a));
381
382 sa = G_INET_SOCKET_ADDRESS (a);
383 g_assert_cmpint (g_inet_socket_address_get_port (sa), ==, expected_port);
384
385 str = g_inet_address_to_string (address: g_inet_socket_address_get_address (address: sa));
386 g_assert_cmpstr (str, ==, expected_address);
387 g_free (mem: str);
388}
389
390static void
391test_loopback_sync (void)
392{
393 GSocketConnectable *addr; /* owned */
394 GSocketAddressEnumerator *enumerator; /* owned */
395 GSocketAddress *a; /* owned */
396 GError *error = NULL;
397
398 addr = g_network_address_new_loopback (port: 616);
399 enumerator = g_socket_connectable_enumerate (connectable: addr);
400
401 /* IPv6 address. */
402 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
403 g_assert_no_error (error);
404 assert_socket_address_matches (a, expected_address: "::1", expected_port: 616);
405 g_object_unref (object: a);
406
407 /* IPv4 address. */
408 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
409 g_assert_no_error (error);
410 assert_socket_address_matches (a, expected_address: "127.0.0.1", expected_port: 616);
411 g_object_unref (object: a);
412
413 /* End of results. */
414 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
415 g_assert_no_error (error);
416
417 g_object_unref (object: enumerator);
418 g_object_unref (object: addr);
419}
420
421static void
422test_localhost_sync (void)
423{
424 GSocketConnectable *addr; /* owned */
425 GSocketAddressEnumerator *enumerator; /* owned */
426 GSocketAddress *a; /* owned */
427 GError *error = NULL;
428 GResolver *original_resolver; /* owned */
429 MockResolver *mock_resolver; /* owned */
430 GList *ipv4_results = NULL; /* owned */
431
432 /* This test ensures that variations of the "localhost" hostname always resolve to a loopback address */
433
434 /* Set up a DNS resolver that returns nonsense for "localhost" */
435 original_resolver = g_resolver_get_default ();
436 mock_resolver = mock_resolver_new ();
437 g_resolver_set_default (G_RESOLVER (mock_resolver));
438 ipv4_results = g_list_append (list: ipv4_results, data: g_inet_address_new_from_string (string: "123.123.123.123"));
439 mock_resolver_set_ipv4_results (self: mock_resolver, results: ipv4_results);
440
441 addr = g_network_address_new (hostname: "localhost.", port: 616);
442 enumerator = g_socket_connectable_enumerate (connectable: addr);
443
444 /* IPv6 address. */
445 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
446 g_assert_no_error (error);
447 assert_socket_address_matches (a, expected_address: "::1", expected_port: 616);
448 g_object_unref (object: a);
449
450 /* IPv4 address. */
451 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
452 g_assert_no_error (error);
453 assert_socket_address_matches (a, expected_address: "127.0.0.1", expected_port: 616);
454 g_object_unref (object: a);
455
456 /* End of results. */
457 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
458 g_assert_no_error (error);
459 g_object_unref (object: enumerator);
460 g_object_unref (object: addr);
461
462 addr = g_network_address_new (hostname: ".localhost", port: 616);
463 enumerator = g_socket_connectable_enumerate (connectable: addr);
464
465 /* IPv6 address. */
466 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
467 g_assert_no_error (error);
468 assert_socket_address_matches (a, expected_address: "::1", expected_port: 616);
469 g_object_unref (object: a);
470
471 /* IPv4 address. */
472 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
473 g_assert_no_error (error);
474 assert_socket_address_matches (a, expected_address: "127.0.0.1", expected_port: 616);
475 g_object_unref (object: a);
476
477 /* End of results. */
478 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
479 g_assert_no_error (error);
480 g_object_unref (object: enumerator);
481 g_object_unref (object: addr);
482
483 addr = g_network_address_new (hostname: "foo.localhost", port: 616);
484 enumerator = g_socket_connectable_enumerate (connectable: addr);
485
486 /* IPv6 address. */
487 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
488 g_assert_no_error (error);
489 assert_socket_address_matches (a, expected_address: "::1", expected_port: 616);
490 g_object_unref (object: a);
491
492 /* IPv4 address. */
493 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
494 g_assert_no_error (error);
495 assert_socket_address_matches (a, expected_address: "127.0.0.1", expected_port: 616);
496 g_object_unref (object: a);
497
498 /* End of results. */
499 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
500 g_assert_no_error (error);
501 g_object_unref (object: enumerator);
502 g_object_unref (object: addr);
503
504 addr = g_network_address_new (hostname: ".localhost.", port: 616);
505 enumerator = g_socket_connectable_enumerate (connectable: addr);
506
507 /* IPv6 address. */
508 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
509 g_assert_no_error (error);
510 assert_socket_address_matches (a, expected_address: "::1", expected_port: 616);
511 g_object_unref (object: a);
512
513 /* IPv4 address. */
514 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
515 g_assert_no_error (error);
516 assert_socket_address_matches (a, expected_address: "127.0.0.1", expected_port: 616);
517 g_object_unref (object: a);
518
519 /* End of results. */
520 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
521 g_assert_no_error (error);
522 g_object_unref (object: enumerator);
523 g_object_unref (object: addr);
524
525 addr = g_network_address_new (hostname: "invalid", port: 616);
526 enumerator = g_socket_connectable_enumerate (connectable: addr);
527
528 /* IPv4 address. */
529 a = g_socket_address_enumerator_next (enumerator, NULL, error: &error);
530 g_assert_no_error (error);
531 assert_socket_address_matches (a, expected_address: "123.123.123.123", expected_port: 616);
532 g_object_unref (object: a);
533
534 /* End of results. */
535 g_assert_null (g_socket_address_enumerator_next (enumerator, NULL, &error));
536 g_assert_no_error (error);
537 g_object_unref (object: enumerator);
538 g_object_unref (object: addr);
539
540 g_resolver_set_default (resolver: original_resolver);
541 g_list_free_full (list: ipv4_results, free_func: (GDestroyNotify) g_object_unref);
542 g_object_unref (object: original_resolver);
543 g_object_unref (object: mock_resolver);
544}
545
546typedef struct {
547 GList/*<owned GSocketAddress> */ *addrs; /* owned */
548 GMainLoop *loop; /* owned */
549 GSocketAddressEnumerator *enumerator; /* unowned */
550 guint delay_ms;
551 gint expected_error_code;
552} AsyncData;
553
554static void got_addr (GObject *source_object, GAsyncResult *result, gpointer user_data);
555
556static int
557on_delayed_get_addr (gpointer user_data)
558{
559 AsyncData *data = user_data;
560 g_socket_address_enumerator_next_async (enumerator: data->enumerator, NULL,
561 callback: got_addr, user_data);
562 return G_SOURCE_REMOVE;
563}
564
565static void
566got_addr (GObject *source_object,
567 GAsyncResult *result,
568 gpointer user_data)
569{
570 GSocketAddressEnumerator *enumerator;
571 AsyncData *data;
572 GSocketAddress *a; /* owned */
573 GError *error = NULL;
574
575 enumerator = G_SOCKET_ADDRESS_ENUMERATOR (source_object);
576 data = user_data;
577
578 a = g_socket_address_enumerator_next_finish (enumerator, result, error: &error);
579
580 if (data->expected_error_code)
581 {
582 g_assert_error (error, G_IO_ERROR, data->expected_error_code);
583 g_clear_error (err: &error);
584 }
585 else
586 g_assert_no_error (error);
587
588 if (a == NULL)
589 {
590 /* End of results. */
591 data->addrs = g_list_reverse (list: data->addrs);
592 g_main_loop_quit (loop: data->loop);
593 }
594 else
595 {
596 g_assert (G_IS_INET_SOCKET_ADDRESS (a));
597 data->addrs = g_list_prepend (list: data->addrs, data: a);
598
599 if (!data->delay_ms)
600 g_socket_address_enumerator_next_async (enumerator, NULL,
601 callback: got_addr, user_data);
602 else
603 {
604 data->enumerator = enumerator;
605 g_timeout_add (interval: data->delay_ms, function: on_delayed_get_addr, data);
606 }
607 }
608}
609
610static void
611got_addr_ignored (GObject *source_object,
612 GAsyncResult *result,
613 gpointer user_data)
614{
615 GSocketAddressEnumerator *enumerator;
616 GSocketAddress *a; /* owned */
617 GError *error = NULL;
618
619 /* This function simply ignores the returned addresses but keeps enumerating */
620
621 enumerator = G_SOCKET_ADDRESS_ENUMERATOR (source_object);
622
623 a = g_socket_address_enumerator_next_finish (enumerator, result, error: &error);
624 g_assert_no_error (error);
625 if (a != NULL)
626 {
627 g_object_unref (object: a);
628 g_socket_address_enumerator_next_async (enumerator, NULL,
629 callback: got_addr_ignored, user_data);
630 }
631}
632
633
634static void
635test_loopback_async (void)
636{
637 GSocketConnectable *addr; /* owned */
638 GSocketAddressEnumerator *enumerator; /* owned */
639 AsyncData data = { 0, };
640
641 addr = g_network_address_new_loopback (port: 610);
642 enumerator = g_socket_connectable_enumerate (connectable: addr);
643
644 /* Get all the addresses. */
645 data.addrs = NULL;
646 data.loop = g_main_loop_new (NULL, FALSE);
647
648 g_socket_address_enumerator_next_async (enumerator, NULL, callback: got_addr, user_data: &data);
649
650 g_main_loop_run (loop: data.loop);
651 g_main_loop_unref (loop: data.loop);
652
653 /* Check results. */
654 g_assert_cmpuint (g_list_length (data.addrs), ==, 2);
655 assert_socket_address_matches (a: data.addrs->data, expected_address: "::1", expected_port: 610);
656 assert_socket_address_matches (a: data.addrs->next->data, expected_address: "127.0.0.1", expected_port: 610);
657
658 g_list_free_full (list: data.addrs, free_func: (GDestroyNotify) g_object_unref);
659
660 g_object_unref (object: enumerator);
661 g_object_unref (object: addr);
662}
663
664static void
665test_localhost_async (void)
666{
667 GSocketConnectable *addr; /* owned */
668 GSocketAddressEnumerator *enumerator; /* owned */
669 AsyncData data = { 0, };
670 GResolver *original_resolver; /* owned */
671 MockResolver *mock_resolver; /* owned */
672 GList *ipv4_results = NULL; /* owned */
673
674 /* This test ensures that variations of the "localhost" hostname always resolve to a loopback address */
675
676 /* Set up a DNS resolver that returns nonsense for "localhost" */
677 original_resolver = g_resolver_get_default ();
678 mock_resolver = mock_resolver_new ();
679 g_resolver_set_default (G_RESOLVER (mock_resolver));
680 ipv4_results = g_list_append (list: ipv4_results, data: g_inet_address_new_from_string (string: "123.123.123.123"));
681 mock_resolver_set_ipv4_results (self: mock_resolver, results: ipv4_results);
682
683 addr = g_network_address_new (hostname: "localhost", port: 610);
684 enumerator = g_socket_connectable_enumerate (connectable: addr);
685
686 /* Get all the addresses. */
687 data.addrs = NULL;
688 data.delay_ms = 1;
689 data.loop = g_main_loop_new (NULL, FALSE);
690
691 g_socket_address_enumerator_next_async (enumerator, NULL, callback: got_addr, user_data: &data);
692 g_main_loop_run (loop: data.loop);
693
694 /* Check results. */
695 g_assert_cmpuint (g_list_length (data.addrs), ==, 2);
696 assert_socket_address_matches (a: data.addrs->data, expected_address: "::1", expected_port: 610);
697 assert_socket_address_matches (a: data.addrs->next->data, expected_address: "127.0.0.1", expected_port: 610);
698
699 g_resolver_set_default (resolver: original_resolver);
700 g_list_free_full (list: data.addrs, free_func: (GDestroyNotify) g_object_unref);
701 g_list_free_full (list: ipv4_results, free_func: (GDestroyNotify) g_object_unref);
702 g_object_unref (object: original_resolver);
703 g_object_unref (object: mock_resolver);
704 g_object_unref (object: enumerator);
705 g_object_unref (object: addr);
706 g_main_loop_unref (loop: data.loop);
707}
708
709static void
710test_to_string (void)
711{
712 GSocketConnectable *addr = NULL;
713 gchar *str = NULL;
714 GError *error = NULL;
715
716 /* Without port. */
717 addr = g_network_address_new (hostname: "some-hostname", port: 0);
718 str = g_socket_connectable_to_string (connectable: addr);
719 g_assert_cmpstr (str, ==, "some-hostname");
720 g_free (mem: str);
721 g_object_unref (object: addr);
722
723 /* With port. */
724 addr = g_network_address_new (hostname: "some-hostname", port: 123);
725 str = g_socket_connectable_to_string (connectable: addr);
726 g_assert_cmpstr (str, ==, "some-hostname:123");
727 g_free (mem: str);
728 g_object_unref (object: addr);
729
730 /* With scheme and port. */
731 addr = g_network_address_parse_uri (uri: "http://some-hostname:123", default_port: 80, error: &error);
732 g_assert_no_error (error);
733 str = g_socket_connectable_to_string (connectable: addr);
734 g_assert_cmpstr (str, ==, "http:some-hostname:123");
735 g_free (mem: str);
736 g_object_unref (object: addr);
737
738 /* Loopback. */
739 addr = g_network_address_new (hostname: "localhost", port: 456);
740 str = g_socket_connectable_to_string (connectable: addr);
741 g_assert_cmpstr (str, ==, "localhost:456");
742 g_free (mem: str);
743 g_object_unref (object: addr);
744}
745
746static int
747sort_addresses (gconstpointer a, gconstpointer b)
748{
749 GSocketFamily family_a = g_inet_address_get_family (G_INET_ADDRESS (a));
750 GSocketFamily family_b = g_inet_address_get_family (G_INET_ADDRESS (b));
751
752 if (family_a == family_b)
753 return 0;
754 else if (family_a == G_SOCKET_FAMILY_IPV4)
755 return -1;
756 else
757 return 1;
758}
759
760static int
761sort_socket_addresses (gconstpointer a, gconstpointer b)
762{
763 GInetAddress *addr_a = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (a));
764 GInetAddress *addr_b = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (b));
765 return sort_addresses (a: addr_a, b: addr_b);
766}
767
768static void
769assert_list_matches_expected (GList *result, GList *expected)
770{
771 g_assert_cmpint (g_list_length (result), ==, g_list_length (expected));
772
773 /* Sort by ipv4 first which matches the expected list */
774 result = g_list_sort (list: result, compare_func: sort_socket_addresses);
775
776 for (; result != NULL; result = result->next, expected = expected->next)
777 {
778 GInetAddress *address = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (result->data));
779 g_assert_true (g_inet_address_equal (address, expected->data));
780 }
781}
782
783typedef struct {
784 MockResolver *mock_resolver;
785 GResolver *original_resolver;
786 GList *input_ipv4_results;
787 GList *input_ipv6_results;
788 GList *input_all_results;
789 GSocketConnectable *addr;
790 GSocketAddressEnumerator *enumerator;
791 GMainLoop *loop;
792} HappyEyeballsFixture;
793
794static void
795happy_eyeballs_setup (HappyEyeballsFixture *fixture,
796 gconstpointer data)
797{
798 static const char * const ipv4_address_strings[] = { "1.1.1.1", "2.2.2.2" };
799 static const char * const ipv6_address_strings[] = { "ff::11", "ff::22" };
800 gsize i;
801
802 fixture->original_resolver = g_resolver_get_default ();
803 fixture->mock_resolver = mock_resolver_new ();
804 g_resolver_set_default (G_RESOLVER (fixture->mock_resolver));
805
806 for (i = 0; i < G_N_ELEMENTS (ipv4_address_strings); ++i)
807 {
808 GInetAddress *ipv4_addr = g_inet_address_new_from_string (string: ipv4_address_strings[i]);
809 GInetAddress *ipv6_addr = g_inet_address_new_from_string (string: ipv6_address_strings[i]);
810 fixture->input_ipv4_results = g_list_append (list: fixture->input_ipv4_results, data: ipv4_addr);
811 fixture->input_ipv6_results = g_list_append (list: fixture->input_ipv6_results, data: ipv6_addr);
812 fixture->input_all_results = g_list_append (list: fixture->input_all_results, data: ipv4_addr);
813 fixture->input_all_results = g_list_append (list: fixture->input_all_results, data: ipv6_addr);
814 }
815 fixture->input_all_results = g_list_sort (list: fixture->input_all_results, compare_func: sort_addresses);
816 mock_resolver_set_ipv4_results (self: fixture->mock_resolver, results: fixture->input_ipv4_results);
817 mock_resolver_set_ipv6_results (self: fixture->mock_resolver, results: fixture->input_ipv6_results);
818
819 fixture->addr = g_network_address_new (hostname: "test.fake", port: 80);
820 fixture->enumerator = g_socket_connectable_enumerate (connectable: fixture->addr);
821
822 fixture->loop = g_main_loop_new (NULL, FALSE);
823}
824
825static void
826happy_eyeballs_teardown (HappyEyeballsFixture *fixture,
827 gconstpointer data)
828{
829 g_object_unref (object: fixture->addr);
830 g_object_unref (object: fixture->enumerator);
831 g_resolver_free_addresses (addresses: fixture->input_all_results);
832 g_list_free (list: fixture->input_ipv4_results);
833 g_list_free (list: fixture->input_ipv6_results);
834 g_resolver_set_default (resolver: fixture->original_resolver);
835 g_object_unref (object: fixture->original_resolver);
836 g_object_unref (object: fixture->mock_resolver);
837 g_main_loop_unref (loop: fixture->loop);
838}
839
840static const guint FAST_DELAY_LESS_THAN_TIMEOUT = 25;
841static const guint SLOW_DELAY_MORE_THAN_TIMEOUT = 100;
842
843static void
844test_happy_eyeballs_basic (HappyEyeballsFixture *fixture,
845 gconstpointer user_data)
846{
847 AsyncData data = { 0 };
848
849 data.delay_ms = FAST_DELAY_LESS_THAN_TIMEOUT;
850 data.loop = fixture->loop;
851
852 /* This just tests in the common case it gets all results */
853
854 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
855 g_main_loop_run (loop: fixture->loop);
856
857 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
858}
859
860static void
861test_happy_eyeballs_parallel (HappyEyeballsFixture *fixture,
862 gconstpointer user_data)
863{
864 AsyncData data = { 0 };
865 GSocketAddressEnumerator *enumerator2;
866
867 enumerator2 = g_socket_connectable_enumerate (connectable: fixture->addr);
868
869 data.delay_ms = FAST_DELAY_LESS_THAN_TIMEOUT;
870 data.loop = fixture->loop;
871
872 /* We run multiple enumerations at once, the results shouldn't be affected. */
873
874 g_socket_address_enumerator_next_async (enumerator: enumerator2, NULL, callback: got_addr_ignored, user_data: &data);
875 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
876 g_main_loop_run (loop: fixture->loop);
877
878 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
879
880 /* Run again to ensure the cache from the previous one is correct */
881
882 data.addrs = NULL;
883 g_object_unref (object: enumerator2);
884
885 enumerator2 = g_socket_connectable_enumerate (connectable: fixture->addr);
886 g_socket_address_enumerator_next_async (enumerator: enumerator2, NULL, callback: got_addr, user_data: &data);
887 g_main_loop_run (loop: fixture->loop);
888
889 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
890 g_object_unref (object: enumerator2);
891}
892
893static void
894test_happy_eyeballs_slow_ipv4 (HappyEyeballsFixture *fixture,
895 gconstpointer user_data)
896{
897 AsyncData data = { 0 };
898
899 /* If ipv4 dns response is a bit slow we still get everything */
900
901 data.loop = fixture->loop;
902 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
903
904 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
905 g_main_loop_run (loop: fixture->loop);
906
907 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
908}
909
910static void
911test_happy_eyeballs_slow_ipv6 (HappyEyeballsFixture *fixture,
912 gconstpointer user_data)
913{
914 AsyncData data = { 0 };
915
916 /* If ipv6 is a bit slow it waits for them */
917
918 data.loop = fixture->loop;
919 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
920
921 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
922 g_main_loop_run (loop: fixture->loop);
923
924 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
925}
926
927static void
928test_happy_eyeballs_very_slow_ipv6 (HappyEyeballsFixture *fixture,
929 gconstpointer user_data)
930{
931 AsyncData data = { 0 };
932
933 /* If ipv6 is very slow we still get everything */
934
935 data.loop = fixture->loop;
936 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: SLOW_DELAY_MORE_THAN_TIMEOUT);
937
938 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
939 g_main_loop_run (loop: fixture->loop);
940
941 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
942}
943
944static void
945test_happy_eyeballs_slow_connection_and_ipv4 (HappyEyeballsFixture *fixture,
946 gconstpointer user_data)
947{
948 AsyncData data = { 0 };
949
950 /* Even if the dns response is slow we still get them if our connection attempts
951 * take long enough. */
952
953 data.loop = fixture->loop;
954 data.delay_ms = SLOW_DELAY_MORE_THAN_TIMEOUT * 2;
955 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: SLOW_DELAY_MORE_THAN_TIMEOUT);
956
957 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
958 g_main_loop_run (loop: fixture->loop);
959
960 assert_list_matches_expected (result: data.addrs, expected: fixture->input_all_results);
961}
962
963static void
964test_happy_eyeballs_ipv6_error_ipv4_first (HappyEyeballsFixture *fixture,
965 gconstpointer user_data)
966{
967 AsyncData data = { 0 };
968 GError *ipv6_error;
969
970 /* If ipv6 fails, ensuring that ipv4 finishes before ipv6 errors, we still get ipv4. */
971
972 data.loop = fixture->loop;
973 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
974 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
975 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
976
977 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
978 g_main_loop_run (loop: fixture->loop);
979
980 assert_list_matches_expected (result: data.addrs, expected: fixture->input_ipv4_results);
981
982 g_error_free (error: ipv6_error);
983}
984
985static void
986test_happy_eyeballs_ipv6_error_ipv6_first (HappyEyeballsFixture *fixture,
987 gconstpointer user_data)
988{
989 AsyncData data = { 0 };
990 GError *ipv6_error;
991
992 /* If ipv6 fails, ensuring that ipv6 errors before ipv4 finishes, we still get ipv4. */
993
994 data.loop = fixture->loop;
995 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
996 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
997 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
998
999 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1000 g_main_loop_run (loop: fixture->loop);
1001
1002 assert_list_matches_expected (result: data.addrs, expected: fixture->input_ipv4_results);
1003
1004 g_error_free (error: ipv6_error);
1005}
1006
1007static void
1008test_happy_eyeballs_ipv6_error_ipv4_very_slow (HappyEyeballsFixture *fixture,
1009 gconstpointer user_data)
1010{
1011 AsyncData data = { 0 };
1012 GError *ipv6_error;
1013
1014 g_test_bug (bug_uri_snippet: "merge_requests/865");
1015 g_test_summary (summary: "Ensure that we successfully return IPv4 results even when they come significantly later than an IPv6 failure.");
1016
1017 /* If ipv6 fails, ensuring that ipv6 errors before ipv4 finishes, we still get ipv4. */
1018
1019 data.loop = fixture->loop;
1020 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
1021 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
1022 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: SLOW_DELAY_MORE_THAN_TIMEOUT);
1023
1024 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1025 g_main_loop_run (loop: fixture->loop);
1026
1027 assert_list_matches_expected (result: data.addrs, expected: fixture->input_ipv4_results);
1028
1029 g_error_free (error: ipv6_error);
1030}
1031
1032static void
1033test_happy_eyeballs_ipv4_error_ipv4_first (HappyEyeballsFixture *fixture,
1034 gconstpointer user_data)
1035{
1036 AsyncData data = { 0 };
1037 GError *ipv4_error;
1038
1039 /* If ipv4 fails, ensuring that ipv4 errors before ipv6 finishes, we still get ipv6. */
1040
1041 data.loop = fixture->loop;
1042 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1043 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1044 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
1045
1046 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1047 g_main_loop_run (loop: fixture->loop);
1048
1049 assert_list_matches_expected (result: data.addrs, expected: fixture->input_ipv6_results);
1050
1051 g_error_free (error: ipv4_error);
1052}
1053
1054static void
1055test_happy_eyeballs_ipv4_error_ipv6_first (HappyEyeballsFixture *fixture,
1056 gconstpointer user_data)
1057{
1058 AsyncData data = { 0 };
1059 GError *ipv4_error;
1060
1061 /* If ipv4 fails, ensuring that ipv6 finishes before ipv4 errors, we still get ipv6. */
1062
1063 data.loop = fixture->loop;
1064 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1065 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1066 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
1067
1068 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1069 g_main_loop_run (loop: fixture->loop);
1070
1071 assert_list_matches_expected (result: data.addrs, expected: fixture->input_ipv6_results);
1072
1073 g_error_free (error: ipv4_error);
1074}
1075
1076static void
1077test_happy_eyeballs_both_error (HappyEyeballsFixture *fixture,
1078 gconstpointer user_data)
1079{
1080 AsyncData data = { 0 };
1081 GError *ipv4_error, *ipv6_error;
1082
1083 /* If both fail we get an error. */
1084
1085 data.loop = fixture->loop;
1086 data.expected_error_code = G_IO_ERROR_TIMED_OUT;
1087 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1088 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
1089
1090 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1091 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
1092
1093 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1094 g_main_loop_run (loop: fixture->loop);
1095
1096 g_assert_null (data.addrs);
1097
1098 g_error_free (error: ipv4_error);
1099 g_error_free (error: ipv6_error);
1100}
1101
1102static void
1103test_happy_eyeballs_both_error_delays_1 (HappyEyeballsFixture *fixture,
1104 gconstpointer user_data)
1105{
1106 AsyncData data = { 0 };
1107 GError *ipv4_error, *ipv6_error;
1108
1109 /* The same with some different timings */
1110
1111 data.loop = fixture->loop;
1112 data.expected_error_code = G_IO_ERROR_TIMED_OUT;
1113 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1114 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
1115
1116 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1117 mock_resolver_set_ipv4_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
1118 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
1119
1120 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1121 g_main_loop_run (loop: fixture->loop);
1122
1123 g_assert_null (data.addrs);
1124
1125 g_error_free (error: ipv4_error);
1126 g_error_free (error: ipv6_error);
1127}
1128
1129static void
1130test_happy_eyeballs_both_error_delays_2 (HappyEyeballsFixture *fixture,
1131 gconstpointer user_data)
1132{
1133 AsyncData data = { 0 };
1134 GError *ipv4_error, *ipv6_error;
1135
1136 /* The same with some different timings */
1137
1138 data.loop = fixture->loop;
1139 data.expected_error_code = G_IO_ERROR_TIMED_OUT;
1140 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1141 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
1142
1143 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1144 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
1145 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: FAST_DELAY_LESS_THAN_TIMEOUT);
1146
1147 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1148 g_main_loop_run (loop: fixture->loop);
1149
1150 g_assert_null (data.addrs);
1151
1152 g_error_free (error: ipv4_error);
1153 g_error_free (error: ipv6_error);
1154}
1155
1156static void
1157test_happy_eyeballs_both_error_delays_3 (HappyEyeballsFixture *fixture,
1158 gconstpointer user_data)
1159{
1160 AsyncData data = { 0 };
1161 GError *ipv4_error, *ipv6_error;
1162
1163 /* The same with some different timings */
1164
1165 data.loop = fixture->loop;
1166 data.expected_error_code = G_IO_ERROR_TIMED_OUT;
1167 ipv4_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv4 Broken");
1168 ipv6_error = g_error_new_literal (G_IO_ERROR, code: G_IO_ERROR_TIMED_OUT, message: "IPv6 Broken");
1169
1170 mock_resolver_set_ipv4_error (self: fixture->mock_resolver, error: ipv4_error);
1171 mock_resolver_set_ipv6_error (self: fixture->mock_resolver, error: ipv6_error);
1172 mock_resolver_set_ipv6_delay_ms (self: fixture->mock_resolver, delay_ms: SLOW_DELAY_MORE_THAN_TIMEOUT);
1173
1174 g_socket_address_enumerator_next_async (enumerator: fixture->enumerator, NULL, callback: got_addr, user_data: &data);
1175 g_main_loop_run (loop: fixture->loop);
1176
1177 g_assert_null (data.addrs);
1178
1179 g_error_free (error: ipv4_error);
1180 g_error_free (error: ipv6_error);
1181}
1182
1183int
1184main (int argc, char *argv[])
1185{
1186 gint i;
1187 gchar *path;
1188
1189 g_test_init (argc: &argc, argv: &argv, NULL);
1190 g_test_bug_base (uri_pattern: "https://gitlab.gnome.org/GNOME/glib/");
1191
1192 g_test_add_func (testpath: "/network-address/basic", test_func: test_basic);
1193
1194 for (i = 0; i < G_N_ELEMENTS (host_tests); i++)
1195 {
1196 path = g_strdup_printf (format: "/network-address/parse-host/%d", i);
1197 g_test_add_data_func (testpath: path, test_data: &host_tests[i], test_func: test_parse_host);
1198 g_free (mem: path);
1199 }
1200
1201 for (i = 0; i < G_N_ELEMENTS (uri_tests); i++)
1202 {
1203 path = g_strdup_printf (format: "/network-address/parse-uri/%d", i);
1204 g_test_add_data_func (testpath: path, test_data: &uri_tests[i], test_func: test_parse_uri);
1205 g_free (mem: path);
1206 }
1207
1208 for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
1209 {
1210 path = g_strdup_printf (format: "/network-address/resolve-address/%d", i);
1211 g_test_add_data_func (testpath: path, test_data: &address_tests[i], test_func: test_resolve_address);
1212 g_free (mem: path);
1213 }
1214
1215 for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
1216 {
1217 path = g_strdup_printf (format: "/gresolver/resolve-address/%d", i);
1218 g_test_add_data_func (testpath: path, test_data: &address_tests[i], test_func: test_resolve_address_gresolver);
1219 g_free (mem: path);
1220 }
1221
1222 g_test_add_func (testpath: "/network-address/scope-id", test_func: test_host_scope_id);
1223 g_test_add_func (testpath: "/network-address/uri-scope-id", test_func: test_uri_scope_id);
1224 g_test_add_func (testpath: "/network-address/loopback/basic", test_func: test_loopback_basic);
1225 g_test_add_func (testpath: "/network-address/loopback/sync", test_func: test_loopback_sync);
1226 g_test_add_func (testpath: "/network-address/loopback/async", test_func: test_loopback_async);
1227 g_test_add_func (testpath: "/network-address/localhost/async", test_func: test_localhost_async);
1228 g_test_add_func (testpath: "/network-address/localhost/sync", test_func: test_localhost_sync);
1229 g_test_add_func (testpath: "/network-address/to-string", test_func: test_to_string);
1230
1231 g_test_add ("/network-address/happy-eyeballs/basic", HappyEyeballsFixture, NULL,
1232 happy_eyeballs_setup, test_happy_eyeballs_basic, happy_eyeballs_teardown);
1233 g_test_add ("/network-address/happy-eyeballs/parallel", HappyEyeballsFixture, NULL,
1234 happy_eyeballs_setup, test_happy_eyeballs_parallel, happy_eyeballs_teardown);
1235 g_test_add ("/network-address/happy-eyeballs/slow-ipv4", HappyEyeballsFixture, NULL,
1236 happy_eyeballs_setup, test_happy_eyeballs_slow_ipv4, happy_eyeballs_teardown);
1237 g_test_add ("/network-address/happy-eyeballs/slow-ipv6", HappyEyeballsFixture, NULL,
1238 happy_eyeballs_setup, test_happy_eyeballs_slow_ipv6, happy_eyeballs_teardown);
1239 g_test_add ("/network-address/happy-eyeballs/very-slow-ipv6", HappyEyeballsFixture, NULL,
1240 happy_eyeballs_setup, test_happy_eyeballs_very_slow_ipv6, happy_eyeballs_teardown);
1241 g_test_add ("/network-address/happy-eyeballs/slow-connection-and-ipv4", HappyEyeballsFixture, NULL,
1242 happy_eyeballs_setup, test_happy_eyeballs_slow_connection_and_ipv4, happy_eyeballs_teardown);
1243 g_test_add ("/network-address/happy-eyeballs/ipv6-error-ipv4-first", HappyEyeballsFixture, NULL,
1244 happy_eyeballs_setup, test_happy_eyeballs_ipv6_error_ipv4_first, happy_eyeballs_teardown);
1245 g_test_add ("/network-address/happy-eyeballs/ipv6-error-ipv6-first", HappyEyeballsFixture, NULL,
1246 happy_eyeballs_setup, test_happy_eyeballs_ipv6_error_ipv6_first, happy_eyeballs_teardown);
1247 g_test_add ("/network-address/happy-eyeballs/ipv6-error-ipv4-very-slow", HappyEyeballsFixture, NULL,
1248 happy_eyeballs_setup, test_happy_eyeballs_ipv6_error_ipv4_very_slow, happy_eyeballs_teardown);
1249 g_test_add ("/network-address/happy-eyeballs/ipv4-error-ipv6-first", HappyEyeballsFixture, NULL,
1250 happy_eyeballs_setup, test_happy_eyeballs_ipv4_error_ipv6_first, happy_eyeballs_teardown);
1251 g_test_add ("/network-address/happy-eyeballs/ipv4-error-ipv4-first", HappyEyeballsFixture, NULL,
1252 happy_eyeballs_setup, test_happy_eyeballs_ipv4_error_ipv4_first, happy_eyeballs_teardown);
1253 g_test_add ("/network-address/happy-eyeballs/both-error", HappyEyeballsFixture, NULL,
1254 happy_eyeballs_setup, test_happy_eyeballs_both_error, happy_eyeballs_teardown);
1255 g_test_add ("/network-address/happy-eyeballs/both-error-delays-1", HappyEyeballsFixture, NULL,
1256 happy_eyeballs_setup, test_happy_eyeballs_both_error_delays_1, happy_eyeballs_teardown);
1257 g_test_add ("/network-address/happy-eyeballs/both-error-delays-2", HappyEyeballsFixture, NULL,
1258 happy_eyeballs_setup, test_happy_eyeballs_both_error_delays_2, happy_eyeballs_teardown);
1259 g_test_add ("/network-address/happy-eyeballs/both-error-delays-3", HappyEyeballsFixture, NULL,
1260 happy_eyeballs_setup, test_happy_eyeballs_both_error_delays_3, happy_eyeballs_teardown);
1261
1262 return g_test_run ();
1263}
1264

source code of gtk/subprojects/glib/gio/tests/network-address.c