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