mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +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
|
static void
|
||||||
collect_namespaces (gpointer key,
|
collect_namespaces (GPtrArray *ordered_typelibs,
|
||||||
gpointer value,
|
char **names,
|
||||||
gpointer data)
|
size_t *inout_i)
|
||||||
{
|
{
|
||||||
GList **list = data;
|
for (guint j = 0; j < ordered_typelibs->len; j++)
|
||||||
|
{
|
||||||
*list = g_list_append (*list, key);
|
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,
|
gi_repository_get_loaded_namespaces (GIRepository *repository,
|
||||||
size_t *n_namespaces_out)
|
size_t *n_namespaces_out)
|
||||||
{
|
{
|
||||||
GList *l, *list = NULL;
|
|
||||||
char **names;
|
char **names;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
size_t n_typelibs;
|
||||||
|
|
||||||
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
||||||
|
|
||||||
g_hash_table_foreach (repository->typelibs, collect_namespaces, &list);
|
n_typelibs = repository->ordered_typelibs->len + repository->ordered_lazy_typelibs->len;
|
||||||
g_hash_table_foreach (repository->lazy_typelibs, collect_namespaces, &list);
|
names = g_malloc0 (sizeof (char *) * (n_typelibs + 1));
|
||||||
|
|
||||||
names = g_malloc0 (sizeof (char *) * (g_list_length (list) + 1));
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (l = list; l; l = l->next)
|
|
||||||
names[i++] = g_strdup (l->data);
|
collect_namespaces (repository->ordered_typelibs, names, &i);
|
||||||
g_list_free (list);
|
collect_namespaces (repository->ordered_lazy_typelibs, names, &i);
|
||||||
|
|
||||||
if (n_namespaces_out != NULL)
|
if (n_namespaces_out != NULL)
|
||||||
*n_namespaces_out = i;
|
*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
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char *argv[])
|
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-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/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/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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user