mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 14:36:13 +01:00
girepository: Make gi_repository_get_loaded_namespaces() deterministic
As with the previous two commits, the results of calling `gi_repository_get_loaded_namespaces()` were previously non-deterministic due to being generated by iterating over a hash table, which has a non-deterministic iteration order. Fix that by using the new `ordered_typelibs` and `ordered_lazy_typelibs` arrays to provide deterministic ordering. At the same time, significantly reduce the number of allocations needed to build the return value — previously the results would be built as a linked list before being turned into an array. The linked list is now banished to history. Add some more unit tests to maximise test coverage of this method. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Fixes: #3303
This commit is contained in:
parent
0d199d6199
commit
03248e7b18
@ -1232,13 +1232,16 @@ gi_repository_get_object_gtype_interfaces (GIRepository *repository,
|
||||
}
|
||||
|
||||
static void
|
||||
collect_namespaces (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
collect_namespaces (GPtrArray *ordered_typelibs,
|
||||
char **names,
|
||||
size_t *inout_i)
|
||||
{
|
||||
GList **list = data;
|
||||
|
||||
*list = g_list_append (*list, key);
|
||||
for (guint j = 0; j < ordered_typelibs->len; j++)
|
||||
{
|
||||
GITypelib *typelib = g_ptr_array_index (ordered_typelibs, j);
|
||||
const char *namespace = gi_typelib_get_namespace (typelib);
|
||||
names[(*inout_i)++] = g_strdup (namespace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1260,20 +1263,18 @@ char **
|
||||
gi_repository_get_loaded_namespaces (GIRepository *repository,
|
||||
size_t *n_namespaces_out)
|
||||
{
|
||||
GList *l, *list = NULL;
|
||||
char **names;
|
||||
size_t i;
|
||||
size_t n_typelibs;
|
||||
|
||||
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
||||
|
||||
g_hash_table_foreach (repository->typelibs, collect_namespaces, &list);
|
||||
g_hash_table_foreach (repository->lazy_typelibs, collect_namespaces, &list);
|
||||
|
||||
names = g_malloc0 (sizeof (char *) * (g_list_length (list) + 1));
|
||||
n_typelibs = repository->ordered_typelibs->len + repository->ordered_lazy_typelibs->len;
|
||||
names = g_malloc0 (sizeof (char *) * (n_typelibs + 1));
|
||||
i = 0;
|
||||
for (l = list; l; l = l->next)
|
||||
names[i++] = g_strdup (l->data);
|
||||
g_list_free (list);
|
||||
|
||||
collect_namespaces (repository->ordered_typelibs, names, &i);
|
||||
collect_namespaces (repository->ordered_lazy_typelibs, names, &i);
|
||||
|
||||
if (n_namespaces_out != NULL)
|
||||
*n_namespaces_out = i;
|
||||
|
@ -863,6 +863,35 @@ test_repository_find_by_gtype (RepositoryFixture *fx,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_repository_loaded_namespaces (RepositoryFixture *fx,
|
||||
const void *unused)
|
||||
{
|
||||
char **namespaces;
|
||||
size_t n_namespaces;
|
||||
|
||||
/* These should be in alphabetical order */
|
||||
#if defined(G_OS_UNIX)
|
||||
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", "GioUnix", NULL };
|
||||
#elif defined(G_OS_WIN32)
|
||||
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", "GioWin32", NULL };
|
||||
#else
|
||||
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", NULL };
|
||||
#endif
|
||||
|
||||
g_test_summary ("Test listing loaded namespaces");
|
||||
|
||||
namespaces = gi_repository_get_loaded_namespaces (fx->repository, &n_namespaces);
|
||||
g_assert_cmpstrv (namespaces, expected_namespaces);
|
||||
g_assert_cmpuint (n_namespaces, ==, g_strv_length ((char **) expected_namespaces));
|
||||
g_strfreev (namespaces);
|
||||
|
||||
/* Test again but without passing `n_namespaces`. */
|
||||
namespaces = gi_repository_get_loaded_namespaces (fx->repository, NULL);
|
||||
g_assert_cmpstrv (namespaces, expected_namespaces);
|
||||
g_strfreev (namespaces);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -891,6 +920,7 @@ main (int argc,
|
||||
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);
|
||||
ADD_REPOSITORY_TEST ("/repository/loaded-namespaces", test_repository_loaded_namespaces, &typelib_load_spec_gio_platform);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user