2018-10-22 19:36:27 +02:00
|
|
|
/* GIO - GLib Input, Output and Streaming Library
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018 Igalia S.L.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General
|
|
|
|
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mock-resolver.h"
|
|
|
|
|
|
|
|
struct _MockResolver
|
|
|
|
{
|
|
|
|
GResolver parent_instance;
|
|
|
|
guint ipv4_delay_ms;
|
|
|
|
guint ipv6_delay_ms;
|
|
|
|
GList *ipv4_results;
|
|
|
|
GList *ipv6_results;
|
|
|
|
GError *ipv4_error;
|
|
|
|
GError *ipv6_error;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MockResolver, mock_resolver, G_TYPE_RESOLVER)
|
|
|
|
|
|
|
|
MockResolver *
|
|
|
|
mock_resolver_new (void)
|
|
|
|
{
|
|
|
|
return g_object_new (MOCK_TYPE_RESOLVER, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv4_delay_ms (MockResolver *self, guint delay_ms)
|
|
|
|
{
|
|
|
|
self->ipv4_delay_ms = delay_ms;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gpointer
|
|
|
|
copy_object (gconstpointer obj, gpointer user_data)
|
|
|
|
{
|
|
|
|
return g_object_ref (G_OBJECT (obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv4_results (MockResolver *self, GList *results)
|
|
|
|
{
|
|
|
|
if (self->ipv4_results)
|
|
|
|
g_list_free_full (self->ipv4_results, g_object_unref);
|
|
|
|
self->ipv4_results = g_list_copy_deep (results, copy_object, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv4_error (MockResolver *self, GError *error)
|
|
|
|
{
|
|
|
|
g_clear_error (&self->ipv4_error);
|
|
|
|
if (error)
|
|
|
|
self->ipv4_error = g_error_copy (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv6_delay_ms (MockResolver *self, guint delay_ms)
|
|
|
|
{
|
|
|
|
self->ipv6_delay_ms = delay_ms;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv6_results (MockResolver *self, GList *results)
|
|
|
|
{
|
|
|
|
if (self->ipv6_results)
|
|
|
|
g_list_free_full (self->ipv6_results, g_object_unref);
|
|
|
|
self->ipv6_results = g_list_copy_deep (results, copy_object, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mock_resolver_set_ipv6_error (MockResolver *self, GError *error)
|
|
|
|
{
|
|
|
|
g_clear_error (&self->ipv6_error);
|
|
|
|
if (error)
|
|
|
|
self->ipv6_error = g_error_copy (error);
|
|
|
|
}
|
|
|
|
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
static gboolean lookup_by_name_cb (gpointer user_data);
|
|
|
|
|
|
|
|
/* Core of the implementation of `lookup_by_name()` in the mock resolver.
|
|
|
|
*
|
|
|
|
* It creates a #GSource which will become ready with the resolver results. It
|
|
|
|
* will become ready either after a timeout, or as an idle callback. This
|
|
|
|
* simulates doing some actual network-based resolution work.
|
|
|
|
*
|
|
|
|
* A previous implementation of this did the work in a thread, but that made it
|
|
|
|
* hard to synchronise the timeouts with the #GResolver failure timeouts in the
|
|
|
|
* calling thread, as spawning a worker thread could be subject to non-trivial
|
|
|
|
* delays. */
|
2018-10-22 19:36:27 +02:00
|
|
|
static void
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
do_lookup_by_name (MockResolver *self,
|
|
|
|
GTask *task,
|
|
|
|
GResolverNameLookupFlags flags)
|
2018-10-22 19:36:27 +02:00
|
|
|
{
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
GSource *source = NULL;
|
|
|
|
|
|
|
|
g_task_set_task_data (task, GINT_TO_POINTER (flags), NULL);
|
|
|
|
|
|
|
|
if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY)
|
|
|
|
source = g_timeout_source_new (self->ipv4_delay_ms);
|
|
|
|
else if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)
|
|
|
|
source = g_timeout_source_new (self->ipv6_delay_ms);
|
|
|
|
else if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
|
|
|
|
source = g_idle_source_new ();
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
g_source_set_callback (source, lookup_by_name_cb, g_object_ref (task), g_object_unref);
|
|
|
|
g_source_attach (source, g_main_context_get_thread_default ());
|
|
|
|
g_source_unref (source);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
lookup_by_name_cb (gpointer user_data)
|
|
|
|
{
|
|
|
|
GTask *task = G_TASK (user_data);
|
|
|
|
MockResolver *self = g_task_get_source_object (task);
|
|
|
|
GResolverNameLookupFlags flags = GPOINTER_TO_INT (g_task_get_task_data (task));
|
2018-10-22 19:36:27 +02:00
|
|
|
|
|
|
|
if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY)
|
|
|
|
{
|
|
|
|
if (self->ipv4_error)
|
|
|
|
g_task_return_error (task, g_error_copy (self->ipv4_error));
|
|
|
|
else
|
|
|
|
g_task_return_pointer (task, g_list_copy_deep (self->ipv4_results, copy_object, NULL), NULL);
|
|
|
|
}
|
|
|
|
else if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)
|
|
|
|
{
|
|
|
|
if (self->ipv6_error)
|
|
|
|
g_task_return_error (task, g_error_copy (self->ipv6_error));
|
|
|
|
else
|
|
|
|
g_task_return_pointer (task, g_list_copy_deep (self->ipv6_results, copy_object, NULL), NULL);
|
|
|
|
}
|
2019-02-05 14:53:44 +01:00
|
|
|
else if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
|
|
|
|
{
|
|
|
|
/* This is only the minimal implementation needed for some tests */
|
|
|
|
g_assert (self->ipv4_error == NULL && self->ipv6_error == NULL && self->ipv6_results == NULL);
|
|
|
|
g_task_return_pointer (task, g_list_copy_deep (self->ipv4_results, copy_object, NULL), NULL);
|
|
|
|
}
|
2018-10-22 19:36:27 +02:00
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
2018-10-22 19:36:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
lookup_by_name_with_flags_async (GResolver *resolver,
|
|
|
|
const gchar *hostname,
|
|
|
|
GResolverNameLookupFlags flags,
|
|
|
|
GCancellable *cancellable,
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
MockResolver *self = MOCK_RESOLVER (resolver);
|
|
|
|
GTask *task = NULL;
|
|
|
|
|
|
|
|
task = g_task_new (resolver, cancellable, callback, user_data);
|
|
|
|
g_task_set_source_tag (task, lookup_by_name_with_flags_async);
|
|
|
|
|
|
|
|
do_lookup_by_name (self, task, flags);
|
|
|
|
|
2018-10-22 19:36:27 +02:00
|
|
|
g_object_unref (task);
|
|
|
|
}
|
|
|
|
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
static void
|
|
|
|
async_result_cb (GObject *source_object,
|
|
|
|
GAsyncResult *result,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GAsyncResult **result_out = user_data;
|
|
|
|
|
|
|
|
g_assert (*result_out == NULL);
|
|
|
|
*result_out = g_object_ref (result);
|
|
|
|
|
|
|
|
g_main_context_wakeup (g_main_context_get_thread_default ());
|
|
|
|
}
|
|
|
|
|
2019-02-05 14:53:44 +01:00
|
|
|
static GList *
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
lookup_by_name (GResolver *resolver,
|
|
|
|
const gchar *hostname,
|
|
|
|
GCancellable *cancellable,
|
2019-02-05 14:53:44 +01:00
|
|
|
GError **error)
|
|
|
|
{
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
MockResolver *self = MOCK_RESOLVER (resolver);
|
|
|
|
GMainContext *context = NULL;
|
2019-02-05 14:53:44 +01:00
|
|
|
GList *result = NULL;
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
GAsyncResult *async_result = NULL;
|
|
|
|
GTask *task = NULL;
|
2019-02-05 14:53:44 +01:00
|
|
|
|
tests: Remove threads from mock-resolver/network-address test
`mock-resolver.c` is a mock implementation of `GResolver` used in the
`network-address` tests. It returns resolver results, and implements
timeouts, as directed by the test calling it.
In particular, it allows the IPv4 and IPv6 resolver results to be
returned using independent delays. This allows code paths which deal
with IPv4 and IPv6 results being returned at different times to be
tested, as the ‘Happy Eyeballs’ spec mandates various hard-coded
timeouts for returning the best results it can in a reasonable
timeframe.
Previously, `mock-resolver.c` implemented the timeouts by handling
`lookup_by_name()` in a `GTask` worker thread, and calling `g_usleep()`
for the timeout. This seemed to cause occasional CI failures, such as
https://gitlab.gnome.org/GNOME/glib/-/jobs/1843454, where a resolver
error would be returned rather than the expected results:
```
ok 52 /network-address/happy-eyeballs/ipv4-error-ipv6-first
\# GLib-GIO-DEBUG: IPv4 DNS error: IPv4 Broken
(/var/tmp/gitlab_runner/builds/Ff4WDDRj/0/GNOME/glib/_build/gio/tests/network-address:18428): GLib-GIO-DEBUG: 09:03:08.587: IPv4 DNS error: IPv4 Broken
Bail out! GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
stderr:
**
GLib-GIO:ERROR:../gio/tests/network-address.c:586:got_addr: assertion failed (error == NULL): IPv4 Broken (g-io-error-quark, 24)
```
While I’ve been unable to reproduce these failures locally, I suspect
they might be down to thread spawning occasionally taking long enough on
a CI runner to change the ordering of the timeouts, such that the ‘Happy
Eyeballs’ algorithm returns a different set of results from what the
test expects.
So, this commit rewrites part of `mock-resolver.c` to implement timeouts
in the main thread, rather than in a worker thread. That should
eliminate the delays in spawning threads, and should mean that the
timeout sources in `mock-resolver.c` are attached to the same
`GMainContext` as those from the ‘Happy Eyeballs’ algorithm which are
monitoring them, so a total order over the timeouts can be guaranteed.
Of course, I might be completely wrong since this is just a guess and I
can’t properly test it since I can’t reproduce the failure. Worth a try.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2022-02-22 12:16:35 +01:00
|
|
|
context = g_main_context_new ();
|
|
|
|
g_main_context_push_thread_default (context);
|
|
|
|
|
|
|
|
task = g_task_new (resolver, cancellable, async_result_cb, &async_result);
|
|
|
|
g_task_set_source_tag (task, lookup_by_name);
|
|
|
|
|
|
|
|
/* Set up the resolution job. */
|
|
|
|
do_lookup_by_name (self, task, G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT);
|
|
|
|
|
|
|
|
/* Wait for it to complete synchronously. */
|
|
|
|
while (async_result == NULL)
|
|
|
|
g_main_context_iteration (context, TRUE);
|
|
|
|
|
|
|
|
result = g_task_propagate_pointer (G_TASK (async_result), error);
|
|
|
|
g_object_unref (async_result);
|
|
|
|
|
|
|
|
g_assert_finalize_object (task);
|
|
|
|
|
|
|
|
g_main_context_pop_thread_default (context);
|
|
|
|
g_main_context_unref (context);
|
|
|
|
|
|
|
|
return g_steal_pointer (&result);
|
|
|
|
}
|
2019-02-05 14:53:44 +01:00
|
|
|
|
2018-10-22 19:36:27 +02:00
|
|
|
static GList *
|
|
|
|
lookup_by_name_with_flags_finish (GResolver *resolver,
|
|
|
|
GAsyncResult *result,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
return g_task_propagate_pointer (G_TASK (result), error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mock_resolver_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MockResolver *self = (MockResolver*)object;
|
|
|
|
|
|
|
|
g_clear_error (&self->ipv4_error);
|
|
|
|
g_clear_error (&self->ipv6_error);
|
|
|
|
if (self->ipv6_results)
|
|
|
|
g_list_free_full (self->ipv6_results, g_object_unref);
|
|
|
|
if (self->ipv4_results)
|
|
|
|
g_list_free_full (self->ipv4_results, g_object_unref);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (mock_resolver_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mock_resolver_class_init (MockResolverClass *klass)
|
|
|
|
{
|
|
|
|
GResolverClass *resolver_class = G_RESOLVER_CLASS (klass);
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
resolver_class->lookup_by_name_with_flags_async = lookup_by_name_with_flags_async;
|
|
|
|
resolver_class->lookup_by_name_with_flags_finish = lookup_by_name_with_flags_finish;
|
2019-02-05 14:53:44 +01:00
|
|
|
resolver_class->lookup_by_name = lookup_by_name;
|
2018-10-22 19:36:27 +02:00
|
|
|
object_class->finalize = mock_resolver_finalize;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mock_resolver_init (MockResolver *self)
|
|
|
|
{
|
|
|
|
}
|