Merge branch 'tests-isolated-tmpdir' into 'main'

gtestutils: Use $G_TEST_TMPDIR as temporary directory when defined

See merge request GNOME/glib!2886
This commit is contained in:
Marco Trevisan 2022-12-19 21:32:56 +00:00
commit 38e01b03b6
7 changed files with 167 additions and 7 deletions

View File

@ -1690,6 +1690,7 @@ void
(*argv)[0], "G_TEST_TMPDIR"); (*argv)[0], "G_TEST_TMPDIR");
exit (1); exit (1);
} }
_g_unset_cached_tmp_dir ();
/* And clear the traditional environment variables so subprocesses /* And clear the traditional environment variables so subprocesses
* spawned by the code under test cant trash anything. If a test * spawned by the code under test cant trash anything. If a test

View File

@ -598,6 +598,7 @@ static gchar *g_user_state_dir = NULL;
static gchar *g_user_runtime_dir = NULL; static gchar *g_user_runtime_dir = NULL;
static gchar **g_system_config_dirs = NULL; static gchar **g_system_config_dirs = NULL;
static gchar **g_user_special_dirs = NULL; static gchar **g_user_special_dirs = NULL;
static gchar *g_tmp_dir = NULL;
/* fifteen minutes of fame for everybody */ /* fifteen minutes of fame for everybody */
#define G_USER_DIRS_EXPIRE 15 * 60 #define G_USER_DIRS_EXPIRE 15 * 60
@ -941,6 +942,17 @@ g_get_home_dir (void)
return home_dir; return home_dir;
} }
void
_g_unset_cached_tmp_dir (void)
{
G_LOCK (g_utils_global);
/* We have to leak the old value, as user code could be retaining pointers
* to it. */
g_ignore_leak (g_tmp_dir);
g_tmp_dir = NULL;
G_UNLOCK (g_utils_global);
}
/** /**
* g_get_tmp_dir: * g_get_tmp_dir:
* *
@ -964,22 +976,33 @@ g_get_home_dir (void)
const gchar * const gchar *
g_get_tmp_dir (void) g_get_tmp_dir (void)
{ {
static gchar *tmp_dir; G_LOCK (g_utils_global);
if (g_once_init_enter (&tmp_dir)) if (g_tmp_dir == NULL)
{ {
gchar *tmp; gchar *tmp;
#ifdef G_OS_WIN32 tmp = g_strdup (g_getenv ("G_TEST_TMPDIR"));
tmp = g_strdup (g_getenv ("TEMP"));
if (tmp == NULL || *tmp == '\0')
{
g_free (tmp);
tmp = g_strdup (g_getenv (
#ifdef G_OS_WIN32
"TEMP"
#else /* G_OS_WIN32 */
"TMPDIR"
#endif /* G_OS_WIN32 */
));
}
#ifdef G_OS_WIN32
if (tmp == NULL || *tmp == '\0') if (tmp == NULL || *tmp == '\0')
{ {
g_free (tmp); g_free (tmp);
tmp = get_windows_directory_root (); tmp = get_windows_directory_root ();
} }
#else /* G_OS_WIN32 */ #else /* G_OS_WIN32 */
tmp = g_strdup (g_getenv ("TMPDIR"));
#ifdef P_tmpdir #ifdef P_tmpdir
if (tmp == NULL || *tmp == '\0') if (tmp == NULL || *tmp == '\0')
@ -1000,10 +1023,12 @@ g_get_tmp_dir (void)
} }
#endif /* !G_OS_WIN32 */ #endif /* !G_OS_WIN32 */
g_once_init_leave (&tmp_dir, tmp); g_tmp_dir = g_steal_pointer (&tmp);
} }
return tmp_dir; G_UNLOCK (g_utils_global);
return g_tmp_dir;
} }
/** /**

View File

@ -59,6 +59,8 @@ g_nearest_pow (gsize num)
return n + 1; return n + 1;
} }
void _g_unset_cached_tmp_dir (void);
G_END_DECLS G_END_DECLS
#endif /* __G_UTILS_PRIVATE_H__ */ #endif /* __G_UTILS_PRIVATE_H__ */

View File

@ -1205,6 +1205,7 @@ test_dir_make_tmp (void)
name = g_dir_make_tmp ("testXXXXXXtest", &error); name = g_dir_make_tmp ("testXXXXXXtest", &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR)); g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
ret = g_rmdir (name); ret = g_rmdir (name);
g_assert_cmpint (ret, ==, 0); g_assert_cmpint (ret, ==, 0);
g_free (name); g_free (name);
@ -1212,6 +1213,7 @@ test_dir_make_tmp (void)
name = g_dir_make_tmp (NULL, &error); name = g_dir_make_tmp (NULL, &error);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR)); g_assert_true (g_file_test (name, G_FILE_TEST_IS_DIR));
g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
ret = g_rmdir (name); ret = g_rmdir (name);
g_assert_cmpint (ret, ==, 0); g_assert_cmpint (ret, ==, 0);
g_free (name); g_free (name);
@ -1238,6 +1240,7 @@ test_file_open_tmp (void)
g_assert_cmpint (fd, !=, -1); g_assert_cmpint (fd, !=, -1);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_nonnull (name); g_assert_nonnull (name);
g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
unlink (name); unlink (name);
g_free (name); g_free (name);
close (fd); close (fd);
@ -1246,6 +1249,7 @@ test_file_open_tmp (void)
g_assert_cmpint (fd, !=, -1); g_assert_cmpint (fd, !=, -1);
g_assert_no_error (error); g_assert_no_error (error);
g_assert_nonnull (name); g_assert_nonnull (name);
g_assert_true (g_str_has_prefix (name, g_getenv ("G_TEST_TMPDIR")));
g_unlink (name); g_unlink (name);
g_free (name); g_free (name);
close (fd); close (fd);

View File

@ -158,6 +158,7 @@ glib_tests = {
'utils' : { 'utils' : {
'c_standards': c_standards.keys(), 'c_standards': c_standards.keys(),
}, },
'utils-isolated' : {},
'unicode' : {}, 'unicode' : {},
'unicode-encoding' : {}, 'unicode-encoding' : {},
'unicode-normalize': {}, 'unicode-normalize': {},

114
glib/tests/utils-isolated.c Normal file
View File

@ -0,0 +1,114 @@
/* Copyright (C) 2022 Marco Trevisan
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* 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: Marco Trevisan <marco.trevisan@canonical.com>
*/
#include "config.h"
#include <glib/glib.h>
/* Test that all of the well-known directories returned by GLib
* are returned as children of test_tmpdir when running with
* %G_TEST_OPTION_ISOLATE_DIRS. This ensures that tests should
* not interfere with each other in `/tmp` while running.
*/
const char *test_tmpdir;
static void
test_tmp_dir (void)
{
g_assert_cmpstr (g_get_tmp_dir (), ==, test_tmpdir);
}
static void
test_home_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_home_dir (), test_tmpdir));
}
static void
test_user_cache_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_user_cache_dir (), test_tmpdir));
}
static void
test_system_config_dirs (void)
{
const char *const *dir;
for (dir = g_get_system_config_dirs (); *dir != NULL; dir++)
g_assert_true (g_str_has_prefix (*dir, test_tmpdir));
}
static void
test_user_config_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_user_config_dir (), test_tmpdir));
}
static void
test_system_data_dirs (void)
{
const char *const *dir;
for (dir = g_get_system_data_dirs (); *dir != NULL; dir++)
g_assert_true (g_str_has_prefix (*dir, test_tmpdir));
}
static void
test_user_data_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_user_data_dir (), test_tmpdir));
}
static void
test_user_state_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_user_state_dir (), test_tmpdir));
}
static void
test_user_runtime_dir (void)
{
g_assert_true (g_str_has_prefix (g_get_user_runtime_dir (), test_tmpdir));
}
int
main (int argc,
char *argv[])
{
g_setenv ("LC_ALL", "C", TRUE);
g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
test_tmpdir = g_getenv ("G_TEST_TMPDIR");
g_assert_nonnull (test_tmpdir);
g_test_add_func ("/utils-isolated/tmp-dir", test_tmp_dir);
g_test_add_func ("/utils-isolated/home-dir", test_home_dir);
g_test_add_func ("/utils-isolated/user-cache-dir", test_user_cache_dir);
g_test_add_func ("/utils-isolated/system-config-dirs", test_system_config_dirs);
g_test_add_func ("/utils-isolated/user-config-dir", test_user_config_dir);
g_test_add_func ("/utils-isolated/system-data-dirs", test_system_data_dirs);
g_test_add_func ("/utils-isolated/user-data-dir", test_user_data_dir);
g_test_add_func ("/utils-isolated/user-state-dir", test_user_state_dir);
g_test_add_func ("/utils-isolated/user-runtime-dir", test_user_runtime_dir);
return g_test_run ();
}

View File

@ -840,6 +840,19 @@
fun:g_set_user_dirs fun:g_set_user_dirs
} }
# _g_unset_cached_tmp_dir() deliberately leaks the previous cached g_get_tmp_dir() values.
# These will not all be reachable on exit.
{
g_get_tmp_dir
Memcheck:Leak
match-leak-kinds:definite,reachable
fun:malloc
...
fun:g_get_tmp_dir
...
fun:g_test_init
}
# g_get_system_data_dirs() caches a one-time allocation # g_get_system_data_dirs() caches a one-time allocation
{ {
g_get_system_data_dirs g_get_system_data_dirs