mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-05 00:43:40 +02:00
girepository: Make gi_repository_find_by_gtype() deterministic
When faced with a `GType` which is present in multiple typelibs, the old implementation was not deterministic, as it iterated over a hash table of typelibs. The iteration order of a hash table is not deterministic. Use the new `ordered_typelibs` and `ordered_lazy_typelibs` arrays to iterate instead, making the order deterministic. Add a unit test to check this. In particular, to check that symbols which are present in both `Gio` and `GioUnix` are correctly resolved as being from `GioUnix`. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Helps: #3303
This commit is contained in:
@@ -35,6 +35,12 @@
|
||||
#include "glib.h"
|
||||
#include "test-common.h"
|
||||
|
||||
#if defined(G_OS_UNIX)
|
||||
#include "gio/gdesktopappinfo.h"
|
||||
#elif defined(G_OS_WIN32)
|
||||
#include "gio/gwin32inputstream.h"
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_repository_basic (RepositoryFixture *fx,
|
||||
const void *unused)
|
||||
@@ -777,6 +783,67 @@ test_repository_vfunc_info_with_invoker_on_object (RepositoryFixture *fx,
|
||||
g_clear_pointer (&invoker_info, gi_base_info_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
test_repository_find_by_gtype (RepositoryFixture *fx,
|
||||
const void *unused)
|
||||
{
|
||||
GIObjectInfo *object_info = NULL;
|
||||
|
||||
g_test_summary ("Test finding a GType");
|
||||
|
||||
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT);
|
||||
g_assert_nonnull (object_info);
|
||||
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, "Object");
|
||||
|
||||
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||
|
||||
/* Find it again; this time it should hit the cache. */
|
||||
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT);
|
||||
g_assert_nonnull (object_info);
|
||||
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, "Object");
|
||||
|
||||
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||
|
||||
/* Try and find an unknown GType. */
|
||||
g_assert_null (gi_repository_find_by_gtype (fx->repository, GI_TYPE_BASE_INFO));
|
||||
|
||||
/* And check caching for unknown GTypes. */
|
||||
g_assert_null (gi_repository_find_by_gtype (fx->repository, GI_TYPE_BASE_INFO));
|
||||
|
||||
/* Now try and find one which will resolve in both Gio and GioUnix/GioWin32.
|
||||
* The longest-named typelib should be returned. */
|
||||
{
|
||||
GType platform_specific_type;
|
||||
const char *expected_name, *expected_namespace;
|
||||
|
||||
#if defined(G_OS_UNIX)
|
||||
platform_specific_type = G_TYPE_DESKTOP_APP_INFO;
|
||||
expected_name = "DesktopAppInfo";
|
||||
expected_namespace = "GioUnix";
|
||||
#elif defined(G_OS_WIN32)
|
||||
platform_specific_type = G_TYPE_WIN32_INPUT_STREAM;
|
||||
expected_name = "InputStream";
|
||||
expected_namespace = "GioWin32";
|
||||
#else
|
||||
platform_specific_type = G_TYPE_INVALID;
|
||||
expected_name = NULL;
|
||||
expected_namespace = NULL;
|
||||
#endif
|
||||
|
||||
if (expected_name != NULL)
|
||||
{
|
||||
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, platform_specific_type);
|
||||
g_assert_nonnull (object_info);
|
||||
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, expected_name);
|
||||
g_assert_cmpstr (gi_base_info_get_namespace (GI_BASE_INFO (object_info)), ==, expected_namespace);
|
||||
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@@ -804,6 +871,7 @@ main (int argc,
|
||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-no-invoker", test_repository_vfunc_info_with_no_invoker, &typelib_load_spec_gobject);
|
||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-interface", test_repository_vfunc_info_with_invoker_on_interface, &typelib_load_spec_gio);
|
||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-object", test_repository_vfunc_info_with_invoker_on_object, &typelib_load_spec_gio);
|
||||
ADD_REPOSITORY_TEST ("/repository/find-by-gtype", test_repository_find_by_gtype, &typelib_load_spec_gio_platform);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user