• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "config.h"
2 #include "mock-resolver.h"
3 
4 #include <gio/gio.h>
5 #include <gio/gnetworking.h>
6 
7 static void
test_basic(void)8 test_basic (void)
9 {
10   GNetworkAddress *address;
11   guint port;
12   gchar *hostname;
13   gchar *scheme;
14 
15   address = (GNetworkAddress*)g_network_address_new ("www.gnome.org", 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 (address, "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 (hostname);
25 
26   g_object_unref (address);
27 }
28 
29 typedef struct {
30   const gchar *input;
31   const gchar *scheme;
32   const gchar *hostname;
33   guint16 port;
34   gint error_code;
35 } ParseTest;
36 
37 static 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 
50 static void
test_parse_uri(gconstpointer d)51 test_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 (test->input, 8080, &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 (address);
72   if (error)
73     g_error_free (error);
74 }
75 
76 static 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 
91 static void
test_parse_host(gconstpointer d)92 test_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 (test->input, 1234, &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 (address);
115   if (error)
116     g_error_free (error);
117 }
118 
119 typedef struct {
120   const gchar *input;
121   gboolean valid_parse, valid_resolve, valid_ip;
122 } ResolveTest;
123 
124 static 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 
145 static void
test_resolve_address(gconstpointer d)146 test_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 ("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 (test->input, 1234, &error);
159   g_assert_no_error (error);
160 
161   addr_enum = g_socket_connectable_enumerate (connectable);
162   addr = g_socket_address_enumerator_next (addr_enum, NULL, &error);
163   g_object_unref (addr_enum);
164   g_object_unref (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 (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  */
185 static void
test_resolve_address_gresolver(gconstpointer d)186 test_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 ("Input: %s", test->input);
195 
196   resolver = g_resolver_get_default ();
197   addrs = g_resolver_lookup_by_name (resolver, test->input, NULL, &error);
198   g_object_unref (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 (iaddr);
209       g_list_free (addrs);
210     }
211   else
212     {
213       g_assert_nonnull (error);
214       g_test_message ("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)
243 static char SCOPE_ID_TEST_IFNAME[IF_NAMESIZE];
244 static int SCOPE_ID_TEST_INDEX;
245 #else
246 #define SCOPE_ID_TEST_IFNAME "1"
247 #define SCOPE_ID_TEST_INDEX 1
248 #endif
249 
250 static void
find_ifname_and_index(void)251 find_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 ("lo");
258   if (SCOPE_ID_TEST_INDEX != 0)
259     {
260       g_strlcpy (SCOPE_ID_TEST_IFNAME, "lo", 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 (SCOPE_ID_TEST_INDEX, SCOPE_ID_TEST_IFNAME))
266       break;
267   }
268   g_assert_cmpstr (SCOPE_ID_TEST_IFNAME, !=, "");
269 #endif
270 }
271 
272 static void
test_scope_id(GSocketConnectable * addr)273 test_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 (addr);
284   saddr = g_socket_address_enumerator_next (addr_enum, NULL, &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 (isaddr);
295   tostring = g_inet_address_to_string (iaddr);
296   g_assert_cmpstr (tostring, ==, SCOPE_ID_TEST_ADDR);
297   g_free (tostring);
298 
299   g_object_unref (saddr);
300   saddr = g_socket_address_enumerator_next (addr_enum, NULL, &error);
301   g_assert_no_error (error);
302   g_assert (saddr == NULL);
303 
304   g_object_unref (addr_enum);
305 #else
306   g_test_skip ("winsock2 getaddrinfo() can’t understand scope IDs");
307 #endif
308 }
309 
310 static void
test_host_scope_id(void)311 test_host_scope_id (void)
312 {
313   GSocketConnectable *addr;
314   char *str;
315 
316   find_ifname_and_index ();
317 
318   str = g_strdup_printf ("%s%%%s", SCOPE_ID_TEST_ADDR, SCOPE_ID_TEST_IFNAME);
319   addr = g_network_address_new (str, SCOPE_ID_TEST_PORT);
320   g_free (str);
321 
322   test_scope_id (addr);
323   g_object_unref (addr);
324 }
325 
326 static void
test_uri_scope_id(void)327 test_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 ("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, 0, &error);
340   g_free (uri);
341   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT);
342   g_assert_null (addr);
343   g_clear_error (&error);
344 
345   uri = g_strdup_printf ("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, 0, &error);
350   g_free (uri);
351   g_assert_no_error (error);
352 
353   test_scope_id (addr);
354   g_object_unref (addr);
355 }
356 
357 static void
test_loopback_basic(void)358 test_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 (addr);
370 }
371 
372 static void
assert_socket_address_matches(GSocketAddress * a,const gchar * expected_address,guint16 expected_port)373 assert_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 (g_inet_socket_address_get_address (sa));
386   g_assert_cmpstr (str, ==, expected_address);
387   g_free (str);
388 }
389 
390 static void
test_loopback_sync(void)391 test_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 (616);
399   enumerator = g_socket_connectable_enumerate (addr);
400 
401   /* IPv6 address. */
402   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
403   g_assert_no_error (error);
404   assert_socket_address_matches (a, "::1", 616);
405   g_object_unref (a);
406 
407   /* IPv4 address. */
408   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
409   g_assert_no_error (error);
410   assert_socket_address_matches (a, "127.0.0.1", 616);
411   g_object_unref (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 (enumerator);
418   g_object_unref (addr);
419 }
420 
421 static void
test_localhost_sync(void)422 test_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 (ipv4_results, g_inet_address_new_from_string ("123.123.123.123"));
439   mock_resolver_set_ipv4_results (mock_resolver, ipv4_results);
440 
441   addr = g_network_address_new ("localhost.", 616);
442   enumerator = g_socket_connectable_enumerate (addr);
443 
444   /* IPv6 address. */
445   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
446   g_assert_no_error (error);
447   assert_socket_address_matches (a, "::1", 616);
448   g_object_unref (a);
449 
450   /* IPv4 address. */
451   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
452   g_assert_no_error (error);
453   assert_socket_address_matches (a, "127.0.0.1", 616);
454   g_object_unref (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 (enumerator);
460   g_object_unref (addr);
461 
462   addr = g_network_address_new (".localhost", 616);
463   enumerator = g_socket_connectable_enumerate (addr);
464 
465   /* IPv6 address. */
466   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
467   g_assert_no_error (error);
468   assert_socket_address_matches (a, "::1", 616);
469   g_object_unref (a);
470 
471   /* IPv4 address. */
472   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
473   g_assert_no_error (error);
474   assert_socket_address_matches (a, "127.0.0.1", 616);
475   g_object_unref (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 (enumerator);
481   g_object_unref (addr);
482 
483   addr = g_network_address_new ("foo.localhost", 616);
484   enumerator = g_socket_connectable_enumerate (addr);
485 
486   /* IPv6 address. */
487   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
488   g_assert_no_error (error);
489   assert_socket_address_matches (a, "::1", 616);
490   g_object_unref (a);
491 
492   /* IPv4 address. */
493   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
494   g_assert_no_error (error);
495   assert_socket_address_matches (a, "127.0.0.1", 616);
496   g_object_unref (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 (enumerator);
502   g_object_unref (addr);
503 
504   addr = g_network_address_new (".localhost.", 616);
505   enumerator = g_socket_connectable_enumerate (addr);
506 
507   /* IPv6 address. */
508   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
509   g_assert_no_error (error);
510   assert_socket_address_matches (a, "::1", 616);
511   g_object_unref (a);
512 
513   /* IPv4 address. */
514   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
515   g_assert_no_error (error);
516   assert_socket_address_matches (a, "127.0.0.1", 616);
517   g_object_unref (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 (enumerator);
523   g_object_unref (addr);
524 
525   addr = g_network_address_new ("invalid", 616);
526   enumerator = g_socket_connectable_enumerate (addr);
527 
528   /* IPv4 address. */
529   a = g_socket_address_enumerator_next (enumerator, NULL, &error);
530   g_assert_no_error (error);
531   assert_socket_address_matches (a, "123.123.123.123", 616);
532   g_object_unref (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 (enumerator);
538   g_object_unref (addr);
539 
540   g_resolver_set_default (original_resolver);
541   g_list_free_full (ipv4_results, (GDestroyNotify) g_object_unref);
542   g_object_unref (original_resolver);
543   g_object_unref (mock_resolver);
544 }
545 
546 typedef 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 
554 static void got_addr (GObject *source_object, GAsyncResult *result, gpointer user_data);
555 
556 static int
on_delayed_get_addr(gpointer user_data)557 on_delayed_get_addr (gpointer user_data)
558 {
559   AsyncData *data = user_data;
560   g_socket_address_enumerator_next_async (data->enumerator, NULL,
561                                           got_addr, user_data);
562   return G_SOURCE_REMOVE;
563 }
564 
565 static void
got_addr(GObject * source_object,GAsyncResult * result,gpointer user_data)566 got_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);
579 
580   if (data->expected_error_code)
581     {
582       g_assert_error (error, G_IO_ERROR, data->expected_error_code);
583       g_clear_error (&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 (data->addrs);
592       g_main_loop_quit (data->loop);
593     }
594   else
595     {
596       g_assert (G_IS_INET_SOCKET_ADDRESS (a));
597       data->addrs = g_list_prepend (data->addrs, a);
598 
599       if (!data->delay_ms)
600         g_socket_address_enumerator_next_async (enumerator, NULL,
601                                                 got_addr, user_data);
602       else
603         {
604           data->enumerator = enumerator;
605           g_timeout_add (data->delay_ms, on_delayed_get_addr, data);
606         }
607     }
608 }
609 
610 static void
got_addr_ignored(GObject * source_object,GAsyncResult * result,gpointer user_data)611 got_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);
624   g_assert_no_error (error);
625   if (a != NULL)
626     {
627       g_object_unref (a);
628       g_socket_address_enumerator_next_async (enumerator, NULL,
629                                               got_addr_ignored, user_data);
630     }
631 }
632 
633 
634 static void
test_loopback_async(void)635 test_loopback_async (void)
636 {
637   GSocketConnectable *addr;  /* owned */
638   GSocketAddressEnumerator *enumerator;  /* owned */
639   AsyncData data = { 0, };
640 
641   addr = g_network_address_new_loopback (610);
642   enumerator = g_socket_connectable_enumerate (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, got_addr, &data);
649 
650   g_main_loop_run (data.loop);
651   g_main_loop_unref (data.loop);
652 
653   /* Check results. */
654   g_assert_cmpuint (g_list_length (data.addrs), ==, 2);
655   assert_socket_address_matches (data.addrs->data, "::1", 610);
656   assert_socket_address_matches (data.addrs->next->data, "127.0.0.1", 610);
657 
658   g_list_free_full (data.addrs, (GDestroyNotify) g_object_unref);
659 
660   g_object_unref (enumerator);
661   g_object_unref (addr);
662 }
663 
664 static void
test_localhost_async(void)665 test_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 (ipv4_results, g_inet_address_new_from_string ("123.123.123.123"));
681   mock_resolver_set_ipv4_results (mock_resolver, ipv4_results);
682 
683   addr = g_network_address_new ("localhost", 610);
684   enumerator = g_socket_connectable_enumerate (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, got_addr, &data);
692   g_main_loop_run (data.loop);
693 
694   /* Check results. */
695   g_assert_cmpuint (g_list_length (data.addrs), ==, 2);
696   assert_socket_address_matches (data.addrs->data, "::1", 610);
697   assert_socket_address_matches (data.addrs->next->data, "127.0.0.1", 610);
698 
699   g_resolver_set_default (original_resolver);
700   g_list_free_full (data.addrs, (GDestroyNotify) g_object_unref);
701   g_list_free_full (ipv4_results, (GDestroyNotify) g_object_unref);
702   g_object_unref (original_resolver);
703   g_object_unref (mock_resolver);
704   g_object_unref (enumerator);
705   g_object_unref (addr);
706   g_main_loop_unref (data.loop);
707 }
708 
709 static void
test_to_string(void)710 test_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 ("some-hostname", 0);
718   str = g_socket_connectable_to_string (addr);
719   g_assert_cmpstr (str, ==, "some-hostname");
720   g_free (str);
721   g_object_unref (addr);
722 
723   /* With port. */
724   addr = g_network_address_new ("some-hostname", 123);
725   str = g_socket_connectable_to_string (addr);
726   g_assert_cmpstr (str, ==, "some-hostname:123");
727   g_free (str);
728   g_object_unref (addr);
729 
730   /* With scheme and port. */
731   addr = g_network_address_parse_uri ("http://some-hostname:123", 80, &error);
732   g_assert_no_error (error);
733   str = g_socket_connectable_to_string (addr);
734   g_assert_cmpstr (str, ==, "http:some-hostname:123");
735   g_free (str);
736   g_object_unref (addr);
737 
738   /* Loopback. */
739   addr = g_network_address_new ("localhost", 456);
740   str = g_socket_connectable_to_string (addr);
741   g_assert_cmpstr (str, ==, "localhost:456");
742   g_free (str);
743   g_object_unref (addr);
744 }
745 
746 static int
sort_addresses(gconstpointer a,gconstpointer b)747 sort_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 
760 static int
sort_socket_addresses(gconstpointer a,gconstpointer b)761 sort_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 (addr_a, addr_b);
766 }
767 
768 static void
assert_list_matches_expected(GList * result,GList * expected)769 assert_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 (result, 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 
783 typedef 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 
794 static void
happy_eyeballs_setup(HappyEyeballsFixture * fixture,gconstpointer data)795 happy_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 (ipv4_address_strings[i]);
809       GInetAddress *ipv6_addr = g_inet_address_new_from_string (ipv6_address_strings[i]);
810       fixture->input_ipv4_results = g_list_append (fixture->input_ipv4_results, ipv4_addr);
811       fixture->input_ipv6_results = g_list_append (fixture->input_ipv6_results, ipv6_addr);
812       fixture->input_all_results = g_list_append (fixture->input_all_results, ipv4_addr);
813       fixture->input_all_results = g_list_append (fixture->input_all_results, ipv6_addr);
814     }
815   fixture->input_all_results = g_list_sort (fixture->input_all_results, sort_addresses);
816   mock_resolver_set_ipv4_results (fixture->mock_resolver, fixture->input_ipv4_results);
817   mock_resolver_set_ipv6_results (fixture->mock_resolver, fixture->input_ipv6_results);
818 
819   fixture->addr = g_network_address_new ("test.fake", 80);
820   fixture->enumerator = g_socket_connectable_enumerate (fixture->addr);
821 
822   fixture->loop = g_main_loop_new (NULL, FALSE);
823 }
824 
825 static void
happy_eyeballs_teardown(HappyEyeballsFixture * fixture,gconstpointer data)826 happy_eyeballs_teardown (HappyEyeballsFixture *fixture,
827                          gconstpointer         data)
828 {
829   g_object_unref (fixture->addr);
830   g_object_unref (fixture->enumerator);
831   g_resolver_free_addresses (fixture->input_all_results);
832   g_list_free (fixture->input_ipv4_results);
833   g_list_free (fixture->input_ipv6_results);
834   g_resolver_set_default (fixture->original_resolver);
835   g_object_unref (fixture->original_resolver);
836   g_object_unref (fixture->mock_resolver);
837   g_main_loop_unref (fixture->loop);
838 }
839 
840 static const guint FAST_DELAY_LESS_THAN_TIMEOUT = 25;
841 static const guint SLOW_DELAY_MORE_THAN_TIMEOUT = 100;
842 
843 static void
test_happy_eyeballs_basic(HappyEyeballsFixture * fixture,gconstpointer user_data)844 test_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 (fixture->enumerator, NULL, got_addr, &data);
855   g_main_loop_run (fixture->loop);
856 
857   assert_list_matches_expected (data.addrs, fixture->input_all_results);
858 }
859 
860 static void
test_happy_eyeballs_parallel(HappyEyeballsFixture * fixture,gconstpointer user_data)861 test_happy_eyeballs_parallel (HappyEyeballsFixture *fixture,
862                               gconstpointer         user_data)
863 {
864   AsyncData data = { 0 };
865   GSocketAddressEnumerator *enumerator2;
866 
867   enumerator2 = g_socket_connectable_enumerate (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 (enumerator2, NULL, got_addr_ignored, &data);
875   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
876   g_main_loop_run (fixture->loop);
877 
878   assert_list_matches_expected (data.addrs, 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 (enumerator2);
884 
885   enumerator2 = g_socket_connectable_enumerate (fixture->addr);
886   g_socket_address_enumerator_next_async (enumerator2, NULL, got_addr, &data);
887   g_main_loop_run (fixture->loop);
888 
889   assert_list_matches_expected (data.addrs, fixture->input_all_results);
890   g_object_unref (enumerator2);
891 }
892 
893 static void
test_happy_eyeballs_slow_ipv4(HappyEyeballsFixture * fixture,gconstpointer user_data)894 test_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 (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
903 
904   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
905   g_main_loop_run (fixture->loop);
906 
907   assert_list_matches_expected (data.addrs, fixture->input_all_results);
908 }
909 
910 static void
test_happy_eyeballs_slow_ipv6(HappyEyeballsFixture * fixture,gconstpointer user_data)911 test_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 (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
920 
921   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
922   g_main_loop_run (fixture->loop);
923 
924   assert_list_matches_expected (data.addrs, fixture->input_all_results);
925 }
926 
927 static void
test_happy_eyeballs_very_slow_ipv6(HappyEyeballsFixture * fixture,gconstpointer user_data)928 test_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 (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
937 
938   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
939   g_main_loop_run (fixture->loop);
940 
941   assert_list_matches_expected (data.addrs, fixture->input_all_results);
942 }
943 
944 static void
test_happy_eyeballs_slow_connection_and_ipv4(HappyEyeballsFixture * fixture,gconstpointer user_data)945 test_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 (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
956 
957   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
958   g_main_loop_run (fixture->loop);
959 
960   assert_list_matches_expected (data.addrs, fixture->input_all_results);
961 }
962 
963 static void
test_happy_eyeballs_ipv6_error_ipv4_first(HappyEyeballsFixture * fixture,gconstpointer user_data)964 test_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, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
974   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
975   mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
976 
977   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
978   g_main_loop_run (fixture->loop);
979 
980   assert_list_matches_expected (data.addrs, fixture->input_ipv4_results);
981 
982   g_error_free (ipv6_error);
983 }
984 
985 static void
test_happy_eyeballs_ipv6_error_ipv6_first(HappyEyeballsFixture * fixture,gconstpointer user_data)986 test_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, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
996   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
997   mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
998 
999   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1000   g_main_loop_run (fixture->loop);
1001 
1002   assert_list_matches_expected (data.addrs, fixture->input_ipv4_results);
1003 
1004   g_error_free (ipv6_error);
1005 }
1006 
1007 static void
test_happy_eyeballs_ipv6_error_ipv4_very_slow(HappyEyeballsFixture * fixture,gconstpointer user_data)1008 test_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 ("merge_requests/865");
1015   g_test_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, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
1021   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
1022   mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
1023 
1024   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1025   g_main_loop_run (fixture->loop);
1026 
1027   assert_list_matches_expected (data.addrs, fixture->input_ipv4_results);
1028 
1029   g_error_free (ipv6_error);
1030 }
1031 
1032 static void
test_happy_eyeballs_ipv4_error_ipv4_first(HappyEyeballsFixture * fixture,gconstpointer user_data)1033 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1043   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1044   mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
1045 
1046   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1047   g_main_loop_run (fixture->loop);
1048 
1049   assert_list_matches_expected (data.addrs, fixture->input_ipv6_results);
1050 
1051   g_error_free (ipv4_error);
1052 }
1053 
1054 static void
test_happy_eyeballs_ipv4_error_ipv6_first(HappyEyeballsFixture * fixture,gconstpointer user_data)1055 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1065   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1066   mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
1067 
1068   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1069   g_main_loop_run (fixture->loop);
1070 
1071   assert_list_matches_expected (data.addrs, fixture->input_ipv6_results);
1072 
1073   g_error_free (ipv4_error);
1074 }
1075 
1076 static void
test_happy_eyeballs_both_error(HappyEyeballsFixture * fixture,gconstpointer user_data)1077 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1088   ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
1089 
1090   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1091   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
1092 
1093   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1094   g_main_loop_run (fixture->loop);
1095 
1096   g_assert_null (data.addrs);
1097 
1098   g_error_free (ipv4_error);
1099   g_error_free (ipv6_error);
1100 }
1101 
1102 static void
test_happy_eyeballs_both_error_delays_1(HappyEyeballsFixture * fixture,gconstpointer user_data)1103 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1114   ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
1115 
1116   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1117   mock_resolver_set_ipv4_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
1118   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
1119 
1120   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1121   g_main_loop_run (fixture->loop);
1122 
1123   g_assert_null (data.addrs);
1124 
1125   g_error_free (ipv4_error);
1126   g_error_free (ipv6_error);
1127 }
1128 
1129 static void
test_happy_eyeballs_both_error_delays_2(HappyEyeballsFixture * fixture,gconstpointer user_data)1130 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1141   ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
1142 
1143   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1144   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
1145   mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, FAST_DELAY_LESS_THAN_TIMEOUT);
1146 
1147   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1148   g_main_loop_run (fixture->loop);
1149 
1150   g_assert_null (data.addrs);
1151 
1152   g_error_free (ipv4_error);
1153   g_error_free (ipv6_error);
1154 }
1155 
1156 static void
test_happy_eyeballs_both_error_delays_3(HappyEyeballsFixture * fixture,gconstpointer user_data)1157 test_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, G_IO_ERROR_TIMED_OUT, "IPv4 Broken");
1168   ipv6_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "IPv6 Broken");
1169 
1170   mock_resolver_set_ipv4_error (fixture->mock_resolver, ipv4_error);
1171   mock_resolver_set_ipv6_error (fixture->mock_resolver, ipv6_error);
1172   mock_resolver_set_ipv6_delay_ms (fixture->mock_resolver, SLOW_DELAY_MORE_THAN_TIMEOUT);
1173 
1174   g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
1175   g_main_loop_run (fixture->loop);
1176 
1177   g_assert_null (data.addrs);
1178 
1179   g_error_free (ipv4_error);
1180   g_error_free (ipv6_error);
1181 }
1182 
1183 int
main(int argc,char * argv[])1184 main (int argc, char *argv[])
1185 {
1186   gint i;
1187   gchar *path;
1188 
1189   g_test_init (&argc, &argv, NULL);
1190   g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/");
1191 
1192   g_test_add_func ("/network-address/basic", test_basic);
1193 
1194   for (i = 0; i < G_N_ELEMENTS (host_tests); i++)
1195     {
1196       path = g_strdup_printf ("/network-address/parse-host/%d", i);
1197       g_test_add_data_func (path, &host_tests[i], test_parse_host);
1198       g_free (path);
1199     }
1200 
1201   for (i = 0; i < G_N_ELEMENTS (uri_tests); i++)
1202     {
1203       path = g_strdup_printf ("/network-address/parse-uri/%d", i);
1204       g_test_add_data_func (path, &uri_tests[i], test_parse_uri);
1205       g_free (path);
1206     }
1207 
1208   for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
1209     {
1210       path = g_strdup_printf ("/network-address/resolve-address/%d", i);
1211       g_test_add_data_func (path, &address_tests[i], test_resolve_address);
1212       g_free (path);
1213     }
1214 
1215   for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
1216     {
1217       path = g_strdup_printf ("/gresolver/resolve-address/%d", i);
1218       g_test_add_data_func (path, &address_tests[i], test_resolve_address_gresolver);
1219       g_free (path);
1220     }
1221 
1222   g_test_add_func ("/network-address/scope-id", test_host_scope_id);
1223   g_test_add_func ("/network-address/uri-scope-id", test_uri_scope_id);
1224   g_test_add_func ("/network-address/loopback/basic", test_loopback_basic);
1225   g_test_add_func ("/network-address/loopback/sync", test_loopback_sync);
1226   g_test_add_func ("/network-address/loopback/async", test_loopback_async);
1227   g_test_add_func ("/network-address/localhost/async", test_localhost_async);
1228   g_test_add_func ("/network-address/localhost/sync", test_localhost_sync);
1229   g_test_add_func ("/network-address/to-string", 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