/* 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 . */ #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); } static void do_lookup_by_name (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { MockResolver *self = source_object; GResolverNameLookupFlags flags = GPOINTER_TO_UINT(task_data); if (flags == G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY) { g_usleep (self->ipv4_delay_ms * 1000); 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) { g_usleep (self->ipv6_delay_ms * 1000); 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); } 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); } else g_assert_not_reached (); } static void lookup_by_name_with_flags_async (GResolver *resolver, const gchar *hostname, GResolverNameLookupFlags flags, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_task_data (task, GUINT_TO_POINTER(flags), NULL); g_task_run_in_thread (task, do_lookup_by_name); g_object_unref (task); } static GList * lookup_by_name (GResolver *resolver, const gchar *hostname, GCancellable *cancellable, GError **error) { GList *result = NULL; GTask *task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_task_data (task, GUINT_TO_POINTER (G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT), NULL); g_task_run_in_thread_sync (task, do_lookup_by_name); result = g_task_propagate_pointer (task, error); g_object_unref (task); return result; } 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; resolver_class->lookup_by_name = lookup_by_name; object_class->finalize = mock_resolver_finalize; } static void mock_resolver_init (MockResolver *self) { }