mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-28 16:36:14 +01:00
Merge branch '1601-appinfo-test-again' into 'master'
Support isolating directories for unit tests Closes #538 and #1601 See merge request GNOME/glib!505
This commit is contained in:
commit
70eb076ac3
@ -64,6 +64,7 @@ IGNORE_HFILES = \
|
||||
glib-init.h \
|
||||
gconstructor.h \
|
||||
valgrind.h \
|
||||
gutilsprivate.h \
|
||||
gvalgrind.h \
|
||||
$(NULL)
|
||||
|
||||
|
@ -1544,6 +1544,7 @@ g_strjoinv
|
||||
GStrv
|
||||
g_strv_length
|
||||
g_strv_contains
|
||||
g_strv_equal
|
||||
|
||||
<SUBSECTION>
|
||||
g_strerror
|
||||
@ -3101,6 +3102,7 @@ g_compute_hmac_for_bytes
|
||||
<SECTION>
|
||||
<TITLE>Testing</TITLE>
|
||||
<FILE>testing</FILE>
|
||||
G_TEST_OPTION_ISOLATE_DIRS
|
||||
g_test_minimized_result
|
||||
g_test_maximized_result
|
||||
g_test_init
|
||||
|
@ -36,6 +36,7 @@ if get_option('gtk_doc')
|
||||
'glib-init.h',
|
||||
'gconstructor.h',
|
||||
'valgrind.h',
|
||||
'gutilsprivate.h',
|
||||
'gvalgrind.h',
|
||||
]
|
||||
|
||||
|
@ -41,13 +41,13 @@
|
||||
*
|
||||
* A content type is a platform specific string that defines the type
|
||||
* of a file. On UNIX it is a
|
||||
* [mime type](http://www.wikipedia.org/wiki/Internet_media_type)
|
||||
* like "text/plain" or "image/png".
|
||||
* On Win32 it is an extension string like ".doc", ".txt" or a perceived
|
||||
* string like "audio". Such strings can be looked up in the registry at
|
||||
* HKEY_CLASSES_ROOT.
|
||||
* On OSX it is a [Uniform Type Identifier](https://en.wikipedia.org/wiki/Uniform_Type_Identifier)
|
||||
* such as "com.apple.application".
|
||||
* [MIME type](http://www.wikipedia.org/wiki/Internet_media_type)
|
||||
* like `text/plain` or `image/png`.
|
||||
* On Win32 it is an extension string like `.doc`, `.txt` or a perceived
|
||||
* string like `audio`. Such strings can be looked up in the registry at
|
||||
* `HKEY_CLASSES_ROOT`.
|
||||
* On macOS it is a [Uniform Type Identifier](https://en.wikipedia.org/wiki/Uniform_Type_Identifier)
|
||||
* such as `com.apple.application`.
|
||||
**/
|
||||
|
||||
#include <dirent.h>
|
||||
@ -55,6 +55,8 @@
|
||||
#define XDG_PREFIX _gio_xdg
|
||||
#include "xdgmime/xdgmime.h"
|
||||
|
||||
static void tree_magic_schedule_reload (void);
|
||||
|
||||
/* We lock this mutex whenever we modify global state in this module. */
|
||||
G_LOCK_DEFINE_STATIC (gio_xdgmime);
|
||||
|
||||
@ -111,6 +113,106 @@ _g_unix_content_type_get_parents (const gchar *type)
|
||||
return (gchar **)g_ptr_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
G_LOCK_DEFINE_STATIC (global_mime_dirs);
|
||||
static gchar **global_mime_dirs = NULL;
|
||||
|
||||
static void
|
||||
_g_content_type_set_mime_dirs_locked (const char * const *dirs)
|
||||
{
|
||||
g_clear_pointer (&global_mime_dirs, g_strfreev);
|
||||
|
||||
if (dirs != NULL)
|
||||
{
|
||||
global_mime_dirs = g_strdupv ((gchar **) dirs);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPtrArray *mime_dirs = g_ptr_array_new_with_free_func (g_free);
|
||||
const gchar * const *system_dirs = g_get_system_data_dirs ();
|
||||
|
||||
g_ptr_array_add (mime_dirs, g_build_filename (g_get_user_data_dir (), "mime", NULL));
|
||||
for (; *system_dirs != NULL; system_dirs++)
|
||||
g_ptr_array_add (mime_dirs, g_build_filename (*system_dirs, "mime", NULL));
|
||||
g_ptr_array_add (mime_dirs, NULL); /* NULL terminator */
|
||||
|
||||
global_mime_dirs = (gchar **) g_ptr_array_free (mime_dirs, FALSE);
|
||||
}
|
||||
|
||||
xdg_mime_set_dirs ((const gchar * const *) global_mime_dirs);
|
||||
tree_magic_schedule_reload ();
|
||||
}
|
||||
|
||||
/**
|
||||
* g_content_type_set_mime_dirs:
|
||||
* @dirs: (array zero-terminated=1) (nullable): %NULL-terminated list of
|
||||
* directories to load MIME data from, including any `mime/` subdirectory,
|
||||
* and with the first directory to try listed first
|
||||
*
|
||||
* Set the list of directories used by GIO to load the MIME database.
|
||||
* If @dirs is %NULL, the directories used are the default:
|
||||
*
|
||||
* - the `mime` subdirectory of the directory in `$XDG_DATA_HOME`
|
||||
* - the `mime` subdirectory of every directory in `$XDG_DATA_DIRS`
|
||||
*
|
||||
* This function is intended to be used when writing tests that depend on
|
||||
* information stored in the MIME database, in order to control the data.
|
||||
*
|
||||
* Typically, in case your tests use %G_TEST_OPTION_ISOLATE_DIRS, but they
|
||||
* depend on the system’s MIME database, you should call this function
|
||||
* with @dirs set to %NULL before calling g_test_init(), for instance:
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* // Load MIME data from the system
|
||||
* g_content_type_set_mime_dirs (NULL);
|
||||
* // Isolate the environment
|
||||
* g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
*
|
||||
* …
|
||||
*
|
||||
* return g_test_run ();
|
||||
* ]|
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
/*< private >*/
|
||||
void
|
||||
g_content_type_set_mime_dirs (const gchar * const *dirs)
|
||||
{
|
||||
G_LOCK (global_mime_dirs);
|
||||
_g_content_type_set_mime_dirs_locked (dirs);
|
||||
G_UNLOCK (global_mime_dirs);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_content_type_get_mime_dirs:
|
||||
*
|
||||
* Get the list of directories which MIME data is loaded from. See
|
||||
* g_content_type_set_mime_dirs() for details.
|
||||
*
|
||||
* Returns: (transfer none) (array zero-terminated=1): %NULL-terminated list of
|
||||
* directories to load MIME data from, including any `mime/` subdirectory,
|
||||
* and with the first directory to try listed first
|
||||
* Since: 2.60
|
||||
*/
|
||||
/*< private >*/
|
||||
const gchar * const *
|
||||
g_content_type_get_mime_dirs (void)
|
||||
{
|
||||
const gchar * const *mime_dirs;
|
||||
|
||||
G_LOCK (global_mime_dirs);
|
||||
|
||||
if (global_mime_dirs == NULL)
|
||||
_g_content_type_set_mime_dirs_locked (NULL);
|
||||
|
||||
mime_dirs = (const gchar * const *) global_mime_dirs;
|
||||
|
||||
G_UNLOCK (global_mime_dirs);
|
||||
|
||||
g_assert (mime_dirs != NULL);
|
||||
return mime_dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_content_type_equals:
|
||||
* @type1: a content type string
|
||||
@ -306,7 +408,7 @@ load_comment_for_mime_helper (const char *dir,
|
||||
mime_info_text
|
||||
};
|
||||
|
||||
filename = g_build_filename (dir, "mime", basename, NULL);
|
||||
filename = g_build_filename (dir, basename, NULL);
|
||||
|
||||
res = g_file_get_contents (filename, &data, &len, NULL);
|
||||
g_free (filename);
|
||||
@ -328,22 +430,14 @@ load_comment_for_mime_helper (const char *dir,
|
||||
static char *
|
||||
load_comment_for_mime (const char *mimetype)
|
||||
{
|
||||
const char * const* dirs;
|
||||
const char * const *dirs;
|
||||
char *basename;
|
||||
char *comment;
|
||||
int i;
|
||||
gsize i;
|
||||
|
||||
basename = g_strdup_printf ("%s.xml", mimetype);
|
||||
|
||||
comment = load_comment_for_mime_helper (g_get_user_data_dir (), basename);
|
||||
if (comment)
|
||||
{
|
||||
g_free (basename);
|
||||
return comment;
|
||||
}
|
||||
|
||||
dirs = g_get_system_data_dirs ();
|
||||
|
||||
dirs = g_content_type_get_mime_dirs ();
|
||||
for (i = 0; dirs[i] != NULL; i++)
|
||||
{
|
||||
comment = load_comment_for_mime_helper (dirs[i], basename);
|
||||
@ -780,10 +874,10 @@ enumerate_mimetypes_dir (const char *dir,
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *ent;
|
||||
char *mimedir;
|
||||
const char *mimedir;
|
||||
char *name;
|
||||
|
||||
mimedir = g_build_filename (dir, "mime", NULL);
|
||||
mimedir = dir;
|
||||
|
||||
d = opendir (mimedir);
|
||||
if (d)
|
||||
@ -800,8 +894,6 @@ enumerate_mimetypes_dir (const char *dir,
|
||||
}
|
||||
closedir (d);
|
||||
}
|
||||
|
||||
g_free (mimedir);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -809,7 +901,7 @@ enumerate_mimetypes_dir (const char *dir,
|
||||
*
|
||||
* Gets a list of strings containing all the registered content types
|
||||
* known to the system. The list and its data should be freed using
|
||||
* g_list_free_full (list, g_free).
|
||||
* `g_list_free_full (list, g_free)`.
|
||||
*
|
||||
* Returns: (element-type utf8) (transfer full): list of the registered
|
||||
* content types
|
||||
@ -817,18 +909,16 @@ enumerate_mimetypes_dir (const char *dir,
|
||||
GList *
|
||||
g_content_types_get_registered (void)
|
||||
{
|
||||
const char * const* dirs;
|
||||
const char * const *dirs;
|
||||
GHashTable *mimetypes;
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
int i;
|
||||
gsize i;
|
||||
GList *l;
|
||||
|
||||
mimetypes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
enumerate_mimetypes_dir (g_get_user_data_dir (), mimetypes);
|
||||
dirs = g_get_system_data_dirs ();
|
||||
|
||||
dirs = g_content_type_get_mime_dirs ();
|
||||
for (i = 0; dirs[i] != NULL; i++)
|
||||
enumerate_mimetypes_dir (dirs[i], mimetypes);
|
||||
|
||||
@ -1030,7 +1120,7 @@ read_tree_magic_from_directory (const gchar *prefix)
|
||||
TreeMatchlet *matchlet;
|
||||
gint depth;
|
||||
|
||||
filename = g_build_filename (prefix, "mime", "treemagic", NULL);
|
||||
filename = g_build_filename (prefix, "treemagic", NULL);
|
||||
|
||||
if (g_file_get_contents (filename, &text, &len, NULL))
|
||||
{
|
||||
@ -1068,11 +1158,16 @@ read_tree_magic_from_directory (const gchar *prefix)
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_magic_schedule_reload (void)
|
||||
{
|
||||
need_reload = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_mime_reload (void *user_data)
|
||||
{
|
||||
need_reload = TRUE;
|
||||
tree_magic_schedule_reload ();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1086,9 +1181,7 @@ static void
|
||||
tree_magic_init (void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
const gchar *dir;
|
||||
const gchar * const * dirs;
|
||||
int i;
|
||||
gsize i;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
@ -1100,14 +1193,14 @@ tree_magic_init (void)
|
||||
|
||||
if (need_reload)
|
||||
{
|
||||
const char * const *dirs;
|
||||
|
||||
need_reload = FALSE;
|
||||
|
||||
tree_magic_shutdown ();
|
||||
|
||||
dir = g_get_user_data_dir ();
|
||||
read_tree_magic_from_directory (dir);
|
||||
dirs = g_get_system_data_dirs ();
|
||||
for (i = 0; dirs[i]; i++)
|
||||
dirs = g_content_type_get_mime_dirs ();
|
||||
for (i = 0; dirs[i] != NULL; i++)
|
||||
read_tree_magic_from_directory (dirs[i]);
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,12 @@ gchar ** g_content_type_guess_for_tree (GFile *root);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList * g_content_types_get_registered (void);
|
||||
|
||||
/*< private >*/
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
const gchar * const *g_content_type_get_mime_dirs (void);
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
void g_content_type_set_mime_dirs (const gchar * const *dirs);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_CONTENT_TYPE_H__ */
|
||||
|
@ -152,6 +152,7 @@ typedef struct
|
||||
|
||||
static DesktopFileDir *desktop_file_dirs;
|
||||
static guint n_desktop_file_dirs;
|
||||
static const gchar *desktop_file_dirs_config_dir = NULL;
|
||||
static const guint desktop_file_dir_user_config_index = 0;
|
||||
static guint desktop_file_dir_user_data_index;
|
||||
static GMutex desktop_file_dir_lock;
|
||||
@ -1476,9 +1477,24 @@ static void
|
||||
desktop_file_dirs_lock (void)
|
||||
{
|
||||
gint i;
|
||||
const gchar *user_config_dir = g_get_user_config_dir ();
|
||||
|
||||
g_mutex_lock (&desktop_file_dir_lock);
|
||||
|
||||
/* If the XDG dirs configuration has changed (expected only during tests),
|
||||
* clear and reload the state. */
|
||||
if (g_strcmp0 (desktop_file_dirs_config_dir, user_config_dir) != 0)
|
||||
{
|
||||
g_debug ("%s: Resetting desktop app info dirs from %s to %s",
|
||||
G_STRFUNC, desktop_file_dirs_config_dir, user_config_dir);
|
||||
|
||||
for (i = 0; i < n_desktop_file_dirs; i++)
|
||||
desktop_file_dir_reset (&desktop_file_dirs[i]);
|
||||
g_clear_pointer (&desktop_file_dirs, g_free);
|
||||
n_desktop_file_dirs = 0;
|
||||
desktop_file_dir_user_data_index = 0;
|
||||
}
|
||||
|
||||
if (desktop_file_dirs == NULL)
|
||||
{
|
||||
const char * const *dirs;
|
||||
@ -1488,7 +1504,7 @@ desktop_file_dirs_lock (void)
|
||||
tmp = g_array_new (FALSE, FALSE, sizeof (DesktopFileDir));
|
||||
|
||||
/* First, the configs. Highest priority: the user's ~/.config */
|
||||
desktop_file_dir_create_for_config (tmp, g_get_user_config_dir ());
|
||||
desktop_file_dir_create_for_config (tmp, user_config_dir);
|
||||
|
||||
/* Next, the system configs (/etc/xdg, and so on). */
|
||||
dirs = g_get_system_config_dirs ();
|
||||
@ -1504,9 +1520,11 @@ desktop_file_dirs_lock (void)
|
||||
for (i = 0; dirs[i]; i++)
|
||||
desktop_file_dir_create (tmp, dirs[i]);
|
||||
|
||||
/* The list of directories will never change after this. */
|
||||
/* The list of directories will never change after this, unless
|
||||
* g_get_user_config_dir() changes due to %G_TEST_OPTION_ISOLATE_DIRS. */
|
||||
desktop_file_dirs = (DesktopFileDir *) tmp->data;
|
||||
n_desktop_file_dirs = tmp->len;
|
||||
desktop_file_dirs_config_dir = user_config_dir;
|
||||
|
||||
g_array_free (tmp, FALSE);
|
||||
}
|
||||
@ -3191,6 +3209,8 @@ ensure_dir (DirType type,
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
g_debug ("%s: Ensuring %s", G_STRFUNC, path);
|
||||
|
||||
errno = 0;
|
||||
if (g_mkdir_with_parents (path, 0700) == 0)
|
||||
return path;
|
||||
|
3
gio/tests/.gitignore
vendored
3
gio/tests/.gitignore
vendored
@ -141,9 +141,6 @@ unix-fd
|
||||
unix-streams
|
||||
vfs
|
||||
volumemonitor
|
||||
xdgconfighome
|
||||
xdgdatadir
|
||||
xdgdatahome
|
||||
xgen-gio
|
||||
xgen-giosrc.c
|
||||
gresource-big-test.txt
|
||||
|
@ -339,10 +339,7 @@ dist_test_data += \
|
||||
|
||||
dist_test_data += \
|
||||
appinfo-test-actions.desktop \
|
||||
appinfo-test-gnome.desktop \
|
||||
appinfo-test-notgnome.desktop \
|
||||
appinfo-test.desktop \
|
||||
appinfo-test2.desktop \
|
||||
appinfo-test-static.desktop \
|
||||
file.c \
|
||||
org.gtk.test.dbusappinfo.desktop \
|
||||
x-content/image-dcf/DCIM/Camera/20130831_203925.jpg \
|
||||
@ -362,11 +359,37 @@ uninstalled_test_extra_programs += \
|
||||
if !OS_COCOA
|
||||
test_extra_programs += apps
|
||||
test_programs += mimeapps
|
||||
clean-local: clean-mimeapps
|
||||
clean-mimeapps:
|
||||
rm -rf xdgdatadir xdgdatahome xdgconfighome
|
||||
endif
|
||||
|
||||
appinfo-test-gnome.desktop: appinfo-test-gnome.desktop.in Makefile
|
||||
$(AM_V_GEN)$(SED) \
|
||||
-e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
|
||||
$< > $@
|
||||
appinfo-test-notgnome.desktop: appinfo-test-notgnome.desktop.in Makefile
|
||||
$(AM_V_GEN)$(SED) \
|
||||
-e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
|
||||
$< > $@
|
||||
appinfo-test.desktop: appinfo-test.desktop.in Makefile
|
||||
$(AM_V_GEN)$(SED) \
|
||||
-e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
|
||||
$< > $@
|
||||
appinfo-test2.desktop: appinfo-test2.desktop.in Makefile
|
||||
$(AM_V_GEN)$(SED) \
|
||||
-e 's|[@]installed_tests_dir[@]|$(installed_testdir)|g' \
|
||||
$< > $@
|
||||
|
||||
appinfo_desktop_templates = \
|
||||
appinfo-test-gnome.desktop.in \
|
||||
appinfo-test-notgnome.desktop.in \
|
||||
appinfo-test.desktop.in \
|
||||
appinfo-test2.desktop.in \
|
||||
$(NULL)
|
||||
appinfo_desktop_files = $(appinfo_desktop_templates:.in=)
|
||||
|
||||
EXTRA_DIST += $(appinfo_desktop_templates)
|
||||
CLEANFILES += $(appinfo_desktop_files)
|
||||
test_data += $(appinfo_desktop_files)
|
||||
|
||||
uninstalled_test_programs += gsettings gschema-compile
|
||||
gsettings_DEPENDENCIES = test.mo
|
||||
CLEANFILES += test.mo de/LC_MESSAGES/test.mo keyfile/gsettings.store
|
||||
|
@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=appinfo-test
|
||||
Exec=./appinfo-test --option
|
||||
Exec=@installed_tests_dir@/appinfo-test --option
|
||||
OnlyShowIn=GNOME;KDE;
|
||||
NotShowIn=ROX;
|
@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=appinfo-test
|
||||
Exec=./appinfo-test --option
|
||||
Exec=@installed_tests_dir@/appinfo-test --option
|
||||
OnlyShowIn=KDE;
|
||||
NotShowIn=GNOME;
|
19
gio/tests/appinfo-test-static.desktop
Normal file
19
gio/tests/appinfo-test-static.desktop
Normal file
@ -0,0 +1,19 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
GenericName=generic-appinfo-test
|
||||
Name=appinfo-test
|
||||
Name[de]=appinfo-test-de
|
||||
X-GNOME-FullName=example
|
||||
X-GNOME-FullName[de]=Beispiel
|
||||
Comment=GAppInfo example
|
||||
Comment[de]=GAppInfo Beispiel
|
||||
Exec=true --option %U %i --name %c --filename %k %m %%
|
||||
Icon=testicon.svg
|
||||
Terminal=true
|
||||
StartupNotify=true
|
||||
StartupWMClass=appinfo-class
|
||||
MimeType=image/png;image/jpeg;
|
||||
Keywords=keyword1;test keyword;
|
||||
Categories=GNOME;GTK;
|
||||
X-JunkFood=Burger
|
||||
X-JunkFood[de]=Bratwurst
|
@ -14,7 +14,7 @@ main (int argc, char *argv[])
|
||||
gchar *expected;
|
||||
gint pid_from_env;
|
||||
|
||||
expected = g_test_build_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
expected = g_test_build_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
|
||||
g_assert_cmpstr (envvar, ==, expected);
|
||||
g_free (expected);
|
||||
|
||||
|
@ -7,7 +7,7 @@ X-GNOME-FullName=example
|
||||
X-GNOME-FullName[de]=Beispiel
|
||||
Comment=GAppInfo example
|
||||
Comment[de]=GAppInfo Beispiel
|
||||
Exec=./appinfo-test --option %U %i --name %c --filename %k %m %%
|
||||
Exec=@installed_tests_dir@/appinfo-test --option %U %i --name %c --filename %k %m %%
|
||||
Icon=testicon.svg
|
||||
Terminal=true
|
||||
StartupNotify=true
|
@ -6,6 +6,6 @@ X-GNOME-FullName=example
|
||||
X-GNOME-FullName[de]=Beispiel
|
||||
Comment=GAppInfo example
|
||||
Comment[de]=GAppInfo Beispiel
|
||||
Exec=./appinfo-test --option
|
||||
Exec=@installed_tests_dir@/appinfo-test --option
|
||||
TryExec=does-not-exist
|
||||
Icon=testicon
|
@ -6,115 +6,11 @@
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gdesktopappinfo.h>
|
||||
|
||||
static gboolean
|
||||
cleanup_dir_recurse (GFile *parent,
|
||||
GFile *root,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GFileEnumerator *enumerator;
|
||||
GError *local_error = NULL;
|
||||
|
||||
g_assert (root != NULL);
|
||||
|
||||
enumerator =
|
||||
g_file_enumerate_children (parent, "*",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
|
||||
&local_error);
|
||||
if (!enumerator)
|
||||
{
|
||||
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&local_error);
|
||||
ret = TRUE;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GFile *child;
|
||||
GFileInfo *finfo;
|
||||
char *relative_path;
|
||||
|
||||
if (!g_file_enumerator_iterate (enumerator, &finfo, &child, NULL, error))
|
||||
goto out;
|
||||
if (!finfo)
|
||||
break;
|
||||
|
||||
relative_path = g_file_get_relative_path (root, child);
|
||||
g_assert (relative_path != NULL);
|
||||
g_free (relative_path);
|
||||
|
||||
if (g_file_info_get_file_type (finfo) == G_FILE_TYPE_DIRECTORY)
|
||||
{
|
||||
if (!cleanup_dir_recurse (child, root, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_file_delete (child, NULL, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
g_clear_object (&enumerator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *tmp_dir;
|
||||
gchar *config_dir;
|
||||
gchar *data_dir;
|
||||
} Fixture;
|
||||
|
||||
static void
|
||||
setup (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
|
||||
fixture->tmp_dir = g_dir_make_tmp ("gio-test-appinfo_XXXXXX", &local_error);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
fixture->config_dir = g_build_filename (fixture->tmp_dir, "config", NULL);
|
||||
g_assert_cmpint (g_mkdir (fixture->config_dir, 0755), ==, 0);
|
||||
|
||||
fixture->data_dir = g_build_filename (fixture->tmp_dir, "data", NULL);
|
||||
g_assert_cmpint (g_mkdir (fixture->data_dir, 0755), ==, 0);
|
||||
|
||||
g_setenv ("XDG_CONFIG_HOME", fixture->config_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_HOME", fixture->data_dir, TRUE);
|
||||
|
||||
g_setenv ("XDG_DATA_DIRS", "/dev/null", TRUE);
|
||||
g_setenv ("XDG_CONFIG_DIRS", "/dev/null", TRUE);
|
||||
g_setenv ("XDG_CACHE_HOME", "/dev/null", TRUE);
|
||||
g_setenv ("XDG_RUNTIME_DIR", "/dev/null", TRUE);
|
||||
|
||||
g_test_message ("Using tmp directory: %s", fixture->tmp_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
teardown (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GFile *tmp_dir = g_file_new_for_path (fixture->tmp_dir);
|
||||
GError *local_error = NULL;
|
||||
|
||||
cleanup_dir_recurse (tmp_dir, tmp_dir, &local_error);
|
||||
g_assert_no_error (local_error);
|
||||
|
||||
g_clear_pointer (&fixture->config_dir, g_free);
|
||||
g_clear_pointer (&fixture->data_dir, g_free);
|
||||
g_clear_pointer (&fixture->tmp_dir, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_for_app_info (GAppInfo *appinfo)
|
||||
{
|
||||
GError *error;
|
||||
GError *error = NULL;
|
||||
gboolean success;
|
||||
GFile *file;
|
||||
GList *l;
|
||||
const gchar *path;
|
||||
@ -126,52 +22,59 @@ test_launch_for_app_info (GAppInfo *appinfo)
|
||||
return;
|
||||
}
|
||||
|
||||
error = NULL;
|
||||
g_assert (g_app_info_launch (appinfo, NULL, NULL, &error));
|
||||
success = g_app_info_launch (appinfo, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (success);
|
||||
|
||||
g_assert (g_app_info_launch_uris (appinfo, NULL, NULL, &error));
|
||||
success = g_app_info_launch_uris (appinfo, NULL, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (success);
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
|
||||
file = g_file_new_for_path (path);
|
||||
l = NULL;
|
||||
l = g_list_append (l, file);
|
||||
|
||||
g_assert (g_app_info_launch (appinfo, l, NULL, &error));
|
||||
success = g_app_info_launch (appinfo, l, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (success);
|
||||
g_list_free (l);
|
||||
g_object_unref (file);
|
||||
|
||||
l = NULL;
|
||||
uri = g_strconcat ("file://", g_test_get_dir (G_TEST_DIST), "/appinfo-test.desktop", NULL);
|
||||
uri = g_strconcat ("file://", g_test_get_dir (G_TEST_BUILT), "/appinfo-test.desktop", NULL);
|
||||
l = g_list_append (l, uri);
|
||||
l = g_list_append (l, "file:///etc/group#adm");
|
||||
|
||||
g_assert (g_app_info_launch_uris (appinfo, l, NULL, &error));
|
||||
success = g_app_info_launch_uris (appinfo, l, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (success);
|
||||
|
||||
g_list_free (l);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_launch (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
g_assert (appinfo != NULL);
|
||||
|
||||
if (appinfo == NULL)
|
||||
{
|
||||
g_test_skip ("appinfo-test binary not installed");
|
||||
return;
|
||||
}
|
||||
|
||||
test_launch_for_app_info (appinfo);
|
||||
g_object_unref (appinfo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_no_app_id (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_launch_no_app_id (void)
|
||||
{
|
||||
const gchar desktop_file_base_contents[] =
|
||||
"[Desktop Entry]\n"
|
||||
@ -191,13 +94,16 @@ test_launch_no_app_id (Fixture *fixture,
|
||||
"Keywords=keyword1;test keyword;\n"
|
||||
"Categories=GNOME;GTK;\n";
|
||||
|
||||
const char *exec_line_variants[] = {
|
||||
"Exec=./appinfo-test --option %U %i --name %c --filename %k %m %%",
|
||||
"Exec=./appinfo-test --option %u %i --name %c --filename %k %m %%"
|
||||
};
|
||||
|
||||
gchar *exec_line_variants[2];
|
||||
gsize i;
|
||||
|
||||
exec_line_variants[0] = g_strdup_printf (
|
||||
"Exec=%s/appinfo-test --option %%U %%i --name %%c --filename %%k %%m %%%%",
|
||||
g_test_get_dir (G_TEST_BUILT));
|
||||
exec_line_variants[1] = g_strdup_printf (
|
||||
"Exec=%s/appinfo-test --option %%u %%i --name %%c --filename %%k %%m %%%%",
|
||||
g_test_get_dir (G_TEST_BUILT));
|
||||
|
||||
g_test_bug ("791337");
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (exec_line_variants); i++)
|
||||
@ -221,7 +127,7 @@ test_launch_no_app_id (Fixture *fixture,
|
||||
g_assert_true (loaded);
|
||||
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_keyfile (fake_desktop_file);
|
||||
g_assert (appinfo != NULL);
|
||||
g_assert_nonnull (appinfo);
|
||||
|
||||
test_launch_for_app_info (appinfo);
|
||||
|
||||
@ -229,6 +135,9 @@ test_launch_no_app_id (Fixture *fixture,
|
||||
g_object_unref (appinfo);
|
||||
g_key_file_unref (fake_desktop_file);
|
||||
}
|
||||
|
||||
g_free (exec_line_variants[1]);
|
||||
g_free (exec_line_variants[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -242,7 +151,7 @@ test_locale (const char *locale)
|
||||
g_setenv ("LANGUAGE", locale, TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
|
||||
if (g_strcmp0 (locale, "C") == 0)
|
||||
@ -272,8 +181,7 @@ test_locale (const char *locale)
|
||||
}
|
||||
|
||||
static void
|
||||
test_text (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_text (void)
|
||||
{
|
||||
test_locale ("C");
|
||||
test_locale ("en_US");
|
||||
@ -282,24 +190,24 @@ test_text (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_basic (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
GAppInfo *appinfo2;
|
||||
GIcon *icon, *icon2;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
g_assert_nonnull (appinfo);
|
||||
|
||||
g_assert_cmpstr (g_app_info_get_id (appinfo), ==, "appinfo-test.desktop");
|
||||
g_assert (strstr (g_app_info_get_executable (appinfo), "appinfo-test") != NULL);
|
||||
g_assert_cmpstr (g_app_info_get_id (appinfo), ==, "appinfo-test-static.desktop");
|
||||
g_assert_nonnull (strstr (g_app_info_get_executable (appinfo), "true"));
|
||||
|
||||
icon = g_app_info_get_icon (appinfo);
|
||||
g_assert (G_IS_THEMED_ICON (icon));
|
||||
g_assert_true (G_IS_THEMED_ICON (icon));
|
||||
icon2 = g_themed_icon_new ("testicon");
|
||||
g_assert (g_icon_equal (icon, icon2));
|
||||
g_assert_true (g_icon_equal (icon, icon2));
|
||||
g_object_unref (icon2);
|
||||
|
||||
appinfo2 = g_app_info_dup (appinfo);
|
||||
@ -311,31 +219,36 @@ test_basic (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_show_in (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_show_in (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
g_assert (g_app_info_should_show (appinfo));
|
||||
|
||||
if (appinfo == NULL)
|
||||
{
|
||||
g_test_skip ("appinfo-test binary not installed");
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_true (g_app_info_should_show (appinfo));
|
||||
g_object_unref (appinfo);
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-gnome.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test-gnome.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
g_assert (g_app_info_should_show (appinfo));
|
||||
g_assert_true (g_app_info_should_show (appinfo));
|
||||
g_object_unref (appinfo);
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-notgnome.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test-notgnome.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
g_assert (!g_app_info_should_show (appinfo));
|
||||
g_assert_false (g_app_info_should_show (appinfo));
|
||||
g_object_unref (appinfo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_commandline (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_commandline (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
GError *error;
|
||||
@ -350,12 +263,12 @@ test_commandline (Fixture *fixture,
|
||||
"cmdline-app-test",
|
||||
G_APP_INFO_CREATE_SUPPORTS_URIS,
|
||||
&error);
|
||||
g_assert (appinfo != NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (appinfo);
|
||||
g_assert_cmpstr (g_app_info_get_name (appinfo), ==, "cmdline-app-test");
|
||||
g_assert_cmpstr (g_app_info_get_commandline (appinfo), ==, cmdline_out);
|
||||
g_assert (g_app_info_supports_uris (appinfo));
|
||||
g_assert (!g_app_info_supports_files (appinfo));
|
||||
g_assert_true (g_app_info_supports_uris (appinfo));
|
||||
g_assert_false (g_app_info_supports_files (appinfo));
|
||||
|
||||
g_object_unref (appinfo);
|
||||
|
||||
@ -367,12 +280,12 @@ test_commandline (Fixture *fixture,
|
||||
"cmdline-app-test",
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert (appinfo != NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert_nonnull (appinfo);
|
||||
g_assert_cmpstr (g_app_info_get_name (appinfo), ==, "cmdline-app-test");
|
||||
g_assert_cmpstr (g_app_info_get_commandline (appinfo), ==, cmdline_out);
|
||||
g_assert (!g_app_info_supports_uris (appinfo));
|
||||
g_assert (g_app_info_supports_files (appinfo));
|
||||
g_assert_false (g_app_info_supports_uris (appinfo));
|
||||
g_assert_true (g_app_info_supports_files (appinfo));
|
||||
|
||||
g_object_unref (appinfo);
|
||||
|
||||
@ -381,8 +294,7 @@ test_commandline (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_context (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_launch_context (void)
|
||||
{
|
||||
GAppLaunchContext *context;
|
||||
GAppInfo *appinfo;
|
||||
@ -398,10 +310,10 @@ test_launch_context (Fixture *fixture,
|
||||
NULL);
|
||||
|
||||
str = g_app_launch_context_get_display (context, appinfo, NULL);
|
||||
g_assert (str == NULL);
|
||||
g_assert_null (str);
|
||||
|
||||
str = g_app_launch_context_get_startup_notify_id (context, appinfo, NULL);
|
||||
g_assert (str == NULL);
|
||||
g_assert_null (str);
|
||||
|
||||
g_object_unref (appinfo);
|
||||
g_object_unref (context);
|
||||
@ -420,8 +332,8 @@ launched (GAppLaunchContext *context,
|
||||
gint pid;
|
||||
|
||||
pid = 0;
|
||||
g_assert (g_variant_lookup (platform_data, "pid", "i", &pid));
|
||||
g_assert (pid != 0);
|
||||
g_assert_true (g_variant_lookup (platform_data, "pid", "i", &pid));
|
||||
g_assert_cmpint (pid, !=, 0);
|
||||
|
||||
launched_reached = TRUE;
|
||||
}
|
||||
@ -434,12 +346,12 @@ launch_failed (GAppLaunchContext *context,
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_context_signals (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_launch_context_signals (void)
|
||||
{
|
||||
GAppLaunchContext *context;
|
||||
GAppInfo *appinfo;
|
||||
GError *error = NULL;
|
||||
gboolean success;
|
||||
gchar *cmdline;
|
||||
|
||||
cmdline = g_strconcat (g_test_get_dir (G_TEST_BUILT), "/appinfo-test --option", NULL);
|
||||
@ -452,11 +364,11 @@ test_launch_context_signals (Fixture *fixture,
|
||||
G_APP_INFO_CREATE_SUPPORTS_URIS,
|
||||
NULL);
|
||||
|
||||
error = NULL;
|
||||
g_assert (g_app_info_launch (appinfo, NULL, context, &error));
|
||||
success = g_app_info_launch (appinfo, NULL, context, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (success);
|
||||
|
||||
g_assert (launched_reached);
|
||||
g_assert_true (launched_reached);
|
||||
|
||||
g_object_unref (appinfo);
|
||||
g_object_unref (context);
|
||||
@ -465,28 +377,26 @@ test_launch_context_signals (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_tryexec (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_tryexec (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test2.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test2.desktop", NULL);
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new_from_filename (path);
|
||||
|
||||
g_assert (appinfo == NULL);
|
||||
g_assert_null (appinfo);
|
||||
}
|
||||
|
||||
/* Test that we can set an appinfo as default for a mime type or
|
||||
* file extension, and also add and remove handled mime types.
|
||||
*/
|
||||
static void
|
||||
test_associations (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_associations (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
GAppInfo *appinfo2;
|
||||
GError *error;
|
||||
GError *error = NULL;
|
||||
gboolean result;
|
||||
GList *list;
|
||||
gchar *cmdline;
|
||||
@ -498,33 +408,31 @@ test_associations (Fixture *fixture,
|
||||
NULL);
|
||||
g_free (cmdline);
|
||||
|
||||
error = NULL;
|
||||
result = g_app_info_set_as_default_for_type (appinfo, "application/x-glib-test", &error);
|
||||
|
||||
g_assert (result);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (result);
|
||||
|
||||
appinfo2 = g_app_info_get_default_for_type ("application/x-glib-test", FALSE);
|
||||
|
||||
g_assert (appinfo2);
|
||||
g_assert_nonnull (appinfo2);
|
||||
g_assert_cmpstr (g_app_info_get_commandline (appinfo), ==, g_app_info_get_commandline (appinfo2));
|
||||
|
||||
g_object_unref (appinfo2);
|
||||
|
||||
result = g_app_info_set_as_default_for_extension (appinfo, "gio-tests", &error);
|
||||
g_assert (result);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (result);
|
||||
|
||||
appinfo2 = g_app_info_get_default_for_type ("application/x-extension-gio-tests", FALSE);
|
||||
|
||||
g_assert (appinfo2);
|
||||
g_assert_nonnull (appinfo2);
|
||||
g_assert_cmpstr (g_app_info_get_commandline (appinfo), ==, g_app_info_get_commandline (appinfo2));
|
||||
|
||||
g_object_unref (appinfo2);
|
||||
|
||||
result = g_app_info_add_supports_type (appinfo, "application/x-gio-test", &error);
|
||||
g_assert (result);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (result);
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-gio-test");
|
||||
g_assert_cmpint (g_list_length (list), ==, 1);
|
||||
@ -533,18 +441,18 @@ test_associations (Fixture *fixture,
|
||||
g_object_unref (appinfo2);
|
||||
g_list_free (list);
|
||||
|
||||
g_assert (g_app_info_can_remove_supports_type (appinfo));
|
||||
g_assert (g_app_info_remove_supports_type (appinfo, "application/x-gio-test", &error));
|
||||
g_assert_true (g_app_info_can_remove_supports_type (appinfo));
|
||||
result = g_app_info_remove_supports_type (appinfo, "application/x-gio-test", &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (result);
|
||||
|
||||
g_assert (g_app_info_can_delete (appinfo));
|
||||
g_assert (g_app_info_delete (appinfo));
|
||||
g_assert_true (g_app_info_can_delete (appinfo));
|
||||
g_assert_true (g_app_info_delete (appinfo));
|
||||
g_object_unref (appinfo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_environment (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_environment (void)
|
||||
{
|
||||
GAppLaunchContext *ctx;
|
||||
gchar **env;
|
||||
@ -558,8 +466,8 @@ test_environment (Fixture *fixture,
|
||||
|
||||
env = g_app_launch_context_get_environment (ctx);
|
||||
|
||||
g_assert (g_environ_getenv (env, "FOO") == NULL);
|
||||
g_assert (g_environ_getenv (env, "BLA") == NULL);
|
||||
g_assert_null (g_environ_getenv (env, "FOO"));
|
||||
g_assert_null (g_environ_getenv (env, "BLA"));
|
||||
g_assert_cmpstr (g_environ_getenv (env, "PATH"), ==, path);
|
||||
|
||||
g_strfreev (env);
|
||||
@ -581,7 +489,7 @@ test_environment (Fixture *fixture,
|
||||
env = g_app_launch_context_get_environment (ctx);
|
||||
|
||||
g_assert_cmpstr (g_environ_getenv (env, "FOO"), ==, "baz");
|
||||
g_assert (g_environ_getenv (env, "BLA") == NULL);
|
||||
g_assert_null (g_environ_getenv (env, "BLA"));
|
||||
|
||||
g_strfreev (env);
|
||||
|
||||
@ -589,14 +497,13 @@ test_environment (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_startup_wm_class (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_startup_wm_class (void)
|
||||
{
|
||||
GDesktopAppInfo *appinfo;
|
||||
const char *wm_class;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL);
|
||||
appinfo = g_desktop_app_info_new_from_filename (path);
|
||||
wm_class = g_desktop_app_info_get_startup_wm_class (appinfo);
|
||||
|
||||
@ -606,14 +513,13 @@ test_startup_wm_class (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_supported_types (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_supported_types (void)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
const char * const *content_types;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL);
|
||||
appinfo = G_APP_INFO (g_desktop_app_info_new_from_filename (path));
|
||||
content_types = g_app_info_get_supported_types (appinfo);
|
||||
|
||||
@ -624,8 +530,7 @@ test_supported_types (Fixture *fixture,
|
||||
}
|
||||
|
||||
static void
|
||||
test_from_keyfile (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
test_from_keyfile (void)
|
||||
{
|
||||
GDesktopAppInfo *info;
|
||||
GKeyFile *kf;
|
||||
@ -638,19 +543,19 @@ test_from_keyfile (Fixture *fixture,
|
||||
const gchar *name;
|
||||
const gchar *path;
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL);
|
||||
kf = g_key_file_new ();
|
||||
g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
info = g_desktop_app_info_new_from_keyfile (kf);
|
||||
g_key_file_unref (kf);
|
||||
g_assert (info != NULL);
|
||||
g_assert_nonnull (info);
|
||||
|
||||
g_object_get (info, "filename", &file, NULL);
|
||||
g_assert (file == NULL);
|
||||
g_assert_null (file);
|
||||
|
||||
file = g_desktop_app_info_get_filename (info);
|
||||
g_assert (file == NULL);
|
||||
g_assert_null (file);
|
||||
categories = g_desktop_app_info_get_categories (info);
|
||||
g_assert_cmpstr (categories, ==, "GNOME;GTK;");
|
||||
categories_list = g_desktop_app_info_get_string_list (info, "Categories", &categories_count);
|
||||
@ -664,7 +569,7 @@ test_from_keyfile (Fixture *fixture,
|
||||
g_assert_cmpstr (keywords[1], ==, "test keyword");
|
||||
name = g_desktop_app_info_get_generic_name (info);
|
||||
g_assert_cmpstr (name, ==, "generic-appinfo-test");
|
||||
g_assert (!g_desktop_app_info_get_nodisplay (info));
|
||||
g_assert_false (g_desktop_app_info_get_nodisplay (info));
|
||||
|
||||
g_strfreev (categories_list);
|
||||
g_object_unref (info);
|
||||
@ -673,33 +578,25 @@ test_from_keyfile (Fixture *fixture,
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
const gchar *build_dir;
|
||||
|
||||
g_setenv ("XDG_CURRENT_DESKTOP", "GNOME", TRUE);
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id=");
|
||||
|
||||
/* With Meson build we need to change into right directory, so that the
|
||||
* appinfo-test binary can be found. */
|
||||
build_dir = g_getenv ("G_TEST_BUILDDIR");
|
||||
if (build_dir)
|
||||
g_chdir (build_dir);
|
||||
|
||||
g_test_add ("/appinfo/basic", Fixture, NULL, setup, test_basic, teardown);
|
||||
g_test_add ("/appinfo/text", Fixture, NULL, setup, test_text, teardown);
|
||||
g_test_add ("/appinfo/launch", Fixture, NULL, setup, test_launch, teardown);
|
||||
g_test_add ("/appinfo/launch/no-appid", Fixture, NULL, setup, test_launch_no_app_id, teardown);
|
||||
g_test_add ("/appinfo/show-in", Fixture, NULL, setup, test_show_in, teardown);
|
||||
g_test_add ("/appinfo/commandline", Fixture, NULL, setup, test_commandline, teardown);
|
||||
g_test_add ("/appinfo/launch-context", Fixture, NULL, setup, test_launch_context, teardown);
|
||||
g_test_add ("/appinfo/launch-context-signals", Fixture, NULL, setup, test_launch_context_signals, teardown);
|
||||
g_test_add ("/appinfo/tryexec", Fixture, NULL, setup, test_tryexec, teardown);
|
||||
g_test_add ("/appinfo/associations", Fixture, NULL, setup, test_associations, teardown);
|
||||
g_test_add ("/appinfo/environment", Fixture, NULL, setup, test_environment, teardown);
|
||||
g_test_add ("/appinfo/startup-wm-class", Fixture, NULL, setup, test_startup_wm_class, teardown);
|
||||
g_test_add ("/appinfo/supported-types", Fixture, NULL, setup, test_supported_types, teardown);
|
||||
g_test_add ("/appinfo/from-keyfile", Fixture, NULL, setup, test_from_keyfile, teardown);
|
||||
g_test_add_func ("/appinfo/basic", test_basic);
|
||||
g_test_add_func ("/appinfo/text", test_text);
|
||||
g_test_add_func ("/appinfo/launch", test_launch);
|
||||
g_test_add_func ("/appinfo/launch/no-appid", test_launch_no_app_id);
|
||||
g_test_add_func ("/appinfo/show-in", test_show_in);
|
||||
g_test_add_func ("/appinfo/commandline", test_commandline);
|
||||
g_test_add_func ("/appinfo/launch-context", test_launch_context);
|
||||
g_test_add_func ("/appinfo/launch-context-signals", test_launch_context_signals);
|
||||
g_test_add_func ("/appinfo/tryexec", test_tryexec);
|
||||
g_test_add_func ("/appinfo/associations", test_associations);
|
||||
g_test_add_func ("/appinfo/environment", test_environment);
|
||||
g_test_add_func ("/appinfo/startup-wm-class", test_startup_wm_class);
|
||||
g_test_add_func ("/appinfo/supported-types", test_supported_types);
|
||||
g_test_add_func ("/appinfo/from-keyfile", test_from_keyfile);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *data_dir;
|
||||
gchar *applications_dir;
|
||||
} Fixture;
|
||||
|
||||
@ -11,18 +10,10 @@ static void
|
||||
setup (Fixture *fixture,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
fixture->applications_dir = g_build_filename (g_get_user_data_dir (), "applications", NULL);
|
||||
g_assert_cmpint (g_mkdir_with_parents (fixture->applications_dir, 0755), ==, 0);
|
||||
|
||||
fixture->data_dir = g_dir_make_tmp ("gio-test-app-monitor_XXXXXX", &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
fixture->applications_dir = g_build_filename (fixture->data_dir, "applications", NULL);
|
||||
g_assert_cmpint (g_mkdir (fixture->applications_dir, 0755), ==, 0);
|
||||
|
||||
g_setenv ("XDG_DATA_DIRS", fixture->data_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_HOME", fixture->data_dir, TRUE);
|
||||
|
||||
g_test_message ("Using data directory: %s", fixture->data_dir);
|
||||
g_test_message ("Using data directory: %s", g_get_user_data_dir ());
|
||||
}
|
||||
|
||||
static void
|
||||
@ -31,9 +22,6 @@ teardown (Fixture *fixture,
|
||||
{
|
||||
g_assert_cmpint (g_rmdir (fixture->applications_dir), ==, 0);
|
||||
g_clear_pointer (&fixture->applications_dir, g_free);
|
||||
|
||||
g_assert_cmpint (g_rmdir (fixture->data_dir), ==, 0);
|
||||
g_clear_pointer (&fixture->data_dir, g_free);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -129,7 +117,7 @@ test_app_monitor (Fixture *fixture,
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
|
||||
g_test_add ("/monitor/app", Fixture, NULL, setup, test_app_monitor, teardown);
|
||||
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char *basedir;
|
||||
|
||||
static GAppInfo *
|
||||
create_app_info (const char *name)
|
||||
{
|
||||
@ -40,13 +38,13 @@ create_app_info (const char *name)
|
||||
name,
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* this is necessary to ensure that the info is saved */
|
||||
g_app_info_set_as_default_for_type (info, "application/x-blah", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
g_app_info_remove_supports_type (info, "application/x-blah", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
g_app_info_reset_type_associations ("application/x-blah");
|
||||
|
||||
return info;
|
||||
@ -64,34 +62,34 @@ test_delete (void)
|
||||
info = create_app_info ("Blah");
|
||||
|
||||
id = g_app_info_get_id (info);
|
||||
g_assert (id != NULL);
|
||||
g_assert_nonnull (id);
|
||||
|
||||
filename = g_build_filename (basedir, "applications", id, NULL);
|
||||
filename = g_build_filename (g_get_user_data_dir (), "applications", id, NULL);
|
||||
|
||||
res = g_file_test (filename, G_FILE_TEST_EXISTS);
|
||||
g_assert (res);
|
||||
g_assert_true (res);
|
||||
|
||||
res = g_app_info_can_delete (info);
|
||||
g_assert (res);
|
||||
g_assert_true (res);
|
||||
|
||||
res = g_app_info_delete (info);
|
||||
g_assert (res);
|
||||
g_assert_true (res);
|
||||
|
||||
res = g_file_test (filename, G_FILE_TEST_EXISTS);
|
||||
g_assert (!res);
|
||||
g_assert_false (res);
|
||||
|
||||
g_object_unref (info);
|
||||
|
||||
if (g_file_test ("/usr/share/applications/gedit.desktop", G_FILE_TEST_EXISTS))
|
||||
{
|
||||
info = (GAppInfo*)g_desktop_app_info_new_from_filename ("/usr/share/applications/gedit.desktop");
|
||||
g_assert (info);
|
||||
g_assert_nonnull (info);
|
||||
|
||||
res = g_app_info_can_delete (info);
|
||||
g_assert (!res);
|
||||
g_assert_false (res);
|
||||
|
||||
res = g_app_info_delete (info);
|
||||
g_assert (!res);
|
||||
g_assert_false (res);
|
||||
}
|
||||
|
||||
g_free (filename);
|
||||
@ -109,33 +107,33 @@ test_default (void)
|
||||
info3 = create_app_info ("Blah3");
|
||||
|
||||
g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_app_info_set_as_default_for_type (info2, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
info = g_app_info_get_default_for_type ("application/x-test", FALSE);
|
||||
g_assert (info != NULL);
|
||||
g_assert_nonnull (info);
|
||||
g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
|
||||
g_object_unref (info);
|
||||
|
||||
/* now try adding something, but not setting as default */
|
||||
g_app_info_add_supports_type (info3, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* check that info2 is still default */
|
||||
info = g_app_info_get_default_for_type ("application/x-test", FALSE);
|
||||
g_assert (info != NULL);
|
||||
g_assert_nonnull (info);
|
||||
g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
|
||||
g_object_unref (info);
|
||||
|
||||
/* now remove info1 again */
|
||||
g_app_info_remove_supports_type (info1, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* and make sure info2 is still default */
|
||||
info = g_app_info_get_default_for_type ("application/x-test", FALSE);
|
||||
g_assert (info != NULL);
|
||||
g_assert_nonnull (info);
|
||||
g_assert_cmpstr (g_app_info_get_id (info), ==, g_app_info_get_id (info2));
|
||||
g_object_unref (info);
|
||||
|
||||
@ -143,7 +141,7 @@ test_default (void)
|
||||
g_app_info_reset_type_associations ("application/x-test");
|
||||
|
||||
list = g_app_info_get_all_for_type ("application/x-test");
|
||||
g_assert (list == NULL);
|
||||
g_assert_null (list);
|
||||
|
||||
g_app_info_delete (info1);
|
||||
g_app_info_delete (info2);
|
||||
@ -165,17 +163,17 @@ test_fallback (void)
|
||||
info1 = create_app_info ("Test1");
|
||||
info2 = create_app_info ("Test2");
|
||||
|
||||
g_assert (g_content_type_is_a ("text/x-python", "text/plain"));
|
||||
g_assert_true (g_content_type_is_a ("text/x-python", "text/plain"));
|
||||
|
||||
apps = g_app_info_get_all_for_type ("text/x-python");
|
||||
old_length = g_list_length (apps);
|
||||
g_list_free_full (apps, g_object_unref);
|
||||
|
||||
g_app_info_add_supports_type (info1, "text/x-python", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_app_info_add_supports_type (info2, "text/plain", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* check that both apps are registered */
|
||||
apps = g_app_info_get_all_for_type ("text/x-python");
|
||||
@ -183,18 +181,18 @@ test_fallback (void)
|
||||
|
||||
/* check that Test1 is among the recommended apps */
|
||||
recomm = g_app_info_get_recommended_for_type ("text/x-python");
|
||||
g_assert (recomm != NULL);
|
||||
g_assert_nonnull (recomm);
|
||||
for (l = recomm; l; l = l->next)
|
||||
{
|
||||
app = l->data;
|
||||
if (g_app_info_equal (info1, app))
|
||||
break;
|
||||
}
|
||||
g_assert (g_app_info_equal (info1, app));
|
||||
g_assert_true (g_app_info_equal (info1, app));
|
||||
|
||||
/* and that Test2 is among the fallback apps */
|
||||
fallback = g_app_info_get_fallback_for_type ("text/x-python");
|
||||
g_assert (fallback != NULL);
|
||||
g_assert_nonnull (fallback);
|
||||
for (l = fallback; l; l = l->next)
|
||||
{
|
||||
app = l->data;
|
||||
@ -205,11 +203,11 @@ test_fallback (void)
|
||||
|
||||
/* check that recomm + fallback = all applications */
|
||||
list = g_list_concat (g_list_copy (recomm), g_list_copy (fallback));
|
||||
g_assert (g_list_length (list) == g_list_length (apps));
|
||||
g_assert_cmpuint (g_list_length (list), ==, g_list_length (apps));
|
||||
|
||||
for (l = list, m = apps; l != NULL && m != NULL; l = l->next, m = m->next)
|
||||
{
|
||||
g_assert (g_app_info_equal (l->data, m->data));
|
||||
g_assert_true (g_app_info_equal (l->data, m->data));
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
@ -239,32 +237,32 @@ test_last_used (void)
|
||||
info2 = create_app_info ("Test2");
|
||||
|
||||
g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_app_info_add_supports_type (info2, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
applications = g_app_info_get_recommended_for_type ("application/x-test");
|
||||
g_assert (g_list_length (applications) == 2);
|
||||
g_assert_cmpuint (g_list_length (applications), ==, 2);
|
||||
|
||||
/* the first should be the default app now */
|
||||
g_assert (g_app_info_equal (g_list_nth_data (applications, 0), info1));
|
||||
g_assert (g_app_info_equal (g_list_nth_data (applications, 1), info2));
|
||||
g_assert_true (g_app_info_equal (g_list_nth_data (applications, 0), info1));
|
||||
g_assert_true (g_app_info_equal (g_list_nth_data (applications, 1), info2));
|
||||
|
||||
g_list_free_full (applications, g_object_unref);
|
||||
|
||||
g_app_info_set_as_last_used_for_type (info2, "application/x-test", &error);
|
||||
g_assert (error == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
applications = g_app_info_get_recommended_for_type ("application/x-test");
|
||||
g_assert (g_list_length (applications) == 2);
|
||||
g_assert_cmpuint (g_list_length (applications), ==, 2);
|
||||
|
||||
default_app = g_app_info_get_default_for_type ("application/x-test", FALSE);
|
||||
g_assert (g_app_info_equal (default_app, info1));
|
||||
g_assert_true (g_app_info_equal (default_app, info1));
|
||||
|
||||
/* the first should be the other app now */
|
||||
g_assert (g_app_info_equal (g_list_nth_data (applications, 0), info2));
|
||||
g_assert (g_app_info_equal (g_list_nth_data (applications, 1), info1));
|
||||
g_assert_true (g_app_info_equal (g_list_nth_data (applications, 0), info2));
|
||||
g_assert_true (g_app_info_equal (g_list_nth_data (applications, 1), info1));
|
||||
|
||||
g_list_free_full (applications, g_object_unref);
|
||||
|
||||
@ -278,81 +276,6 @@ test_last_used (void)
|
||||
g_object_unref (default_app);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cleanup_dir_recurse (GFile *parent,
|
||||
GFile *root,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GFileEnumerator *enumerator;
|
||||
GError *local_error = NULL;
|
||||
|
||||
g_assert (root != NULL);
|
||||
|
||||
enumerator =
|
||||
g_file_enumerate_children (parent, "*",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
|
||||
&local_error);
|
||||
if (!enumerator)
|
||||
{
|
||||
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&local_error);
|
||||
ret = TRUE;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GFile *child;
|
||||
GFileInfo *finfo;
|
||||
char *relative_path;
|
||||
|
||||
if (!g_file_enumerator_iterate (enumerator, &finfo, &child, NULL, error))
|
||||
goto out;
|
||||
if (!finfo)
|
||||
break;
|
||||
|
||||
relative_path = g_file_get_relative_path (root, child);
|
||||
g_assert (relative_path != NULL);
|
||||
g_free (relative_path);
|
||||
|
||||
if (g_file_info_get_file_type (finfo) == G_FILE_TYPE_DIRECTORY)
|
||||
{
|
||||
if (!cleanup_dir_recurse (child, root, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_file_delete (child, NULL, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
g_clear_object (&enumerator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_subdirs (const char *base_dir)
|
||||
{
|
||||
GFile *base, *file;
|
||||
GError *error = NULL;
|
||||
|
||||
base = g_file_new_for_path (base_dir);
|
||||
file = g_file_get_child (base, "applications");
|
||||
(void) cleanup_dir_recurse (file, file, &error);
|
||||
g_assert_no_error (error);
|
||||
g_object_unref (file);
|
||||
file = g_file_get_child (base, "mime");
|
||||
(void) cleanup_dir_recurse (file, file, &error);
|
||||
g_assert_no_error (error);
|
||||
g_object_unref (file);
|
||||
g_object_unref (base);
|
||||
}
|
||||
|
||||
static void
|
||||
test_extra_getters (void)
|
||||
{
|
||||
@ -365,11 +288,11 @@ test_extra_getters (void)
|
||||
g_setenv ("LANGUAGE", "de_DE.UTF8", TRUE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
appinfo = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL));
|
||||
g_assert (appinfo != NULL);
|
||||
appinfo = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "appinfo-test-static.desktop", NULL));
|
||||
g_assert_nonnull (appinfo);
|
||||
|
||||
g_assert (g_desktop_app_info_has_key (appinfo, "Terminal"));
|
||||
g_assert (!g_desktop_app_info_has_key (appinfo, "Bratwurst"));
|
||||
g_assert_true (g_desktop_app_info_has_key (appinfo, "Terminal"));
|
||||
g_assert_false (g_desktop_app_info_has_key (appinfo, "Bratwurst"));
|
||||
|
||||
s = g_desktop_app_info_get_string (appinfo, "StartupWMClass");
|
||||
g_assert_cmpstr (s, ==, "appinfo-class");
|
||||
@ -387,7 +310,7 @@ test_extra_getters (void)
|
||||
g_free (s);
|
||||
|
||||
b = g_desktop_app_info_get_boolean (appinfo, "Terminal");
|
||||
g_assert (b);
|
||||
g_assert_true (b);
|
||||
|
||||
g_object_unref (appinfo);
|
||||
|
||||
@ -400,7 +323,7 @@ wait_for_file (const gchar *want_this,
|
||||
const gchar *but_not_this,
|
||||
const gchar *or_this)
|
||||
{
|
||||
gint retries = 600;
|
||||
guint retries = 600;
|
||||
|
||||
/* I hate time-based conditions in tests, but this will wait up to one
|
||||
* whole minute for "touch file" to finish running. I think it should
|
||||
@ -411,12 +334,12 @@ wait_for_file (const gchar *want_this,
|
||||
while (access (want_this, F_OK) != 0)
|
||||
{
|
||||
g_usleep (100000); /* 100ms */
|
||||
g_assert (retries);
|
||||
g_assert_cmpuint (retries, >, 0);
|
||||
retries--;
|
||||
}
|
||||
|
||||
g_assert (access (but_not_this, F_OK) != 0);
|
||||
g_assert (access (or_this, F_OK) != 0);
|
||||
g_assert_cmpuint (access (but_not_this, F_OK), !=, 0);
|
||||
g_assert_cmpuint (access (or_this, F_OK), !=, 0);
|
||||
|
||||
unlink (want_this);
|
||||
unlink (but_not_this);
|
||||
@ -431,7 +354,7 @@ test_actions (void)
|
||||
gchar *name;
|
||||
|
||||
appinfo = g_desktop_app_info_new_from_filename (g_test_get_filename (G_TEST_DIST, "appinfo-test-actions.desktop", NULL));
|
||||
g_assert (appinfo != NULL);
|
||||
g_assert_nonnull (appinfo);
|
||||
|
||||
actions = g_desktop_app_info_list_actions (appinfo);
|
||||
g_assert_cmpstr (actions[0], ==, "frob");
|
||||
@ -453,8 +376,8 @@ test_actions (void)
|
||||
g_free (name);
|
||||
|
||||
name = g_desktop_app_info_get_action_name (appinfo, "broken");
|
||||
g_assert (name != NULL);
|
||||
g_assert (g_utf8_validate (name, -1, NULL));
|
||||
g_assert_nonnull (name);
|
||||
g_assert_true (g_utf8_validate (name, -1, NULL));
|
||||
g_free (name);
|
||||
|
||||
unlink ("frob"); unlink ("tweak"); unlink ("twiddle");
|
||||
@ -485,6 +408,7 @@ run_apps (const gchar *command,
|
||||
gchar **argv;
|
||||
gint status;
|
||||
gchar *out;
|
||||
gchar *argv_str = NULL;
|
||||
|
||||
argv = g_new (gchar *, 4);
|
||||
argv[0] = g_test_build_filename (G_TEST_BUILT, "apps", NULL);
|
||||
@ -527,9 +451,15 @@ run_apps (const gchar *command,
|
||||
else
|
||||
envp = g_environ_unsetenv (envp, "XDG_CURRENT_DESKTOP");
|
||||
|
||||
envp = g_environ_setenv (envp, "G_MESSAGES_DEBUG", "", TRUE);
|
||||
|
||||
success = g_spawn_sync (NULL, argv, envp, 0, NULL, NULL, &out, NULL, &status, NULL);
|
||||
g_assert (success);
|
||||
g_assert (status == 0);
|
||||
g_assert_true (success);
|
||||
g_assert_cmpuint (status, ==, 0);
|
||||
|
||||
argv_str = g_strjoinv (" ", argv);
|
||||
g_test_message ("%s: `%s` returned: %s", G_STRFUNC, argv_str, out);
|
||||
g_free (argv_str);
|
||||
|
||||
g_strfreev (envp);
|
||||
g_strfreev (argv);
|
||||
@ -814,9 +744,14 @@ test_launch_as_manager (void)
|
||||
return;
|
||||
}
|
||||
|
||||
path = g_test_get_filename (G_TEST_DIST, "appinfo-test.desktop", NULL);
|
||||
path = g_test_get_filename (G_TEST_BUILT, "appinfo-test.desktop", NULL);
|
||||
appinfo = g_desktop_app_info_new_from_filename (path);
|
||||
g_assert_nonnull (appinfo);
|
||||
|
||||
if (appinfo == NULL)
|
||||
{
|
||||
g_test_skip ("appinfo-test binary not installed");
|
||||
return;
|
||||
}
|
||||
|
||||
retval = g_desktop_app_info_launch_uris_as_manager (appinfo, NULL, NULL, 0,
|
||||
NULL, NULL,
|
||||
@ -841,20 +776,12 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
const gchar *build_dir;
|
||||
gint result;
|
||||
/* While we use %G_TEST_OPTION_ISOLATE_DIRS to create temporary directories
|
||||
* for each of the tests, we want to use the system MIME registry, assuming
|
||||
* that it exists and correctly has shared-mime-info installed. */
|
||||
g_content_type_set_mime_dirs (NULL);
|
||||
|
||||
/* With Meson build we need to change into right directory, so that the
|
||||
* appinfo-test binary can be found. */
|
||||
build_dir = g_getenv ("G_TEST_BUILDDIR");
|
||||
if (build_dir)
|
||||
g_chdir (build_dir);
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
basedir = g_get_current_dir ();
|
||||
g_setenv ("XDG_DATA_HOME", basedir, TRUE);
|
||||
cleanup_subdirs (basedir);
|
||||
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
|
||||
g_test_add_func ("/desktop-app-info/delete", test_delete);
|
||||
g_test_add_func ("/desktop-app-info/default", test_default);
|
||||
@ -867,9 +794,5 @@ main (int argc,
|
||||
g_test_add_func ("/desktop-app-info/show-in", test_show_in);
|
||||
g_test_add_func ("/desktop-app-info/launch-as-manager", test_launch_as_manager);
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
cleanup_subdirs (basedir);
|
||||
|
||||
return result;
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -156,11 +156,9 @@ if host_machine.system() != 'windows'
|
||||
gio_tests += {
|
||||
'appinfo' : {
|
||||
'install' : false,
|
||||
'is_parallel' : false,
|
||||
},
|
||||
'desktop-app-info' : {
|
||||
'install' : false,
|
||||
'is_parallel' : false,
|
||||
},
|
||||
}
|
||||
endif
|
||||
@ -397,15 +395,36 @@ if host_machine.system() != 'windows'
|
||||
}
|
||||
endif
|
||||
|
||||
appinfo_test_desktop_files = [
|
||||
'appinfo-test-gnome.desktop',
|
||||
'appinfo-test-notgnome.desktop',
|
||||
'appinfo-test.desktop',
|
||||
'appinfo-test2.desktop',
|
||||
]
|
||||
|
||||
cdata = configuration_data()
|
||||
if installed_tests_enabled
|
||||
cdata.set('installed_tests_dir', installed_tests_execdir)
|
||||
else
|
||||
cdata.set('installed_tests_dir', meson.current_build_dir())
|
||||
endif
|
||||
|
||||
foreach appinfo_test_desktop_file : appinfo_test_desktop_files
|
||||
configure_file(
|
||||
input: appinfo_test_desktop_file + '.in',
|
||||
output: appinfo_test_desktop_file,
|
||||
install_dir: installed_tests_execdir,
|
||||
install: installed_tests_enabled,
|
||||
configuration: cdata,
|
||||
)
|
||||
endforeach
|
||||
|
||||
if installed_tests_enabled
|
||||
install_data(
|
||||
'contexts.c',
|
||||
'g-icon.c',
|
||||
'appinfo-test-actions.desktop',
|
||||
'appinfo-test-gnome.desktop',
|
||||
'appinfo-test-notgnome.desktop',
|
||||
'appinfo-test.desktop',
|
||||
'appinfo-test2.desktop',
|
||||
'appinfo-test-static.desktop',
|
||||
'file.c',
|
||||
'org.gtk.test.dbusappinfo.desktop',
|
||||
install_dir : installed_tests_execdir,
|
||||
|
@ -95,109 +95,114 @@ const gchar *mimecache_data =
|
||||
"image/bmp=myapp4.desktop;myapp5.desktop;\n"
|
||||
"image/png=myapp3.desktop;\n";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *mimeapps_list_home; /* (owned) */
|
||||
} Fixture;
|
||||
|
||||
/* Set up XDG_DATA_HOME and XDG_DATA_DIRS.
|
||||
* XDG_DATA_DIRS/applications will contain mimeapps.list
|
||||
* XDG_DATA_HOME/applications will contain myapp.desktop
|
||||
* and myapp2.desktop, and no mimeapps.list
|
||||
*/
|
||||
static void
|
||||
setup (void)
|
||||
setup (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
gchar *dir;
|
||||
gchar *xdgconfighome;
|
||||
gchar *xdgdatahome;
|
||||
gchar *xdgdatadir;
|
||||
const gchar *xdgdatahome;
|
||||
const gchar * const *xdgdatadirs;
|
||||
gchar *appdir;
|
||||
gchar *apphome;
|
||||
gchar *mimeapps;
|
||||
gchar *name;
|
||||
gboolean res;
|
||||
gint res;
|
||||
GError *error = NULL;
|
||||
|
||||
dir = g_get_current_dir ();
|
||||
xdgconfighome = g_build_filename (dir, "xdgconfighome", NULL);
|
||||
xdgdatahome = g_build_filename (dir, "xdgdatahome", NULL);
|
||||
xdgdatadir = g_build_filename (dir, "xdgdatadir", NULL);
|
||||
g_test_message ("setting XDG_CONFIG_HOME to '%s'\n", xdgconfighome);
|
||||
g_setenv ("XDG_CONFIG_HOME", xdgconfighome, TRUE);
|
||||
g_test_message ("setting XDG_DATA_HOME to '%s'\n", xdgdatahome);
|
||||
g_setenv ("XDG_DATA_HOME", xdgdatahome, TRUE);
|
||||
g_test_message ("setting XDG_DATA_DIRS to '%s'\n", xdgdatadir);
|
||||
g_setenv ("XDG_DATA_DIRS", xdgdatadir, TRUE);
|
||||
/* These are already set to a temporary directory through our use of
|
||||
* %G_TEST_OPTION_ISOLATE_DIRS below. */
|
||||
xdgdatahome = g_get_user_data_dir ();
|
||||
xdgdatadirs = g_get_system_data_dirs ();
|
||||
|
||||
appdir = g_build_filename (xdgdatadir, "applications", NULL);
|
||||
g_test_message ("creating '%s'\n", appdir);
|
||||
appdir = g_build_filename (xdgdatadirs[0], "applications", NULL);
|
||||
g_test_message ("creating '%s'", appdir);
|
||||
res = g_mkdir_with_parents (appdir, 0700);
|
||||
g_assert (res == 0);
|
||||
g_assert_cmpint (res, ==, 0);
|
||||
|
||||
name = g_build_filename (appdir, "mimeapps.list", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, defaults_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
apphome = g_build_filename (xdgdatahome, "applications", NULL);
|
||||
g_test_message ("creating '%s'\n", apphome);
|
||||
g_test_message ("creating '%s'", apphome);
|
||||
res = g_mkdir_with_parents (apphome, 0700);
|
||||
g_assert (res == 0);
|
||||
g_assert_cmpint (res, ==, 0);
|
||||
|
||||
name = g_build_filename (apphome, "myapp.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, myapp_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
name = g_build_filename (apphome, "myapp2.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, myapp2_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
name = g_build_filename (apphome, "myapp3.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, myapp3_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
name = g_build_filename (apphome, "myapp4.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, myapp4_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
name = g_build_filename (apphome, "myapp5.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, myapp5_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
name = g_build_filename (apphome, "nosuchapp.desktop", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, nosuchapp_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
mimeapps = g_build_filename (apphome, "mimeapps.list", NULL);
|
||||
g_test_message ("removing '%s'\n", mimeapps);
|
||||
g_test_message ("removing '%s'", mimeapps);
|
||||
g_remove (mimeapps);
|
||||
|
||||
name = g_build_filename (apphome, "mimeinfo.cache", NULL);
|
||||
g_test_message ("creating '%s'\n", name);
|
||||
g_test_message ("creating '%s'", name);
|
||||
g_file_set_contents (name, mimecache_data, -1, &error);
|
||||
g_assert_no_error (error);
|
||||
g_free (name);
|
||||
|
||||
g_free (dir);
|
||||
g_free (xdgconfighome);
|
||||
g_free (xdgdatahome);
|
||||
g_free (xdgdatadir);
|
||||
g_free (apphome);
|
||||
g_free (appdir);
|
||||
g_free (mimeapps);
|
||||
|
||||
/* Pointer to one of the temporary directories. */
|
||||
fixture->mimeapps_list_home = g_build_filename (g_get_user_config_dir (), "mimeapps.list", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mime_api (void)
|
||||
teardown (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
g_free (fixture->mimeapps_list_home);
|
||||
}
|
||||
|
||||
static void
|
||||
test_mime_api (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
GAppInfo *appinfo2;
|
||||
@ -214,8 +219,8 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (def == NULL);
|
||||
g_assert (list == NULL);
|
||||
g_assert_null (def);
|
||||
g_assert_null (list);
|
||||
|
||||
/* 1. add a non-default association */
|
||||
g_app_info_add_supports_type (appinfo, contenttype, &error);
|
||||
@ -223,9 +228,9 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo));
|
||||
g_assert_true (g_app_info_equal (def, appinfo));
|
||||
g_assert_cmpint (g_list_length (list), ==, 1);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -235,10 +240,10 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo));
|
||||
g_assert_true (g_app_info_equal (def, appinfo));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -248,10 +253,10 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo));
|
||||
g_assert_true (g_app_info_equal (def, appinfo));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -261,10 +266,10 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo));
|
||||
g_assert_true (g_app_info_equal (def, appinfo));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo2));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo2));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -273,8 +278,8 @@ test_mime_api (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (def == NULL);
|
||||
g_assert (list == NULL);
|
||||
g_assert_null (def);
|
||||
g_assert_null (list);
|
||||
|
||||
g_object_unref (appinfo);
|
||||
g_object_unref (appinfo2);
|
||||
@ -286,7 +291,8 @@ test_mime_api (void)
|
||||
* mimeapps.list to verify the results.
|
||||
*/
|
||||
static void
|
||||
test_mime_file (void)
|
||||
test_mime_file (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
gchar **assoc;
|
||||
GAppInfo *appinfo;
|
||||
@ -297,13 +303,8 @@ test_mime_file (void)
|
||||
gboolean res;
|
||||
GAppInfo *def;
|
||||
GList *list;
|
||||
gchar *mimeapps;
|
||||
gchar *dir;
|
||||
const gchar *contenttype = "application/pdf";
|
||||
|
||||
dir = g_get_current_dir ();
|
||||
mimeapps = g_build_filename (dir, "xdgconfighome", "mimeapps.list", NULL);
|
||||
|
||||
/* clear things out */
|
||||
g_app_info_reset_type_associations (contenttype);
|
||||
|
||||
@ -312,25 +313,25 @@ test_mime_file (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (def == NULL);
|
||||
g_assert (list == NULL);
|
||||
g_assert_null (def);
|
||||
g_assert_null (list);
|
||||
|
||||
/* 1. add a non-default association */
|
||||
g_app_info_add_supports_type (appinfo, contenttype, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
|
||||
g_key_file_load_from_file (keyfile, fixture->mimeapps_list_home, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (strv_equal (assoc, "myapp.desktop", NULL));
|
||||
g_assert_true (strv_equal (assoc, "myapp.desktop", NULL));
|
||||
g_strfreev (assoc);
|
||||
|
||||
/* we've unset XDG_DATA_DIRS so there should be no default */
|
||||
assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
|
||||
g_assert (error != NULL);
|
||||
g_assert_nonnull (error);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_key_file_free (keyfile);
|
||||
@ -340,16 +341,16 @@ test_mime_file (void)
|
||||
g_assert_no_error (error);
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
|
||||
g_key_file_load_from_file (keyfile, fixture->mimeapps_list_home, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
|
||||
g_assert_true (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
|
||||
g_strfreev (assoc);
|
||||
|
||||
assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
|
||||
g_assert (error != NULL);
|
||||
g_assert_nonnull (error);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_key_file_free (keyfile);
|
||||
@ -359,12 +360,12 @@ test_mime_file (void)
|
||||
g_assert_no_error (error);
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
|
||||
g_key_file_load_from_file (keyfile, fixture->mimeapps_list_home, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
|
||||
g_assert_true (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
|
||||
g_strfreev (assoc);
|
||||
|
||||
str = g_key_file_get_string (keyfile, "Default Applications", contenttype, &error);
|
||||
@ -379,12 +380,12 @@ test_mime_file (void)
|
||||
g_assert_no_error (error);
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
|
||||
g_key_file_load_from_file (keyfile, fixture->mimeapps_list_home, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (strv_equal (assoc, "myapp2.desktop", "myapp.desktop", NULL));
|
||||
g_assert_true (strv_equal (assoc, "myapp2.desktop", "myapp.desktop", NULL));
|
||||
g_strfreev (assoc);
|
||||
|
||||
g_key_file_free (keyfile);
|
||||
@ -393,27 +394,25 @@ test_mime_file (void)
|
||||
g_app_info_reset_type_associations (contenttype);
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
|
||||
g_key_file_load_from_file (keyfile, fixture->mimeapps_list_home, G_KEY_FILE_NONE, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
res = g_key_file_has_key (keyfile, "Added Associations", contenttype, NULL);
|
||||
g_assert (!res);
|
||||
g_assert_false (res);
|
||||
|
||||
res = g_key_file_has_key (keyfile, "Default Applications", contenttype, NULL);
|
||||
g_assert (!res);
|
||||
g_assert_false (res);
|
||||
|
||||
g_key_file_free (keyfile);
|
||||
|
||||
g_object_unref (appinfo);
|
||||
g_object_unref (appinfo2);
|
||||
|
||||
g_free (mimeapps);
|
||||
g_free (dir);
|
||||
}
|
||||
|
||||
/* test interaction between mimeapps.list at different levels */
|
||||
static void
|
||||
test_mime_default (void)
|
||||
test_mime_default (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
GAppInfo *appinfo2;
|
||||
@ -433,9 +432,9 @@ test_mime_default (void)
|
||||
/* myapp3 is set as the default in defaults.list */
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo3));
|
||||
g_assert_true (g_app_info_equal (def, appinfo3));
|
||||
g_assert_cmpint (g_list_length (list), ==, 1);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo3));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo3));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -445,10 +444,10 @@ test_mime_default (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo3)); /* default is unaffected */
|
||||
g_assert_true (g_app_info_equal (def, appinfo3)); /* default is unaffected */
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo3));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo3));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -458,11 +457,11 @@ test_mime_default (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo3));
|
||||
g_assert_true (g_app_info_equal (def, appinfo3));
|
||||
g_assert_cmpint (g_list_length (list), ==, 3);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -472,11 +471,11 @@ test_mime_default (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo));
|
||||
g_assert_true (g_app_info_equal (def, appinfo));
|
||||
g_assert_cmpint (g_list_length (list), ==, 3);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -490,7 +489,8 @@ test_mime_default (void)
|
||||
* change the default
|
||||
*/
|
||||
static void
|
||||
test_mime_default_last_used (void)
|
||||
test_mime_default_last_used (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GAppInfo *appinfo4;
|
||||
GAppInfo *appinfo5;
|
||||
@ -509,10 +509,10 @@ test_mime_default_last_used (void)
|
||||
/* myapp4 and myapp5 can both handle image/bmp */
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo4));
|
||||
g_assert_true (g_app_info_equal (def, appinfo4));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -522,10 +522,10 @@ test_mime_default_last_used (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo4)); /* default is unaffected */
|
||||
g_assert_true (g_app_info_equal (def, appinfo4)); /* default is unaffected */
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -535,10 +535,10 @@ test_mime_default_last_used (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo4));
|
||||
g_assert_true (g_app_info_equal (def, appinfo4));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -548,10 +548,10 @@ test_mime_default_last_used (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo5));
|
||||
g_assert_true (g_app_info_equal (def, appinfo5));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -561,10 +561,10 @@ test_mime_default_last_used (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo5));
|
||||
g_assert_true (g_app_info_equal (def, appinfo5));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -574,10 +574,10 @@ test_mime_default_last_used (void)
|
||||
|
||||
def = g_app_info_get_default_for_type (contenttype, FALSE);
|
||||
list = g_app_info_get_recommended_for_type (contenttype);
|
||||
g_assert (g_app_info_equal (def, appinfo5));
|
||||
g_assert_true (g_app_info_equal (def, appinfo5));
|
||||
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
|
||||
g_assert_true (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
|
||||
g_object_unref (def);
|
||||
g_list_free_full (list, g_object_unref);
|
||||
|
||||
@ -586,13 +586,14 @@ test_mime_default_last_used (void)
|
||||
}
|
||||
|
||||
static void
|
||||
test_scheme_handler (void)
|
||||
test_scheme_handler (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GAppInfo *info, *info5;
|
||||
|
||||
info5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
|
||||
info = g_app_info_get_default_for_uri_scheme ("ftp");
|
||||
g_assert (g_app_info_equal (info, info5));
|
||||
g_assert_true (g_app_info_equal (info, info5));
|
||||
|
||||
g_object_unref (info);
|
||||
g_object_unref (info5);
|
||||
@ -601,23 +602,25 @@ test_scheme_handler (void)
|
||||
/* test that g_app_info_* ignores desktop files with nonexisting executables
|
||||
*/
|
||||
static void
|
||||
test_mime_ignore_nonexisting (void)
|
||||
test_mime_ignore_nonexisting (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GAppInfo *appinfo;
|
||||
|
||||
appinfo = (GAppInfo*)g_desktop_app_info_new ("nosuchapp.desktop");
|
||||
g_assert (appinfo == NULL);
|
||||
g_assert_null (appinfo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_all (void)
|
||||
test_all (Fixture *fixture,
|
||||
gconstpointer test_data)
|
||||
{
|
||||
GList *all, *l;
|
||||
|
||||
all = g_app_info_get_all ();
|
||||
|
||||
for (l = all; l; l = l->next)
|
||||
g_assert (G_IS_APP_INFO (l->data));
|
||||
g_assert_true (G_IS_APP_INFO (l->data));
|
||||
|
||||
g_list_free_full (all, g_object_unref);
|
||||
}
|
||||
@ -625,17 +628,21 @@ test_all (void)
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
|
||||
|
||||
setup ();
|
||||
|
||||
g_test_add_func ("/appinfo/mime/api", test_mime_api);
|
||||
g_test_add_func ("/appinfo/mime/default", test_mime_default);
|
||||
g_test_add_func ("/appinfo/mime/file", test_mime_file);
|
||||
g_test_add_func ("/appinfo/mime/scheme-handler", test_scheme_handler);
|
||||
g_test_add_func ("/appinfo/mime/default-last-used", test_mime_default_last_used);
|
||||
g_test_add_func ("/appinfo/mime/ignore-nonexisting", test_mime_ignore_nonexisting);
|
||||
g_test_add_func ("/appinfo/all", test_all);
|
||||
g_test_add ("/appinfo/mime/api", Fixture, NULL, setup,
|
||||
test_mime_api, teardown);
|
||||
g_test_add ("/appinfo/mime/default", Fixture, NULL, setup,
|
||||
test_mime_default, teardown);
|
||||
g_test_add ("/appinfo/mime/file", Fixture, NULL, setup,
|
||||
test_mime_file, teardown);
|
||||
g_test_add ("/appinfo/mime/scheme-handler", Fixture, NULL, setup,
|
||||
test_scheme_handler, teardown);
|
||||
g_test_add ("/appinfo/mime/default-last-used", Fixture, NULL, setup,
|
||||
test_mime_default_last_used, teardown);
|
||||
g_test_add ("/appinfo/mime/ignore-nonexisting", Fixture, NULL, setup,
|
||||
test_mime_ignore_nonexisting, teardown);
|
||||
g_test_add ("/appinfo/all", Fixture, NULL, setup, test_all, teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ static XdgCallbackList *callback_list = NULL;
|
||||
static XdgIconList *icon_list = NULL;
|
||||
static XdgIconList *generic_icon_list = NULL;
|
||||
|
||||
static char **xdg_dirs = NULL; /* NULL terminated */
|
||||
|
||||
XdgMimeCache **_caches = NULL;
|
||||
static int n_caches = 0;
|
||||
|
||||
@ -139,8 +141,8 @@ xdg_mime_init_from_directory (const char *directory)
|
||||
|
||||
assert (directory != NULL);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime.cache") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime.cache");
|
||||
if (stat (file_name, &st) == 0)
|
||||
{
|
||||
XdgMimeCache *cache = _xdg_mime_cache_new_from_file (file_name);
|
||||
@ -159,8 +161,8 @@ xdg_mime_init_from_directory (const char *directory)
|
||||
}
|
||||
free (file_name);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/globs2") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/globs2");
|
||||
file_name = malloc (strlen (directory) + strlen ("/globs2") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/globs2");
|
||||
if (stat (file_name, &st) == 0)
|
||||
{
|
||||
_xdg_mime_glob_read_from_file (global_hash, file_name, TRUE);
|
||||
@ -169,8 +171,8 @@ xdg_mime_init_from_directory (const char *directory)
|
||||
else
|
||||
{
|
||||
free (file_name);
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/globs");
|
||||
file_name = malloc (strlen (directory) + strlen ("/globs") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/globs");
|
||||
if (stat (file_name, &st) == 0)
|
||||
{
|
||||
_xdg_mime_glob_read_from_file (global_hash, file_name, FALSE);
|
||||
@ -182,8 +184,8 @@ xdg_mime_init_from_directory (const char *directory)
|
||||
}
|
||||
}
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/magic");
|
||||
file_name = malloc (strlen (directory) + strlen ("/magic") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/magic");
|
||||
if (stat (file_name, &st) == 0)
|
||||
{
|
||||
_xdg_mime_magic_read_from_file (global_magic, file_name);
|
||||
@ -194,69 +196,81 @@ xdg_mime_init_from_directory (const char *directory)
|
||||
free (file_name);
|
||||
}
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/aliases") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/aliases");
|
||||
file_name = malloc (strlen (directory) + strlen ("/aliases") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/aliases");
|
||||
_xdg_mime_alias_read_from_file (alias_list, file_name);
|
||||
free (file_name);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/subclasses") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/subclasses");
|
||||
file_name = malloc (strlen (directory) + strlen ("/subclasses") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/subclasses");
|
||||
_xdg_mime_parent_read_from_file (parent_list, file_name);
|
||||
free (file_name);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/icons") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/icons");
|
||||
file_name = malloc (strlen (directory) + strlen ("/icons") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/icons");
|
||||
_xdg_mime_icon_read_from_file (icon_list, file_name);
|
||||
free (file_name);
|
||||
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/generic-icons") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/generic-icons");
|
||||
file_name = malloc (strlen (directory) + strlen ("/generic-icons") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/generic-icons");
|
||||
_xdg_mime_icon_read_from_file (generic_icon_list, file_name);
|
||||
free (file_name);
|
||||
|
||||
return FALSE; /* Keep processing */
|
||||
}
|
||||
|
||||
/* Runs a command on all the directories in the search path */
|
||||
/* Set @xdg_dirs from the environment. It must not have been set already. */
|
||||
static void
|
||||
xdg_run_command_on_dirs (XdgDirectoryFunc func,
|
||||
void *user_data)
|
||||
xdg_init_dirs (void)
|
||||
{
|
||||
const char *xdg_data_home;
|
||||
const char *xdg_data_dirs;
|
||||
const char *xdg_data_home, *home, *xdg_data_dirs;
|
||||
const char *ptr;
|
||||
size_t n_dirs = 0;
|
||||
size_t i, current_dir;
|
||||
|
||||
assert (xdg_dirs == NULL);
|
||||
|
||||
xdg_data_home = getenv ("XDG_DATA_HOME");
|
||||
if (xdg_data_home)
|
||||
{
|
||||
if ((func) (xdg_data_home, user_data))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *home;
|
||||
|
||||
home = getenv ("HOME");
|
||||
if (home != NULL)
|
||||
{
|
||||
char *guessed_xdg_home;
|
||||
int stop_processing;
|
||||
|
||||
guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/") + 1);
|
||||
strcpy (guessed_xdg_home, home);
|
||||
strcat (guessed_xdg_home, "/.local/share/");
|
||||
stop_processing = (func) (guessed_xdg_home, user_data);
|
||||
free (guessed_xdg_home);
|
||||
|
||||
if (stop_processing)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
xdg_data_dirs = getenv ("XDG_DATA_DIRS");
|
||||
|
||||
if (xdg_data_dirs == NULL)
|
||||
xdg_data_dirs = "/usr/local/share/:/usr/share/";
|
||||
|
||||
/* Work out how many dirs we’re dealing with. */
|
||||
if (xdg_data_home != NULL || home != NULL)
|
||||
n_dirs++;
|
||||
n_dirs++; /* initial entry in @xdg_data_dirs */
|
||||
for (i = 0; xdg_data_dirs[i] != '\0'; i++)
|
||||
if (xdg_data_dirs[i] == ':')
|
||||
n_dirs++;
|
||||
|
||||
xdg_dirs = calloc (n_dirs + 1 /* NULL terminator */, sizeof (char *));
|
||||
current_dir = 0;
|
||||
|
||||
/* $XDG_DATA_HOME */
|
||||
if (xdg_data_home != NULL)
|
||||
{
|
||||
char *mime_subdir;
|
||||
|
||||
mime_subdir = malloc (strlen (xdg_data_home) + strlen ("/mime/") + 1);
|
||||
strcpy (mime_subdir, xdg_data_home);
|
||||
strcat (mime_subdir, "/mime/");
|
||||
|
||||
xdg_dirs[current_dir++] = mime_subdir;
|
||||
}
|
||||
else if (home != NULL)
|
||||
{
|
||||
char *guessed_xdg_home;
|
||||
|
||||
guessed_xdg_home = malloc (strlen (home) + strlen ("/.local/share/mime/") + 1);
|
||||
strcpy (guessed_xdg_home, home);
|
||||
strcat (guessed_xdg_home, "/.local/share/mime/");
|
||||
|
||||
xdg_dirs[current_dir++] = guessed_xdg_home;
|
||||
}
|
||||
|
||||
/* $XDG_DATA_DIRS */
|
||||
ptr = xdg_data_dirs;
|
||||
|
||||
while (*ptr != '\000')
|
||||
@ -264,7 +278,6 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
|
||||
const char *end_ptr;
|
||||
char *dir;
|
||||
int len;
|
||||
int stop_processing;
|
||||
|
||||
end_ptr = ptr;
|
||||
while (*end_ptr != ':' && *end_ptr != '\000')
|
||||
@ -280,17 +293,68 @@ xdg_run_command_on_dirs (XdgDirectoryFunc func,
|
||||
len = end_ptr - ptr;
|
||||
else
|
||||
len = end_ptr - ptr + 1;
|
||||
dir = malloc (len + 1);
|
||||
dir = malloc (len + strlen ("/mime/") + 1);
|
||||
strncpy (dir, ptr, len);
|
||||
dir[len] = '\0';
|
||||
stop_processing = (func) (dir, user_data);
|
||||
free (dir);
|
||||
strcat (dir, "/mime/");
|
||||
|
||||
if (stop_processing)
|
||||
return;
|
||||
xdg_dirs[current_dir++] = dir;
|
||||
|
||||
ptr = end_ptr;
|
||||
}
|
||||
|
||||
/* NULL terminator */
|
||||
xdg_dirs[current_dir] = NULL;
|
||||
|
||||
need_reread = TRUE;
|
||||
}
|
||||
|
||||
/* Runs a command on all the directories in the search path (@xdg_dirs). */
|
||||
static void
|
||||
xdg_run_command_on_dirs (XdgDirectoryFunc func,
|
||||
void *user_data)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (xdg_dirs == NULL)
|
||||
xdg_init_dirs ();
|
||||
|
||||
for (i = 0; xdg_dirs[i] != NULL; i++)
|
||||
{
|
||||
if ((func) (xdg_dirs[i], user_data))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allows the calling code to override the directories used by xdgmime, without
|
||||
* having to change environment variables in a running process (which is not
|
||||
* thread safe). This is intended to be used by tests. The changes will be
|
||||
* picked up by xdg_mime_init() next time public API is called.
|
||||
*
|
||||
* This will set @xdg_dirs. Directories in @dirs must be complete, including
|
||||
* the conventional `/mime` subdirectory. This is to allow tests to override
|
||||
* them without the need to create a subdirectory. */
|
||||
void
|
||||
xdg_mime_set_dirs (const char * const *dirs)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; xdg_dirs != NULL && xdg_dirs[i] != NULL; i++)
|
||||
free (xdg_dirs[i]);
|
||||
if (xdg_dirs != NULL)
|
||||
free (xdg_dirs[i]);
|
||||
xdg_dirs = NULL;
|
||||
|
||||
if (dirs != NULL)
|
||||
{
|
||||
for (i = 0; dirs[i] != NULL; i++);
|
||||
xdg_dirs = calloc (i + 1 /* NULL terminator */, sizeof (char*));
|
||||
for (i = 0; dirs[i] != NULL; i++)
|
||||
xdg_dirs[i] = strdup (dirs[i]);
|
||||
xdg_dirs[i] = NULL;
|
||||
}
|
||||
|
||||
need_reread = TRUE;
|
||||
}
|
||||
|
||||
/* Checks file_path to make sure it has the same mtime as last time it was
|
||||
@ -344,8 +408,8 @@ xdg_check_dir (const char *directory,
|
||||
assert (directory != NULL);
|
||||
|
||||
/* Check the mime.cache file */
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/mime.cache") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/mime.cache");
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime.cache") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime.cache");
|
||||
invalid = xdg_check_file (file_name, &exists);
|
||||
free (file_name);
|
||||
if (invalid)
|
||||
@ -359,8 +423,8 @@ xdg_check_dir (const char *directory,
|
||||
}
|
||||
|
||||
/* Check the globs file */
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/globs") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/globs");
|
||||
file_name = malloc (strlen (directory) + strlen ("/globs") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/globs");
|
||||
invalid = xdg_check_file (file_name, NULL);
|
||||
free (file_name);
|
||||
if (invalid)
|
||||
@ -370,8 +434,8 @@ xdg_check_dir (const char *directory,
|
||||
}
|
||||
|
||||
/* Check the magic file */
|
||||
file_name = malloc (strlen (directory) + strlen ("/mime/magic") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/mime/magic");
|
||||
file_name = malloc (strlen (directory) + strlen ("/magic") + 1);
|
||||
strcpy (file_name, directory); strcat (file_name, "/magic");
|
||||
invalid = xdg_check_file (file_name, NULL);
|
||||
free (file_name);
|
||||
if (invalid)
|
||||
|
@ -127,6 +127,8 @@ int xdg_mime_register_reload_callback (XdgMimeCallback callback,
|
||||
void xdg_mime_remove_callback (int callback_id);
|
||||
#endif
|
||||
|
||||
void xdg_mime_set_dirs (const char * const *dirs);
|
||||
|
||||
/* Private versions of functions that don't call xdg_mime_init () */
|
||||
int _xdg_mime_mime_type_equal (const char *mime_a,
|
||||
const char *mime_b);
|
||||
|
116
glib.supp
116
glib.supp
@ -229,13 +229,21 @@
|
||||
}
|
||||
|
||||
{
|
||||
g-get-language-names
|
||||
g-get-language-names-malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_get_language_names
|
||||
}
|
||||
|
||||
{
|
||||
g-get-language-names-calloc
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_get_language_names
|
||||
}
|
||||
|
||||
{
|
||||
g-static-mutex
|
||||
Memcheck:Leak
|
||||
@ -543,3 +551,109 @@
|
||||
...
|
||||
fun:g_object_new_valist
|
||||
}
|
||||
|
||||
# g_set_user_dirs() deliberately leaks the previous cached g_get_user_*() values.
|
||||
{
|
||||
g_set_user_dirs_str
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:set_str_if_different
|
||||
fun:g_set_user_dirs
|
||||
}
|
||||
|
||||
# g_set_user_dirs() deliberately leaks the previous cached g_get_user_*() values.
|
||||
{
|
||||
g_set_user_dirs_strv
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:set_strv_if_different
|
||||
fun:g_set_user_dirs
|
||||
}
|
||||
|
||||
# g_get_system_data_dirs() caches a one-time allocation
|
||||
{
|
||||
g_get_system_data_dirs
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_build_system_data_dirs
|
||||
fun:g_get_system_data_dirs
|
||||
}
|
||||
|
||||
# g_get_user_data_dir() caches a one-time allocation
|
||||
{
|
||||
g_get_user_data_dir
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
...
|
||||
fun:g_build_user_data_dir
|
||||
fun:g_get_user_data_dir
|
||||
}
|
||||
|
||||
# gdesktopappinfo.c caches a one-time allocation global table of @desktop_file_dirs.
|
||||
{
|
||||
desktop_file_dirs_malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:desktop_file_dirs_lock
|
||||
}
|
||||
|
||||
# gdesktopappinfo.c caches a one-time allocation global table of @desktop_file_dirs.
|
||||
{
|
||||
desktop_file_dirs_realloc
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
...
|
||||
fun:desktop_file_dirs_lock
|
||||
}
|
||||
|
||||
# gdesktopappinfo.c caches a one-time allocation global table of @desktop_file_dirs.
|
||||
{
|
||||
desktop_file_dir_unindexed_setup_search
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:desktop_file_dir_unindexed_setup_search
|
||||
fun:desktop_file_dir_unindexed_setup_search
|
||||
}
|
||||
|
||||
# g_io_extension_point_register() caches a one-time allocation global table of @extension_points.
|
||||
{
|
||||
g_io_extension_point_register
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_io_extension_point_register
|
||||
}
|
||||
|
||||
# g_strerror() caches a one-time allocation global table of @errors.
|
||||
{
|
||||
g_strerror
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_locale_to_utf8
|
||||
fun:g_strerror
|
||||
}
|
||||
|
||||
# g_socket_connection_factory_register_type() caches a one-time allocation global table of @connection_types.
|
||||
{
|
||||
g_socket_connection_factory_register_type
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_socket_connection_factory_register_type
|
||||
}
|
||||
|
||||
# g_dbus_error_quark() never unregisters itself as a GDBusError domain, as it’s always available
|
||||
{
|
||||
g_dbus_error_quark
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_dbus_error_register_error_domain
|
||||
fun:g_dbus_error_quark
|
||||
}
|
@ -191,6 +191,7 @@ libglib_2_0_la_SOURCES = \
|
||||
gunicodeprivate.h \
|
||||
gurifuncs.c \
|
||||
gutils.c \
|
||||
gutilsprivate.h \
|
||||
guuid.c \
|
||||
gvalgrind.h \
|
||||
gvariant.h \
|
||||
|
@ -3181,6 +3181,40 @@ g_strv_contains (const gchar * const *strv,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_strv_equal:
|
||||
* @strv1: a %NULL-terminated array of strings
|
||||
* @strv2: another %NULL-terminated array of strings
|
||||
*
|
||||
* Checks if @strv1 and @strv2 contain exactly the same elements in exactly the
|
||||
* same order. Elements are compared using g_str_equal(). To match independently
|
||||
* of order, sort the arrays first (using g_qsort_with_data() or similar).
|
||||
*
|
||||
* Two empty arrays are considered equal. Neither @strv1 not @strv2 may be
|
||||
* %NULL.
|
||||
*
|
||||
* Returns: %TRUE if @strv1 and @strv2 are equal
|
||||
* Since: 2.60
|
||||
*/
|
||||
gboolean
|
||||
g_strv_equal (const gchar * const *strv1,
|
||||
const gchar * const *strv2)
|
||||
{
|
||||
g_return_val_if_fail (strv1 != NULL, FALSE);
|
||||
g_return_val_if_fail (strv2 != NULL, FALSE);
|
||||
|
||||
if (strv1 == strv2)
|
||||
return TRUE;
|
||||
|
||||
for (; *strv1 != NULL && *strv2 != NULL; strv1++, strv2++)
|
||||
{
|
||||
if (!g_str_equal (*strv1, *strv2))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (*strv1 == NULL && *strv2 == NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
str_has_sign (const gchar *str)
|
||||
{
|
||||
|
@ -307,6 +307,10 @@ GLIB_AVAILABLE_IN_2_44
|
||||
gboolean g_strv_contains (const gchar * const *strv,
|
||||
const gchar *str);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
gboolean g_strv_equal (const gchar * const *strv1,
|
||||
const gchar * const *strv2);
|
||||
|
||||
/* Convenience ASCII string to number API */
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <glib/gstdio.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -44,6 +43,7 @@
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif /* HAVE_SYS_SELECT_H */
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "gmain.h"
|
||||
#include "gpattern.h"
|
||||
@ -53,6 +53,7 @@
|
||||
#include "gslice.h"
|
||||
#include "gspawn.h"
|
||||
#include "glib-private.h"
|
||||
#include "gutilsprivate.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -825,6 +826,9 @@ static const char * const g_test_result_names[] = {
|
||||
static int test_log_fd = -1;
|
||||
static gboolean test_mode_fatal = TRUE;
|
||||
static gboolean g_test_run_once = TRUE;
|
||||
static gboolean test_isolate_dirs = FALSE;
|
||||
static gchar *test_isolate_dirs_tmpdir = NULL;
|
||||
static const gchar *test_tmpdir = NULL;
|
||||
static gboolean test_run_list = FALSE;
|
||||
static gchar *test_run_seedstr = NULL;
|
||||
G_LOCK_DEFINE_STATIC (test_run_rand);
|
||||
@ -1261,15 +1265,139 @@ parse_args (gint *argc_p,
|
||||
*argc_p = e;
|
||||
}
|
||||
|
||||
/* A fairly naive `rm -rf` implementation to clean up after unit tests. */
|
||||
static void
|
||||
rm_rf (const gchar *path)
|
||||
{
|
||||
GDir *dir = NULL;
|
||||
const gchar *entry;
|
||||
|
||||
dir = g_dir_open (path, 0, NULL);
|
||||
if (dir == NULL)
|
||||
{
|
||||
/* Assume it’s a file. */
|
||||
g_remove (path);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((entry = g_dir_read_name (dir)) != NULL)
|
||||
{
|
||||
gchar *sub_path = g_build_filename (path, entry, NULL);
|
||||
rm_rf (sub_path);
|
||||
g_free (sub_path);
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
|
||||
g_rmdir (path);
|
||||
}
|
||||
|
||||
/* Implement the %G_TEST_OPTION_ISOLATE_DIRS option, iff it’s enabled. Create
|
||||
* a temporary directory for this unit test (disambiguated using @test_run_name)
|
||||
* and use g_set_user_dirs() to point various XDG directories into it, without
|
||||
* having to call setenv() in a process which potentially has threads running.
|
||||
*
|
||||
* Note that this is called for each unit test, and hence won’t have taken
|
||||
* effect before g_test_run() is called in the unit test’s main(). Hence
|
||||
* references to XDG variables in main() will not be using the temporary
|
||||
* directory. */
|
||||
static gboolean
|
||||
test_do_isolate_dirs (GError **error)
|
||||
{
|
||||
gchar *subdir = NULL;
|
||||
gchar *home_dir = NULL, *cache_dir = NULL, *config_dir = NULL;
|
||||
gchar *data_dir = NULL, *runtime_dir = NULL;
|
||||
gchar *config_dirs[3];
|
||||
gchar *data_dirs[3];
|
||||
|
||||
if (!test_isolate_dirs)
|
||||
return TRUE;
|
||||
|
||||
/* The @test_run_name includes the test suites, so may be several directories
|
||||
* deep. Add a `.dirs` directory to contain all the paths we create, and
|
||||
* guarantee none of them clash with test paths below the current one — test
|
||||
* paths may not contain components starting with `.`. */
|
||||
subdir = g_build_filename (test_tmpdir, test_run_name, ".dirs", NULL);
|
||||
|
||||
/* We have to create the runtime directory (because it must be bound to
|
||||
* the session lifetime, which we consider to be the lifetime of the unit
|
||||
* test for testing purposes — see
|
||||
* https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html.
|
||||
* We don’t need to create the other directories — the specification
|
||||
* requires that client code create them if they don’t exist. Not creating
|
||||
* them automatically is a good test of clients’ adherence to the spec
|
||||
* and error handling of missing directories. */
|
||||
runtime_dir = g_build_filename (subdir, "runtime", NULL);
|
||||
if (g_mkdir_with_parents (runtime_dir, 0700) != 0)
|
||||
{
|
||||
gint saved_errno = errno;
|
||||
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
|
||||
"Failed to create XDG_RUNTIME_DIR ‘%s’: %s",
|
||||
runtime_dir, g_strerror (saved_errno));
|
||||
g_free (runtime_dir);
|
||||
g_free (subdir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
home_dir = g_build_filename (subdir, "home", NULL);
|
||||
cache_dir = g_build_filename (subdir, "cache", NULL);
|
||||
config_dir = g_build_filename (subdir, "config", NULL);
|
||||
data_dir = g_build_filename (subdir, "data", NULL);
|
||||
|
||||
config_dirs[0] = g_build_filename (subdir, "system-config1", NULL);
|
||||
config_dirs[1] = g_build_filename (subdir, "system-config2", NULL);
|
||||
config_dirs[2] = NULL;
|
||||
|
||||
data_dirs[0] = g_build_filename (subdir, "system-data1", NULL);
|
||||
data_dirs[1] = g_build_filename (subdir, "system-data2", NULL);
|
||||
data_dirs[2] = NULL;
|
||||
|
||||
/* Remember to update the documentation for %G_TEST_OPTION_ISOLATE_DIRS if
|
||||
* this list changes. */
|
||||
g_set_user_dirs ("HOME", home_dir,
|
||||
"XDG_CACHE_HOME", cache_dir,
|
||||
"XDG_CONFIG_DIRS", config_dirs,
|
||||
"XDG_CONFIG_HOME", config_dir,
|
||||
"XDG_DATA_DIRS", data_dirs,
|
||||
"XDG_DATA_HOME", data_dir,
|
||||
"XDG_RUNTIME_DIR", runtime_dir,
|
||||
NULL);
|
||||
|
||||
g_free (runtime_dir);
|
||||
g_free (data_dir);
|
||||
g_free (config_dir);
|
||||
g_free (cache_dir);
|
||||
g_free (home_dir);
|
||||
g_free (data_dirs[1]);
|
||||
g_free (data_dirs[0]);
|
||||
g_free (config_dirs[1]);
|
||||
g_free (config_dirs[0]);
|
||||
g_free (subdir);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Clean up after test_do_isolate_dirs(). */
|
||||
static void
|
||||
test_rm_isolate_dirs (void)
|
||||
{
|
||||
gchar *subdir = NULL;
|
||||
|
||||
if (!test_isolate_dirs)
|
||||
return;
|
||||
|
||||
subdir = g_build_filename (test_tmpdir, test_run_name, NULL);
|
||||
rm_rf (subdir);
|
||||
g_free (subdir);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_test_init:
|
||||
* @argc: Address of the @argc parameter of the main() function.
|
||||
* Changed if any arguments were handled.
|
||||
* @argv: Address of the @argv parameter of main().
|
||||
* Any parameters understood by g_test_init() stripped before return.
|
||||
* @...: %NULL-terminated list of special options. Currently the only
|
||||
* defined option is `"no_g_set_prgname"`, which
|
||||
* will cause g_test_init() to not call g_set_prgname().
|
||||
* @...: %NULL-terminated list of special options, documented below.
|
||||
*
|
||||
* Initialize the GLib testing framework, e.g. by seeding the
|
||||
* test random number generator, the name for g_get_prgname()
|
||||
@ -1303,6 +1431,14 @@ parse_args (gint *argc_p,
|
||||
*
|
||||
* - `--debug-log`: Debug test logging output.
|
||||
*
|
||||
* Options which can be passed to @... are:
|
||||
*
|
||||
* - `"no_g_set_prgname"`: Causes g_test_init() to not call g_set_prgname().
|
||||
* - %G_TEST_OPTION_ISOLATE_DIRS: Creates a unique temporary directory for each
|
||||
* unit test and uses g_set_user_dirs() to set XDG directories to point into
|
||||
* that temporary directory for the duration of the unit test. See the
|
||||
* documentation for %G_TEST_OPTION_ISOLATE_DIRS.
|
||||
*
|
||||
* Since 2.58, if tests are compiled with `G_DISABLE_ASSERT` defined,
|
||||
* g_test_init() will print an error and exit. This is to prevent no-op tests
|
||||
* from being executed, as g_assert() is commonly (erroneously) used in unit
|
||||
@ -1335,6 +1471,8 @@ void
|
||||
{
|
||||
if (g_strcmp0 (option, "no_g_set_prgname") == 0)
|
||||
no_g_set_prgname = TRUE;
|
||||
else if (g_strcmp0 (option, G_TEST_OPTION_ISOLATE_DIRS) == 0)
|
||||
test_isolate_dirs = TRUE;
|
||||
}
|
||||
va_end (args);
|
||||
|
||||
@ -1348,6 +1486,77 @@ void
|
||||
if (!g_get_prgname() && !no_g_set_prgname)
|
||||
g_set_prgname ((*argv)[0]);
|
||||
|
||||
/* Set up the temporary directory for isolating the test. We have to do this
|
||||
* early, as we want the return values from g_get_user_data_dir() (and
|
||||
* friends) to return subdirectories of the temporary directory throughout
|
||||
* the setup function, test, and teardown function, for each unit test.
|
||||
* See test_do_isolate_dirs().
|
||||
*
|
||||
* The directory is deleted at the bottom of g_test_run().
|
||||
*
|
||||
* Rather than setting the XDG_* environment variables we use a new
|
||||
* G_TEST_TMPDIR variable which gives the top-level temporary directory. This
|
||||
* allows test subprocesses to reuse the same temporary directory when
|
||||
* g_test_init() is called in them. */
|
||||
if (test_isolate_dirs)
|
||||
{
|
||||
if (g_getenv ("G_TEST_TMPDIR") == NULL)
|
||||
{
|
||||
gchar *test_prgname = NULL;
|
||||
gchar *tmpl = NULL;
|
||||
GError *local_error = NULL;
|
||||
|
||||
test_prgname = g_path_get_basename (g_get_prgname ());
|
||||
if (*test_prgname == '\0')
|
||||
test_prgname = g_strdup ("unknown");
|
||||
tmpl = g_strdup_printf ("test_%s_XXXXXX", test_prgname);
|
||||
g_free (test_prgname);
|
||||
|
||||
test_isolate_dirs_tmpdir = g_dir_make_tmp (tmpl, &local_error);
|
||||
if (local_error != NULL)
|
||||
{
|
||||
g_printerr ("%s: Failed to create temporary directory: %s\n",
|
||||
(*argv)[0], local_error->message);
|
||||
g_error_free (local_error);
|
||||
exit (1);
|
||||
}
|
||||
g_free (tmpl);
|
||||
|
||||
/* Propagate the temporary directory to subprocesses. */
|
||||
g_setenv ("G_TEST_TMPDIR", test_isolate_dirs_tmpdir, TRUE);
|
||||
|
||||
/* And clear the traditional environment variables so subprocesses
|
||||
* spawned by the code under test can’t trash anything. If a test
|
||||
* spawns a process, the test is responsible for propagating
|
||||
* appropriate environment variables.
|
||||
*
|
||||
* We assume that any in-process code will use g_get_user_data_dir()
|
||||
* and friends, rather than getenv() directly.
|
||||
*
|
||||
* We set them to ‘/dev/null’ as that should fairly obviously not
|
||||
* accidentally work, and should be fairly greppable. */
|
||||
{
|
||||
const gchar *overridden_environment_variables[] =
|
||||
{
|
||||
"HOME",
|
||||
"XDG_CACHE_HOME",
|
||||
"XDG_CONFIG_DIRS",
|
||||
"XDG_CONFIG_HOME",
|
||||
"XDG_DATA_DIRS",
|
||||
"XDG_DATA_HOME",
|
||||
"XDG_RUNTIME_DIR",
|
||||
};
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (overridden_environment_variables); i++)
|
||||
g_setenv (overridden_environment_variables[i], "/dev/null", TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache this for the remainder of this process’ lifetime. */
|
||||
test_tmpdir = g_getenv ("G_TEST_TMPDIR");
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if (test_tap_log)
|
||||
{
|
||||
@ -1798,6 +2007,14 @@ g_test_run (void)
|
||||
if (g_test_run_suite (g_test_get_root()) != 0)
|
||||
return 1;
|
||||
|
||||
/* Clean up the temporary directory. */
|
||||
if (test_isolate_dirs_tmpdir != NULL)
|
||||
{
|
||||
rm_rf (test_isolate_dirs_tmpdir);
|
||||
g_free (test_isolate_dirs_tmpdir);
|
||||
test_isolate_dirs_tmpdir = NULL;
|
||||
}
|
||||
|
||||
/* 77 is special to Automake's default driver, but not Automake's TAP driver
|
||||
* or Perl's prove(1) TAP driver. */
|
||||
if (test_tap_log)
|
||||
@ -1914,6 +2131,7 @@ g_test_add_vtable (const char *testpath,
|
||||
g_return_if_fail (testpath != NULL);
|
||||
g_return_if_fail (g_path_is_absolute (testpath));
|
||||
g_return_if_fail (fixture_test_func != NULL);
|
||||
g_return_if_fail (!test_isolate_dirs || strstr (testpath, "/.") == NULL);
|
||||
|
||||
suite = g_test_get_root();
|
||||
segments = g_strsplit (testpath, "/", -1);
|
||||
@ -2102,6 +2320,10 @@ g_test_set_nonfatal_assertions (void)
|
||||
* the test will be skipped by default, and only run if explicitly
|
||||
* required via the `-p` command-line option or g_test_trap_subprocess().
|
||||
*
|
||||
* No component of @testpath may start with a dot (`.`) if the
|
||||
* %G_TEST_OPTION_ISOLATE_DIRS option is being used; and it is recommended to
|
||||
* do so even if it isn’t.
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
void
|
||||
@ -2140,6 +2362,10 @@ g_test_add_func (const char *testpath,
|
||||
* the test will be skipped by default, and only run if explicitly
|
||||
* required via the `-p` command-line option or g_test_trap_subprocess().
|
||||
*
|
||||
* No component of @testpath may start with a dot (`.`) if the
|
||||
* %G_TEST_OPTION_ISOLATE_DIRS option is being used; and it is recommended to
|
||||
* do so even if it isn’t.
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
void
|
||||
@ -2351,6 +2577,16 @@ test_case_run (GTestCase *tc)
|
||||
g_test_log_set_fatal_handler (NULL, NULL);
|
||||
if (test_paths_skipped && g_slist_find_custom (test_paths_skipped, test_run_name, (GCompareFunc)g_strcmp0))
|
||||
g_test_skip ("by request (-s option)");
|
||||
else
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
|
||||
if (!test_do_isolate_dirs (&local_error))
|
||||
{
|
||||
g_test_log (G_TEST_LOG_ERROR, local_error->message, NULL, 0, NULL);
|
||||
g_test_fail ();
|
||||
g_error_free (local_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_timer_start (test_run_timer);
|
||||
@ -2373,6 +2609,9 @@ test_case_run (GTestCase *tc)
|
||||
g_free (fixture);
|
||||
g_timer_stop (test_run_timer);
|
||||
}
|
||||
|
||||
test_rm_isolate_dirs ();
|
||||
}
|
||||
success = test_run_success;
|
||||
test_run_success = G_TEST_RUN_FAILURE;
|
||||
largs[0] = success; /* OK */
|
||||
@ -3781,25 +4020,3 @@ g_test_get_filename (GTestFileType file_type,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --- macros docs START --- */
|
||||
/**
|
||||
* g_test_add:
|
||||
* @testpath: The test path for a new test case.
|
||||
* @Fixture: The type of a fixture data structure.
|
||||
* @tdata: Data argument for the test functions.
|
||||
* @fsetup: The function to set up the fixture data.
|
||||
* @ftest: The actual test function.
|
||||
* @fteardown: The function to tear down the fixture data.
|
||||
*
|
||||
* Hook up a new test case at @testpath, similar to g_test_add_func().
|
||||
* A fixture data structure with setup and teardown functions may be provided,
|
||||
* similar to g_test_create_case().
|
||||
*
|
||||
* g_test_add() is implemented as a macro, so that the fsetup(), ftest() and
|
||||
* fteardown() callbacks can expect a @Fixture pointer as their first argument
|
||||
* in a type safe manner. They otherwise have type #GTestFixtureFunc.
|
||||
*
|
||||
* Since: 2.16
|
||||
**/
|
||||
/* --- macros docs END --- */
|
||||
|
@ -165,6 +165,36 @@ void g_test_init (int *argc,
|
||||
char ***argv,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
/**
|
||||
* G_TEST_OPTION_ISOLATE_DIRS:
|
||||
*
|
||||
* Creates a unique temporary directory for each unit test and uses
|
||||
* g_set_user_dirs() to set XDG directories to point into subdirectories of it
|
||||
* for the duration of the unit test. The directory tree is cleaned up after the
|
||||
* test finishes successfully. Note that this doesn’t take effect until
|
||||
* g_test_run() is called, so calls to (for example) g_get_user_home_dir() will
|
||||
* return the system-wide value when made in a test program’s main() function.
|
||||
*
|
||||
* The following functions will return subdirectories of the temporary directory
|
||||
* when this option is used. The specific subdirectory paths in use are not
|
||||
* guaranteed to be stable API — always use a getter function to retrieve them.
|
||||
*
|
||||
* - g_get_home_dir()
|
||||
* - g_get_user_cache_dir()
|
||||
* - g_get_system_config_dirs()
|
||||
* - g_get_user_config_dir()
|
||||
* - g_get_system_data_dirs()
|
||||
* - g_get_user_data_dir()
|
||||
* - g_get_user_runtime_dir()
|
||||
*
|
||||
* The subdirectories may not be created by the test harness; as with normal
|
||||
* calls to functions like g_get_user_cache_dir(), the caller must be prepared
|
||||
* to create the directory if it doesn’t exist.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
#define G_TEST_OPTION_ISOLATE_DIRS "isolate_dirs"
|
||||
|
||||
/* While we discourage its use, g_assert() is often used in unit tests
|
||||
* (especially in legacy code). g_assert_*() should really be used instead.
|
||||
* g_assert() can be disabled at client program compile time, which can render
|
||||
@ -230,7 +260,25 @@ gboolean g_test_failed (void);
|
||||
GLIB_AVAILABLE_IN_2_38
|
||||
void g_test_set_nonfatal_assertions (void);
|
||||
|
||||
/* hook up a test with fixture under test path */
|
||||
/**
|
||||
* g_test_add:
|
||||
* @testpath: The test path for a new test case.
|
||||
* @Fixture: The type of a fixture data structure.
|
||||
* @tdata: Data argument for the test functions.
|
||||
* @fsetup: The function to set up the fixture data.
|
||||
* @ftest: The actual test function.
|
||||
* @fteardown: The function to tear down the fixture data.
|
||||
*
|
||||
* Hook up a new test case at @testpath, similar to g_test_add_func().
|
||||
* A fixture data structure with setup and teardown functions may be provided,
|
||||
* similar to g_test_create_case().
|
||||
*
|
||||
* g_test_add() is implemented as a macro, so that the fsetup(), ftest() and
|
||||
* fteardown() callbacks can expect a @Fixture pointer as their first argument
|
||||
* in a type safe manner. They otherwise have type #GTestFixtureFunc.
|
||||
*
|
||||
* Since: 2.16
|
||||
*/
|
||||
#define g_test_add(testpath, Fixture, tdata, fsetup, ftest, fteardown) \
|
||||
G_STMT_START { \
|
||||
void (*add_vtable) (const char*, \
|
||||
|
609
glib/gutils.c
609
glib/gutils.c
@ -29,6 +29,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gutils.h"
|
||||
#include "gutilsprivate.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -555,12 +556,13 @@ typedef struct
|
||||
gchar *home_dir;
|
||||
} UserDatabaseEntry;
|
||||
|
||||
/* These must all be read/written with @g_utils_global held. */
|
||||
static gchar *g_user_data_dir = NULL;
|
||||
static gchar **g_system_data_dirs = NULL;
|
||||
static gchar *g_user_cache_dir = NULL;
|
||||
static gchar *g_user_config_dir = NULL;
|
||||
static gchar *g_user_runtime_dir = NULL;
|
||||
static gchar **g_system_config_dirs = NULL;
|
||||
|
||||
static gchar **g_user_special_dirs = NULL;
|
||||
|
||||
/* fifteen minutes of fame for everybody */
|
||||
@ -790,6 +792,79 @@ g_get_real_name (void)
|
||||
return entry->real_name;
|
||||
}
|
||||
|
||||
/* Protected by @g_utils_global_lock. */
|
||||
static gchar *g_home_dir = NULL; /* (owned) (nullable before initialised) */
|
||||
|
||||
static gchar *
|
||||
g_build_home_dir (void)
|
||||
{
|
||||
gchar *home_dir;
|
||||
|
||||
/* We first check HOME and use it if it is set */
|
||||
home_dir = g_strdup (g_getenv ("HOME"));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Only believe HOME if it is an absolute path and exists.
|
||||
*
|
||||
* We only do this check on Windows for a couple of reasons.
|
||||
* Historically, we only did it there because we used to ignore $HOME
|
||||
* on UNIX. There are concerns about enabling it now on UNIX because
|
||||
* of things like autofs. In short, if the user has a bogus value in
|
||||
* $HOME then they get what they pay for...
|
||||
*/
|
||||
if (home_dir != NULL)
|
||||
{
|
||||
if (!(g_path_is_absolute (home_dir) &&
|
||||
g_file_test (home_dir, G_FILE_TEST_IS_DIR)))
|
||||
g_clear_pointer (&home_dir, g_free);
|
||||
}
|
||||
|
||||
/* In case HOME is Unix-style (it happens), convert it to
|
||||
* Windows style.
|
||||
*/
|
||||
if (home_dir != NULL)
|
||||
{
|
||||
gchar *p;
|
||||
while ((p = strchr (home_dir, '/')) != NULL)
|
||||
*p = '\\';
|
||||
}
|
||||
|
||||
if (home_dir == NULL)
|
||||
{
|
||||
/* USERPROFILE is probably the closest equivalent to $HOME? */
|
||||
if (g_getenv ("USERPROFILE") != NULL)
|
||||
home_dir = g_strdup (g_getenv ("USERPROFILE"));
|
||||
}
|
||||
|
||||
if (home_dir == NULL)
|
||||
home_dir = get_special_folder (CSIDL_PROFILE);
|
||||
|
||||
if (home_dir == NULL)
|
||||
home_dir = get_windows_directory_root ();
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
if (home_dir == NULL)
|
||||
{
|
||||
/* If we didn't get it from any of those methods, we will have
|
||||
* to read the user database entry.
|
||||
*/
|
||||
UserDatabaseEntry *entry = g_get_user_database_entry ();
|
||||
home_dir = g_strdup (entry->home_dir);
|
||||
}
|
||||
|
||||
/* If we have been denied access to /etc/passwd (for example, by an
|
||||
* overly-zealous LSM), make up a junk value. The return value at this
|
||||
* point is explicitly documented as ‘undefined’. */
|
||||
if (home_dir == NULL)
|
||||
{
|
||||
g_warning ("Could not find home directory: $HOME is not set, and "
|
||||
"user database could not be read.");
|
||||
home_dir = g_strdup ("/");
|
||||
}
|
||||
|
||||
return g_steal_pointer (&home_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_home_dir:
|
||||
*
|
||||
@ -819,87 +894,15 @@ g_get_real_name (void)
|
||||
const gchar *
|
||||
g_get_home_dir (void)
|
||||
{
|
||||
static gchar *home_dir;
|
||||
const gchar *home_dir;
|
||||
|
||||
if (g_once_init_enter (&home_dir))
|
||||
{
|
||||
gchar *tmp;
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
/* We first check HOME and use it if it is set */
|
||||
tmp = g_strdup (g_getenv ("HOME"));
|
||||
if (g_home_dir == NULL)
|
||||
g_home_dir = g_build_home_dir ();
|
||||
home_dir = g_home_dir;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Only believe HOME if it is an absolute path and exists.
|
||||
*
|
||||
* We only do this check on Windows for a couple of reasons.
|
||||
* Historically, we only did it there because we used to ignore $HOME
|
||||
* on UNIX. There are concerns about enabling it now on UNIX because
|
||||
* of things like autofs. In short, if the user has a bogus value in
|
||||
* $HOME then they get what they pay for...
|
||||
*/
|
||||
if (tmp)
|
||||
{
|
||||
if (!(g_path_is_absolute (tmp) &&
|
||||
g_file_test (tmp, G_FILE_TEST_IS_DIR)))
|
||||
{
|
||||
g_free (tmp);
|
||||
tmp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* In case HOME is Unix-style (it happens), convert it to
|
||||
* Windows style.
|
||||
*/
|
||||
if (tmp)
|
||||
{
|
||||
gchar *p;
|
||||
while ((p = strchr (tmp, '/')) != NULL)
|
||||
*p = '\\';
|
||||
}
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
/* USERPROFILE is probably the closest equivalent to $HOME? */
|
||||
if (g_getenv ("USERPROFILE") != NULL)
|
||||
tmp = g_strdup (g_getenv ("USERPROFILE"));
|
||||
}
|
||||
|
||||
if (!tmp)
|
||||
tmp = get_special_folder (CSIDL_PROFILE);
|
||||
|
||||
if (!tmp)
|
||||
tmp = get_windows_directory_root ();
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
/* If we didn't get it from any of those methods, we will have
|
||||
* to read the user database entry.
|
||||
*/
|
||||
UserDatabaseEntry *entry;
|
||||
|
||||
entry = g_get_user_database_entry ();
|
||||
|
||||
/* Strictly speaking, we should copy this, but we know that
|
||||
* neither will ever be freed, so don't bother...
|
||||
*/
|
||||
tmp = entry->home_dir;
|
||||
}
|
||||
|
||||
/* If we have been denied access to /etc/passwd (for example, by an
|
||||
* overly-zealous LSM), make up a junk value. The return value at this
|
||||
* point is explicitly documented as ‘undefined’. Memory management is as
|
||||
* immediately above: strictly this should be copied, but we know not
|
||||
* copying it is OK. */
|
||||
if (tmp == NULL)
|
||||
{
|
||||
g_warning ("Could not find home directory: $HOME is not set, and "
|
||||
"user database could not be read.");
|
||||
tmp = "/";
|
||||
}
|
||||
|
||||
g_once_init_leave (&home_dir, tmp);
|
||||
}
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return home_dir;
|
||||
}
|
||||
@ -1167,6 +1170,135 @@ g_set_application_name (const gchar *application_name)
|
||||
g_warning ("g_set_application_name() called multiple times");
|
||||
}
|
||||
|
||||
/* Set @global_str to a copy of @new_value if it’s currently unset or has a
|
||||
* different value. If its current value matches @new_value, do nothing. If
|
||||
* replaced, we have to leak the old value as client code could still have
|
||||
* pointers to it. */
|
||||
static void
|
||||
set_str_if_different (gchar **global_str,
|
||||
const gchar *type,
|
||||
const gchar *new_value)
|
||||
{
|
||||
if (*global_str == NULL ||
|
||||
!g_str_equal (new_value, *global_str))
|
||||
{
|
||||
g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value);
|
||||
|
||||
/* We have to leak the old value, as user code could be retaining pointers
|
||||
* to it. */
|
||||
*global_str = g_strdup (new_value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_strv_if_different (gchar ***global_strv,
|
||||
const gchar *type,
|
||||
const gchar * const *new_value)
|
||||
{
|
||||
if (*global_strv == NULL ||
|
||||
!g_strv_equal (new_value, (const gchar * const *) *global_strv))
|
||||
{
|
||||
gchar *new_value_str = g_strjoinv (":", (gchar **) new_value);
|
||||
g_debug ("g_set_user_dirs: Setting %s to %s", type, new_value_str);
|
||||
g_free (new_value_str);
|
||||
|
||||
/* We have to leak the old value, as user code could be retaining pointers
|
||||
* to it. */
|
||||
*global_strv = g_strdupv ((gchar **) new_value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* g_set_user_dirs:
|
||||
* @first_dir_type: Type of the first directory to set
|
||||
* @...: Value to set the first directory to, followed by additional type/value
|
||||
* pairs, followed by %NULL
|
||||
*
|
||||
* Set one or more ‘user’ directories to custom values. This is intended to be
|
||||
* used by test code (particularly with the %G_TEST_OPTION_ISOLATE_DIRS option)
|
||||
* to override the values returned by the following functions, so that test
|
||||
* code can be run without touching an installed system and user data:
|
||||
*
|
||||
* - g_get_home_dir() — use type `HOME`, pass a string
|
||||
* - g_get_user_cache_dir() — use type `XDG_CACHE_HOME`, pass a string
|
||||
* - g_get_system_config_dirs() — use type `XDG_CONFIG_DIRS`, pass a
|
||||
* %NULL-terminated string array
|
||||
* - g_get_user_config_dir() — use type `XDG_CONFIG_HOME`, pass a string
|
||||
* - g_get_system_data_dirs() — use type `XDG_DATA_DIRS`, pass a
|
||||
* %NULL-terminated string array
|
||||
* - g_get_user_data_dir() — use type `XDG_DATA_HOME`, pass a string
|
||||
* - g_get_user_runtime_dir() — use type `XDG_RUNTIME_DIR`, pass a string
|
||||
*
|
||||
* The list must be terminated with a %NULL type. All of the values must be
|
||||
* non-%NULL — passing %NULL as a value won’t reset a directory. If a reference
|
||||
* to a directory from the calling environment needs to be kept, copy it before
|
||||
* the first call to g_set_user_dirs(). g_set_user_dirs() can be called multiple
|
||||
* times.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
/*< private > */
|
||||
void
|
||||
g_set_user_dirs (const gchar *first_dir_type,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
const gchar *dir_type;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
va_start (args, first_dir_type);
|
||||
|
||||
for (dir_type = first_dir_type; dir_type != NULL; dir_type = va_arg (args, const gchar *))
|
||||
{
|
||||
gconstpointer dir_value = va_arg (args, gconstpointer);
|
||||
g_assert (dir_value != NULL);
|
||||
|
||||
if (g_str_equal (dir_type, "HOME"))
|
||||
set_str_if_different (&g_home_dir, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_CACHE_HOME"))
|
||||
set_str_if_different (&g_user_cache_dir, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_CONFIG_DIRS"))
|
||||
set_strv_if_different (&g_system_config_dirs, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_CONFIG_HOME"))
|
||||
set_str_if_different (&g_user_config_dir, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_DATA_DIRS"))
|
||||
set_strv_if_different (&g_system_data_dirs, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_DATA_HOME"))
|
||||
set_str_if_different (&g_user_data_dir, dir_type, dir_value);
|
||||
else if (g_str_equal (dir_type, "XDG_RUNTIME_DIR"))
|
||||
set_str_if_different (&g_user_runtime_dir, dir_type, dir_value);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
g_build_user_data_dir (void)
|
||||
{
|
||||
gchar *data_dir = NULL;
|
||||
const gchar *data_dir_env = g_getenv ("XDG_DATA_HOME");
|
||||
|
||||
if (data_dir_env && data_dir_env[0])
|
||||
data_dir = g_strdup (data_dir_env);
|
||||
#ifdef G_OS_WIN32
|
||||
else
|
||||
data_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
|
||||
#endif
|
||||
if (!data_dir || !data_dir[0])
|
||||
{
|
||||
gchar *home_dir = g_build_home_dir ();
|
||||
data_dir = g_build_filename (home_dir, ".local", "share", NULL);
|
||||
g_free (home_dir);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&data_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_user_data_dir:
|
||||
*
|
||||
@ -1192,47 +1324,23 @@ g_set_application_name (const gchar *application_name)
|
||||
const gchar *
|
||||
g_get_user_data_dir (void)
|
||||
{
|
||||
gchar *data_dir = NULL;
|
||||
const gchar *user_data_dir;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
if (!g_user_data_dir)
|
||||
{
|
||||
const gchar *data_dir_env = g_getenv ("XDG_DATA_HOME");
|
||||
|
||||
if (data_dir_env && data_dir_env[0])
|
||||
data_dir = g_strdup (data_dir_env);
|
||||
#ifdef G_OS_WIN32
|
||||
else
|
||||
data_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
|
||||
#endif
|
||||
if (!data_dir || !data_dir[0])
|
||||
{
|
||||
const gchar *home_dir = g_get_home_dir ();
|
||||
|
||||
if (home_dir)
|
||||
data_dir = g_build_filename (home_dir, ".local", "share", NULL);
|
||||
else
|
||||
data_dir = g_build_filename (g_get_tmp_dir (), g_get_user_name (), ".local", "share", NULL);
|
||||
}
|
||||
|
||||
g_user_data_dir = data_dir;
|
||||
}
|
||||
else
|
||||
data_dir = g_user_data_dir;
|
||||
if (g_user_data_dir == NULL)
|
||||
g_user_data_dir = g_build_user_data_dir ();
|
||||
user_data_dir = g_user_data_dir;
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return data_dir;
|
||||
return user_data_dir;
|
||||
}
|
||||
|
||||
static void
|
||||
g_init_user_config_dir (void)
|
||||
static gchar *
|
||||
g_build_user_config_dir (void)
|
||||
{
|
||||
gchar *config_dir = NULL;
|
||||
|
||||
if (!g_user_config_dir)
|
||||
{
|
||||
const gchar *config_dir_env = g_getenv ("XDG_CONFIG_HOME");
|
||||
|
||||
if (config_dir_env && config_dir_env[0])
|
||||
@ -1243,16 +1351,12 @@ g_init_user_config_dir (void)
|
||||
#endif
|
||||
if (!config_dir || !config_dir[0])
|
||||
{
|
||||
const gchar *home_dir = g_get_home_dir ();
|
||||
|
||||
if (home_dir)
|
||||
gchar *home_dir = g_build_home_dir ();
|
||||
config_dir = g_build_filename (home_dir, ".config", NULL);
|
||||
else
|
||||
config_dir = g_build_filename (g_get_tmp_dir (), g_get_user_name (), ".config", NULL);
|
||||
g_free (home_dir);
|
||||
}
|
||||
|
||||
g_user_config_dir = config_dir;
|
||||
}
|
||||
return g_steal_pointer (&config_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1280,13 +1384,39 @@ g_init_user_config_dir (void)
|
||||
const gchar *
|
||||
g_get_user_config_dir (void)
|
||||
{
|
||||
const gchar *user_config_dir;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
g_init_user_config_dir ();
|
||||
if (g_user_config_dir == NULL)
|
||||
g_user_config_dir = g_build_user_config_dir ();
|
||||
user_config_dir = g_user_config_dir;
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_user_config_dir;
|
||||
return user_config_dir;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
g_build_user_cache_dir (void)
|
||||
{
|
||||
gchar *cache_dir = NULL;
|
||||
const gchar *cache_dir_env = g_getenv ("XDG_CACHE_HOME");
|
||||
|
||||
if (cache_dir_env && cache_dir_env[0])
|
||||
cache_dir = g_strdup (cache_dir_env);
|
||||
#ifdef G_OS_WIN32
|
||||
else
|
||||
cache_dir = get_special_folder (CSIDL_INTERNET_CACHE);
|
||||
#endif
|
||||
if (!cache_dir || !cache_dir[0])
|
||||
{
|
||||
gchar *home_dir = g_build_home_dir ();
|
||||
cache_dir = g_build_filename (home_dir, ".cache", NULL);
|
||||
g_free (home_dir);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&cache_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1313,37 +1443,45 @@ g_get_user_config_dir (void)
|
||||
const gchar *
|
||||
g_get_user_cache_dir (void)
|
||||
{
|
||||
gchar *cache_dir = NULL;
|
||||
const gchar *user_cache_dir;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
if (!g_user_cache_dir)
|
||||
{
|
||||
const gchar *cache_dir_env = g_getenv ("XDG_CACHE_HOME");
|
||||
|
||||
if (cache_dir_env && cache_dir_env[0])
|
||||
cache_dir = g_strdup (cache_dir_env);
|
||||
#ifdef G_OS_WIN32
|
||||
else
|
||||
cache_dir = get_special_folder (CSIDL_INTERNET_CACHE);
|
||||
#endif
|
||||
if (!cache_dir || !cache_dir[0])
|
||||
{
|
||||
const gchar *home_dir = g_get_home_dir ();
|
||||
|
||||
if (home_dir)
|
||||
cache_dir = g_build_filename (home_dir, ".cache", NULL);
|
||||
else
|
||||
cache_dir = g_build_filename (g_get_tmp_dir (), g_get_user_name (), ".cache", NULL);
|
||||
}
|
||||
g_user_cache_dir = cache_dir;
|
||||
}
|
||||
else
|
||||
cache_dir = g_user_cache_dir;
|
||||
if (g_user_cache_dir == NULL)
|
||||
g_user_cache_dir = g_build_user_cache_dir ();
|
||||
user_cache_dir = g_user_cache_dir;
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return cache_dir;
|
||||
return user_cache_dir;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
g_build_user_runtime_dir (void)
|
||||
{
|
||||
gchar *runtime_dir = NULL;
|
||||
const gchar *runtime_dir_env = g_getenv ("XDG_RUNTIME_DIR");
|
||||
|
||||
if (runtime_dir_env && runtime_dir_env[0])
|
||||
runtime_dir = g_strdup (runtime_dir_env);
|
||||
else
|
||||
{
|
||||
runtime_dir = g_build_user_cache_dir ();
|
||||
|
||||
/* The user should be able to rely on the directory existing
|
||||
* when the function returns. Probably it already does, but
|
||||
* let's make sure. Just do mkdir() directly since it will be
|
||||
* no more expensive than a stat() in the case that the
|
||||
* directory already exists and is a lot easier.
|
||||
*
|
||||
* $XDG_CACHE_HOME is probably ~/.cache/ so as long as $HOME
|
||||
* exists this will work. If the user changed $XDG_CACHE_HOME
|
||||
* then they can make sure that it exists...
|
||||
*/
|
||||
(void) g_mkdir (runtime_dir, 0700);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&runtime_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1368,38 +1506,17 @@ g_get_user_cache_dir (void)
|
||||
const gchar *
|
||||
g_get_user_runtime_dir (void)
|
||||
{
|
||||
static const gchar *runtime_dir;
|
||||
const gchar *user_runtime_dir;
|
||||
|
||||
if (g_once_init_enter (&runtime_dir))
|
||||
{
|
||||
const gchar *dir;
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
|
||||
if (g_user_runtime_dir == NULL)
|
||||
g_user_runtime_dir = g_build_user_runtime_dir ();
|
||||
user_runtime_dir = g_user_runtime_dir;
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
/* No need to strdup this one since it is valid forever. */
|
||||
dir = g_get_user_cache_dir ();
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
/* The user should be able to rely on the directory existing
|
||||
* when the function returns. Probably it already does, but
|
||||
* let's make sure. Just do mkdir() directly since it will be
|
||||
* no more expensive than a stat() in the case that the
|
||||
* directory already exists and is a lot easier.
|
||||
*
|
||||
* $XDG_CACHE_HOME is probably ~/.cache/ so as long as $HOME
|
||||
* exists this will work. If the user changed $XDG_CACHE_HOME
|
||||
* then they can make sure that it exists...
|
||||
*/
|
||||
(void) g_mkdir (dir, 0700);
|
||||
}
|
||||
|
||||
g_assert (dir != NULL);
|
||||
|
||||
g_once_init_leave (&runtime_dir, dir);
|
||||
}
|
||||
|
||||
return runtime_dir;
|
||||
return user_runtime_dir;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CARBON
|
||||
@ -1553,15 +1670,17 @@ load_user_special_dirs (void)
|
||||
static void
|
||||
load_user_special_dirs (void)
|
||||
{
|
||||
gchar *config_dir = NULL;
|
||||
gchar *config_file;
|
||||
gchar *data;
|
||||
gchar **lines;
|
||||
gint n_lines, i;
|
||||
|
||||
g_init_user_config_dir ();
|
||||
config_file = g_build_filename (g_user_config_dir,
|
||||
config_dir = g_build_user_config_dir ();
|
||||
config_file = g_build_filename (config_dir,
|
||||
"user-dirs.dirs",
|
||||
NULL);
|
||||
g_free (config_dir);
|
||||
|
||||
if (!g_file_get_contents (config_file, &data, NULL, NULL))
|
||||
{
|
||||
@ -1669,7 +1788,9 @@ load_user_special_dirs (void)
|
||||
|
||||
if (is_relative)
|
||||
{
|
||||
g_user_special_dirs[directory] = g_build_filename (g_get_home_dir (), d, NULL);
|
||||
gchar *home_dir = g_build_home_dir ();
|
||||
g_user_special_dirs[directory] = g_build_filename (home_dir, d, NULL);
|
||||
g_free (home_dir);
|
||||
}
|
||||
else
|
||||
g_user_special_dirs[directory] = g_strdup (d);
|
||||
@ -1689,7 +1810,7 @@ load_user_special_dirs (void)
|
||||
* that the latest on-disk version is used. Call this only
|
||||
* if you just changed the data on disk yourself.
|
||||
*
|
||||
* Due to threadsafety issues this may cause leaking of strings
|
||||
* Due to thread safety issues this may cause leaking of strings
|
||||
* that were previously returned from g_get_user_special_dir()
|
||||
* that can't be freed. We ensure to only leak the data for
|
||||
* the directories that actually changed value though.
|
||||
@ -1762,6 +1883,8 @@ g_reload_user_special_dirs_cache (void)
|
||||
const gchar *
|
||||
g_get_user_special_dir (GUserDirectory directory)
|
||||
{
|
||||
const gchar *user_special_dir;
|
||||
|
||||
g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
|
||||
directory < G_USER_N_DIRECTORIES, NULL);
|
||||
|
||||
@ -1775,12 +1898,17 @@ g_get_user_special_dir (GUserDirectory directory)
|
||||
|
||||
/* Special-case desktop for historical compatibility */
|
||||
if (g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] == NULL)
|
||||
g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = g_build_filename (g_get_home_dir (), "Desktop", NULL);
|
||||
{
|
||||
gchar *home_dir = g_build_home_dir ();
|
||||
g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = g_build_filename (home_dir, "Desktop", NULL);
|
||||
g_free (home_dir);
|
||||
}
|
||||
}
|
||||
user_special_dir = g_user_special_dirs[directory];
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return g_user_special_dirs[directory];
|
||||
return user_special_dir;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
@ -1942,7 +2070,7 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void))
|
||||
gboolean should_call_g_get_system_data_dirs;
|
||||
|
||||
should_call_g_get_system_data_dirs = TRUE;
|
||||
/* These checks are the same as the ones that g_get_system_data_dirs() does.
|
||||
/* These checks are the same as the ones that g_build_system_data_dirs() does.
|
||||
* Please keep them in sync.
|
||||
*/
|
||||
G_LOCK (g_utils_global);
|
||||
@ -1986,6 +2114,30 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void))
|
||||
|
||||
#endif
|
||||
|
||||
static gchar **
|
||||
g_build_system_data_dirs (void)
|
||||
{
|
||||
gchar **data_dir_vector = NULL;
|
||||
gchar *data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
|
||||
|
||||
/* These checks are the same as the ones that g_win32_get_system_data_dirs_for_module()
|
||||
* does. Please keep them in sync.
|
||||
*/
|
||||
#ifndef G_OS_WIN32
|
||||
if (!data_dirs || !data_dirs[0])
|
||||
data_dirs = "/usr/local/share/:/usr/share/";
|
||||
|
||||
data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#else
|
||||
if (!data_dirs || !data_dirs[0])
|
||||
data_dir_vector = g_strdupv ((gchar **) g_win32_get_system_data_dirs_for_module_real (NULL));
|
||||
else
|
||||
data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#endif
|
||||
|
||||
return g_steal_pointer (&data_dir_vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_get_system_data_dirs:
|
||||
*
|
||||
@ -2030,37 +2182,49 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void))
|
||||
const gchar * const *
|
||||
g_get_system_data_dirs (void)
|
||||
{
|
||||
gchar **data_dir_vector;
|
||||
const gchar * const *system_data_dirs;
|
||||
|
||||
/* These checks are the same as the ones that g_win32_get_system_data_dirs_for_module()
|
||||
* does. Please keep them in sync.
|
||||
*/
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
if (!g_system_data_dirs)
|
||||
{
|
||||
gchar *data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (!data_dirs || !data_dirs[0])
|
||||
data_dirs = "/usr/local/share/:/usr/share/";
|
||||
|
||||
data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#else
|
||||
if (!data_dirs || !data_dirs[0])
|
||||
data_dir_vector = g_strdupv ((gchar **) g_win32_get_system_data_dirs_for_module_real (NULL));
|
||||
else
|
||||
data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#endif
|
||||
|
||||
g_system_data_dirs = data_dir_vector;
|
||||
}
|
||||
else
|
||||
data_dir_vector = g_system_data_dirs;
|
||||
if (g_system_data_dirs == NULL)
|
||||
g_system_data_dirs = g_build_system_data_dirs ();
|
||||
system_data_dirs = (const gchar * const *) g_system_data_dirs;
|
||||
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return (const gchar * const *) data_dir_vector;
|
||||
return system_data_dirs;
|
||||
}
|
||||
|
||||
static gchar **
|
||||
g_build_system_config_dirs (void)
|
||||
{
|
||||
gchar **conf_dir_vector = NULL;
|
||||
const gchar *conf_dirs = g_getenv ("XDG_CONFIG_DIRS");
|
||||
#ifdef G_OS_WIN32
|
||||
if (conf_dirs)
|
||||
{
|
||||
conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *special_conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
|
||||
|
||||
if (special_conf_dirs)
|
||||
conf_dir_vector = g_strsplit (special_conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
else
|
||||
/* Return empty list */
|
||||
conf_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
|
||||
g_free (special_conf_dirs);
|
||||
}
|
||||
#else
|
||||
if (!conf_dirs || !conf_dirs[0])
|
||||
conf_dirs = "/etc/xdg";
|
||||
|
||||
conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#endif
|
||||
|
||||
return g_steal_pointer (&conf_dir_vector);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2093,44 +2257,17 @@ g_get_system_data_dirs (void)
|
||||
const gchar * const *
|
||||
g_get_system_config_dirs (void)
|
||||
{
|
||||
gchar **conf_dir_vector;
|
||||
const gchar * const *system_config_dirs;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
if (!g_system_config_dirs)
|
||||
{
|
||||
const gchar *conf_dirs = g_getenv ("XDG_CONFIG_DIRS");
|
||||
#ifdef G_OS_WIN32
|
||||
if (conf_dirs)
|
||||
{
|
||||
conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *special_conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA);
|
||||
if (g_system_config_dirs == NULL)
|
||||
g_system_config_dirs = g_build_system_config_dirs ();
|
||||
system_config_dirs = (const gchar * const *) g_system_config_dirs;
|
||||
|
||||
if (special_conf_dirs)
|
||||
conf_dir_vector = g_strsplit (special_conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
else
|
||||
/* Return empty list */
|
||||
conf_dir_vector = g_strsplit ("", G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
|
||||
g_free (special_conf_dirs);
|
||||
}
|
||||
#else
|
||||
if (!conf_dirs || !conf_dirs[0])
|
||||
conf_dirs = "/etc/xdg";
|
||||
|
||||
conf_dir_vector = g_strsplit (conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
#endif
|
||||
|
||||
g_system_config_dirs = conf_dir_vector;
|
||||
}
|
||||
else
|
||||
conf_dir_vector = g_system_config_dirs;
|
||||
G_UNLOCK (g_utils_global);
|
||||
|
||||
return (const gchar * const *) conf_dir_vector;
|
||||
return system_config_dirs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +78,7 @@ GLIB_AVAILABLE_IN_ALL
|
||||
const gchar * const * g_get_system_data_dirs (void);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* This functions is not part of the public GLib API */
|
||||
/* This function is not part of the public GLib API */
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
const gchar * const * g_win32_get_system_data_dirs_for_module (void (*address_of_function)(void));
|
||||
#endif
|
||||
|
33
glib/gutilsprivate.h
Normal file
33
glib/gutilsprivate.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright © 2018 Endless Mobile, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author: Philip Withnall <withnall@endlessm.com>
|
||||
*/
|
||||
|
||||
#ifndef __G_UTILS_PRIVATE_H__
|
||||
#define __G_UTILS_PRIVATE_H__
|
||||
|
||||
#include "gtypes.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
void g_set_user_dirs (const gchar *first_dir_type,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_UTILS_PRIVATE_H__ */
|
@ -199,6 +199,7 @@ glib_sources = files(
|
||||
'gunidecomp.c',
|
||||
'gurifuncs.c',
|
||||
'gutils.c',
|
||||
'gutilsprivate.h',
|
||||
'guuid.c',
|
||||
'gvariant.c',
|
||||
'gvariant-core.c',
|
||||
|
@ -68,21 +68,6 @@ static CmdlineTest cmdline_tests[] =
|
||||
{"foo '/bar/summer'\\''09 tours.pdf'", 2, {"foo", "/bar/summer'09 tours.pdf", NULL}, -1}
|
||||
};
|
||||
|
||||
static gboolean
|
||||
strv_equal (gchar **a, gchar **b)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (g_strv_length (a) != g_strv_length (b))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; a[i]; i++)
|
||||
if (g_strcmp0 (a[i], b[i]) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
do_cmdline_test (gconstpointer d)
|
||||
{
|
||||
@ -99,7 +84,7 @@ do_cmdline_test (gconstpointer d)
|
||||
{
|
||||
g_assert (res);
|
||||
g_assert_cmpint (argc, ==, test->argc);
|
||||
g_assert (strv_equal (argv, (gchar **)test->argv));
|
||||
g_assert (g_strv_equal ((const gchar * const *) argv, (const gchar * const *) test->argv));
|
||||
g_assert_no_error (err);
|
||||
}
|
||||
else
|
||||
|
@ -1507,6 +1507,34 @@ test_strv_contains (void)
|
||||
g_assert_false (g_strv_contains (strv_empty, ""));
|
||||
}
|
||||
|
||||
/* Test g_strv_equal() works for various inputs. */
|
||||
static void
|
||||
test_strv_equal (void)
|
||||
{
|
||||
const gchar *strv_empty[] = { NULL };
|
||||
const gchar *strv_empty2[] = { NULL };
|
||||
const gchar *strv_simple[] = { "hello", "you", NULL };
|
||||
const gchar *strv_simple2[] = { "hello", "you", NULL };
|
||||
const gchar *strv_simple_reordered[] = { "you", "hello", NULL };
|
||||
const gchar *strv_simple_superset[] = { "hello", "you", "again", NULL };
|
||||
const gchar *strv_another[] = { "not", "a", "coded", "message", NULL };
|
||||
|
||||
g_assert_true (g_strv_equal (strv_empty, strv_empty));
|
||||
g_assert_true (g_strv_equal (strv_empty, strv_empty2));
|
||||
g_assert_true (g_strv_equal (strv_empty2, strv_empty));
|
||||
g_assert_false (g_strv_equal (strv_empty, strv_simple));
|
||||
g_assert_false (g_strv_equal (strv_simple, strv_empty));
|
||||
g_assert_true (g_strv_equal (strv_simple, strv_simple));
|
||||
g_assert_true (g_strv_equal (strv_simple, strv_simple2));
|
||||
g_assert_true (g_strv_equal (strv_simple2, strv_simple));
|
||||
g_assert_false (g_strv_equal (strv_simple, strv_simple_reordered));
|
||||
g_assert_false (g_strv_equal (strv_simple_reordered, strv_simple));
|
||||
g_assert_false (g_strv_equal (strv_simple, strv_simple_superset));
|
||||
g_assert_false (g_strv_equal (strv_simple_superset, strv_simple));
|
||||
g_assert_false (g_strv_equal (strv_simple, strv_another));
|
||||
g_assert_false (g_strv_equal (strv_another, strv_simple));
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SIGNED,
|
||||
@ -1761,6 +1789,7 @@ main (int argc,
|
||||
g_test_add_func ("/strfuncs/strup", test_strup);
|
||||
g_test_add_func ("/strfuncs/transliteration", test_transliteration);
|
||||
g_test_add_func ("/strfuncs/strv-contains", test_strv_contains);
|
||||
g_test_add_func ("/strfuncs/strv-equal", test_strv_equal);
|
||||
g_test_add_func ("/strfuncs/ascii-string-to-num/usual", test_ascii_string_to_number_usual);
|
||||
g_test_add_func ("/strfuncs/ascii-string-to-num/pathological", test_ascii_string_to_number_pathological);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user