glib/glib/tests/utils.c
Emmanuel Fleury 7f7b5ba093 Move unit test on g_basename() function to glib/tests/fileutils.c
g_basename() function is defined in glib/gfileutils.c which is tested
by glib/tests/fileutils.c test set. Until now, g_basename() test was
in glib/test/utils.c. This patch move the unit test to the proper file.
2022-03-17 18:10:09 +01:00

1185 lines
29 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Unit tests for utilities
* Copyright (C) 2010 Red Hat, Inc.
*
* This work is provided "as is"; redistribution and modification
* in whole or in part, in any medium, physical or electronic is
* permitted without restriction.
*
* This work 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.
*
* In no event shall the authors or contributors be liable for any
* direct, indirect, incidental, special, exemplary, or consequential
* damages (including, but not limited to, procurement of substitute
* goods or services; loss of use, data, or profits; or business
* interruption) however caused and on any theory of liability, whether
* in contract, strict liability, or tort (including negligence or
* otherwise) arising in any way out of the use of this software, even
* if advised of the possibility of such damage.
*
* Author: Matthias Clasen
*/
#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#endif
#include "glib.h"
#include "glib-private.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef G_OS_UNIX
#include <sys/utsname.h>
#endif
#ifdef G_OS_WIN32
#include <windows.h>
#endif
static gboolean
strv_check (const gchar * const *strv, ...)
{
va_list args;
gchar *s;
gint i;
va_start (args, strv);
for (i = 0; strv[i]; i++)
{
s = va_arg (args, gchar*);
if (g_strcmp0 (strv[i], s) != 0)
{
va_end (args);
return FALSE;
}
}
va_end (args);
return TRUE;
}
static void
test_language_names (void)
{
const gchar * const *names;
g_setenv ("LANGUAGE", "de:en_US", TRUE);
names = g_get_language_names ();
g_assert (strv_check (names, "de", "en_US", "en", "C", NULL));
g_setenv ("LANGUAGE", "tt_RU.UTF-8@iqtelif", TRUE);
names = g_get_language_names ();
g_assert (strv_check (names,
"tt_RU.UTF-8@iqtelif",
"tt_RU@iqtelif",
"tt.UTF-8@iqtelif",
"tt@iqtelif",
"tt_RU.UTF-8",
"tt_RU",
"tt.UTF-8",
"tt",
"C",
NULL));
}
static void
test_locale_variants (void)
{
char **v;
v = g_get_locale_variants ("fr_BE");
g_assert (strv_check ((const gchar * const *) v, "fr_BE", "fr", NULL));
g_strfreev (v);
v = g_get_locale_variants ("sr_SR@latin");
g_assert (strv_check ((const gchar * const *) v, "sr_SR@latin", "sr@latin", "sr_SR", "sr", NULL));
g_strfreev (v);
}
static void
test_version (void)
{
if (g_test_verbose ())
g_printerr ("(header %d.%d.%d library %d.%d.%d) ",
GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
glib_major_version, glib_minor_version, glib_micro_version);
g_assert (glib_check_version (GLIB_MAJOR_VERSION,
GLIB_MINOR_VERSION,
GLIB_MICRO_VERSION) == NULL);
g_assert (glib_check_version (GLIB_MAJOR_VERSION,
GLIB_MINOR_VERSION,
0) == NULL);
g_assert (glib_check_version (GLIB_MAJOR_VERSION - 1,
0,
0) != NULL);
g_assert (glib_check_version (GLIB_MAJOR_VERSION + 1,
0,
0) != NULL);
g_assert (glib_check_version (GLIB_MAJOR_VERSION,
GLIB_MINOR_VERSION + 1,
0) != NULL);
/* don't use + 1 here, since a +/-1 difference can
* happen due to post-release version bumps in git
*/
g_assert (glib_check_version (GLIB_MAJOR_VERSION,
GLIB_MINOR_VERSION,
GLIB_MICRO_VERSION + 3) != NULL);
}
static const gchar *argv0;
static void
test_appname (void)
{
const gchar *prgname;
const gchar *appname;
prgname = g_get_prgname ();
appname = g_get_application_name ();
g_assert_cmpstr (prgname, ==, argv0);
g_assert_cmpstr (appname, ==, prgname);
g_set_prgname ("prgname");
prgname = g_get_prgname ();
appname = g_get_application_name ();
g_assert_cmpstr (prgname, ==, "prgname");
g_assert_cmpstr (appname, ==, "prgname");
g_set_application_name ("appname");
prgname = g_get_prgname ();
appname = g_get_application_name ();
g_assert_cmpstr (prgname, ==, "prgname");
g_assert_cmpstr (appname, ==, "appname");
}
static gpointer
thread_prgname_check (gpointer data)
{
gint *n_threads_got_prgname = (gint *) data;
const gchar *old_prgname;
old_prgname = g_get_prgname ();
g_assert_cmpstr (old_prgname, ==, "prgname");
g_atomic_int_inc (n_threads_got_prgname);
while (g_strcmp0 (g_get_prgname (), "prgname2") != 0);
return NULL;
}
static void
test_prgname_thread_safety (void)
{
gsize i;
gint n_threads_got_prgname;
GThread *threads[4];
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/847");
g_test_summary ("Test that threads racing to get and set the program name "
"always receive a valid program name.");
g_set_prgname ("prgname");
g_atomic_int_set (&n_threads_got_prgname, 0);
for (i = 0; i < G_N_ELEMENTS (threads); i++)
threads[i] = g_thread_new (NULL, thread_prgname_check, &n_threads_got_prgname);
while (g_atomic_int_get (&n_threads_got_prgname) != G_N_ELEMENTS (threads))
g_usleep (50);
g_set_prgname ("prgname2");
/* Wait for all the workers to exit. */
for (i = 0; i < G_N_ELEMENTS (threads); i++)
g_thread_join (threads[i]);
/* reset prgname */
g_set_prgname ("prgname");
}
static void
test_tmpdir (void)
{
g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=627969");
g_assert_cmpstr (g_get_tmp_dir (), !=, "");
}
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define TEST_BUILTINS 1
#else
#define TEST_BUILTINS 0
#endif
#if TEST_BUILTINS
static gint
builtin_bit_nth_lsf1 (gulong mask, gint nth_bit)
{
if (nth_bit >= 0)
{
if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
mask &= -(1UL << (nth_bit + 1));
else
mask = 0;
}
return __builtin_ffsl (mask) - 1;
}
static gint
builtin_bit_nth_lsf2 (gulong mask, gint nth_bit)
{
if (nth_bit >= 0)
{
if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
mask &= -(1UL << (nth_bit + 1));
else
mask = 0;
}
return mask ? __builtin_ctzl (mask) : -1;
}
static gint
builtin_bit_nth_msf (gulong mask, gint nth_bit)
{
if (nth_bit >= 0 && nth_bit < GLIB_SIZEOF_LONG * 8)
mask &= (1UL << nth_bit) - 1;
return mask ? GLIB_SIZEOF_LONG * 8 - 1 - __builtin_clzl (mask) : -1;
}
static guint
builtin_bit_storage (gulong number)
{
return number ? GLIB_SIZEOF_LONG * 8 - __builtin_clzl (number) : 1;
}
#endif
static gint
naive_bit_nth_lsf (gulong mask, gint nth_bit)
{
if (G_UNLIKELY (nth_bit < -1))
nth_bit = -1;
while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1))
{
nth_bit++;
if (mask & (1UL << nth_bit))
return nth_bit;
}
return -1;
}
static gint
naive_bit_nth_msf (gulong mask, gint nth_bit)
{
if (nth_bit < 0 || G_UNLIKELY (nth_bit > GLIB_SIZEOF_LONG * 8))
nth_bit = GLIB_SIZEOF_LONG * 8;
while (nth_bit > 0)
{
nth_bit--;
if (mask & (1UL << nth_bit))
return nth_bit;
}
return -1;
}
static guint
naive_bit_storage (gulong number)
{
guint n_bits = 0;
do
{
n_bits++;
number >>= 1;
}
while (number);
return n_bits;
}
static void
test_basic_bits (void)
{
gulong i;
gint nth_bit;
/* we loop like this: 0, -1, 1, -2, 2, -3, 3, ... */
for (i = 0; (glong) i < 1500; i = -(i + ((glong) i >= 0)))
{
guint naive_bit_storage_i = naive_bit_storage (i);
/* Test the g_bit_*() implementations against the compiler builtins (if
* available), and against a slow-but-correct naive implementation.
* They should all agree.
*
* The macro and function versions of the g_bit_*() functions are tested,
* hence one call with the function name in brackets (to avoid it being
* expanded as a macro). */
#if TEST_BUILTINS
g_assert_cmpint (naive_bit_storage_i, ==, builtin_bit_storage (i));
#endif
g_assert_cmpint (naive_bit_storage_i, ==, g_bit_storage (i));
g_assert_cmpint (naive_bit_storage_i, ==, (g_bit_storage) (i));
for (nth_bit = -3; nth_bit <= 2 + GLIB_SIZEOF_LONG * 8; nth_bit++)
{
gint naive_bit_nth_lsf_i_nth_bit = naive_bit_nth_lsf (i, nth_bit);
gint naive_bit_nth_msf_i_nth_bit = naive_bit_nth_msf (i, nth_bit);
#if TEST_BUILTINS
g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
builtin_bit_nth_lsf1 (i, nth_bit));
g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
builtin_bit_nth_lsf2 (i, nth_bit));
#endif
g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
g_bit_nth_lsf (i, nth_bit));
g_assert_cmpint (naive_bit_nth_lsf_i_nth_bit, ==,
(g_bit_nth_lsf) (i, nth_bit));
#if TEST_BUILTINS
g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
builtin_bit_nth_msf (i, nth_bit));
#endif
g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
g_bit_nth_msf (i, nth_bit));
g_assert_cmpint (naive_bit_nth_msf_i_nth_bit, ==,
(g_bit_nth_msf) (i, nth_bit));
}
}
}
static void
test_bits (void)
{
gulong mask;
gint max_bit;
gint i, pos;
pos = g_bit_nth_lsf (0, -1);
g_assert_cmpint (pos, ==, -1);
max_bit = sizeof (gulong) * 8;
for (i = 0; i < max_bit; i++)
{
mask = 1UL << i;
pos = g_bit_nth_lsf (mask, -1);
g_assert_cmpint (pos, ==, i);
pos = g_bit_nth_lsf (mask, i - 3);
g_assert_cmpint (pos , ==, i);
pos = g_bit_nth_lsf (mask, i);
g_assert_cmpint (pos , ==, -1);
pos = g_bit_nth_lsf (mask, i + 1);
g_assert_cmpint (pos , ==, -1);
}
pos = g_bit_nth_msf (0, -1);
g_assert_cmpint (pos, ==, -1);
for (i = 0; i < max_bit; i++)
{
mask = 1UL << i;
pos = g_bit_nth_msf (mask, -1);
g_assert_cmpint (pos, ==, i);
pos = g_bit_nth_msf (mask, i + 3);
g_assert_cmpint (pos , ==, i);
pos = g_bit_nth_msf (mask, i);
g_assert_cmpint (pos , ==, -1);
if (i > 0)
{
pos = g_bit_nth_msf (mask, i - 1);
g_assert_cmpint (pos , ==, -1);
}
}
}
static void
test_swap (void)
{
guint16 a16, b16;
guint32 a32, b32;
guint64 a64, b64;
a16 = 0xaabb;
b16 = 0xbbaa;
g_assert_cmpint (GUINT16_SWAP_LE_BE (a16), ==, b16);
a32 = 0xaaaabbbb;
b32 = 0xbbbbaaaa;
g_assert_cmpint (GUINT32_SWAP_LE_BE (a32), ==, b32);
a64 = G_GUINT64_CONSTANT(0xaaaaaaaabbbbbbbb);
b64 = G_GUINT64_CONSTANT(0xbbbbbbbbaaaaaaaa);
g_assert_cmpint (GUINT64_SWAP_LE_BE (a64), ==, b64);
}
static void
test_find_program (void)
{
gchar *res;
#ifdef G_OS_UNIX
gchar *relative_path;
gchar *absolute_path;
gchar *cwd;
gsize i;
res = g_find_program_in_path ("sh");
g_assert (res != NULL);
g_free (res);
res = g_find_program_in_path ("/bin/sh");
g_assert (res != NULL);
g_free (res);
cwd = g_get_current_dir ();
absolute_path = g_find_program_in_path ("sh");
relative_path = g_strdup (absolute_path);
for (i = 0; cwd[i] != '\0'; i++)
{
if (cwd[i] == '/' && cwd[i + 1] != '\0')
{
gchar *relative_path_2 = g_strconcat ("../", relative_path, NULL);
g_free (relative_path);
relative_path = relative_path_2;
}
}
res = g_find_program_in_path (relative_path);
g_assert_nonnull (res);
g_assert_true (g_path_is_absolute (res));
g_free (cwd);
g_free (absolute_path);
g_free (relative_path);
g_free (res);
#else
/* There's not a lot we can search for that would reliably work both
* on real Windows and mingw.
*/
#endif
res = g_find_program_in_path ("this_program_does_not_exit");
g_assert (res == NULL);
res = g_find_program_in_path ("/bin");
g_assert (res == NULL);
res = g_find_program_in_path ("/etc/passwd");
g_assert (res == NULL);
}
static void
test_debug (void)
{
GDebugKey keys[] = {
{ "key1", 1 },
{ "key2", 2 },
{ "key3", 4 },
};
guint res;
res = g_parse_debug_string (NULL, keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 0);
res = g_parse_debug_string ("foobabla;#!%!$%112 223", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 0);
res = g_parse_debug_string ("key1:key2", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 3);
res = g_parse_debug_string ("key1;key2", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 3);
res = g_parse_debug_string ("key1,key2", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 3);
res = g_parse_debug_string ("key1 key2", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 3);
res = g_parse_debug_string ("key1\tkey2", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 3);
res = g_parse_debug_string ("all", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 7);
if (g_test_subprocess ())
{
res = g_parse_debug_string ("help", keys, G_N_ELEMENTS (keys));
g_assert_cmpint (res, ==, 0);
return;
}
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_passed ();
g_test_trap_assert_stderr ("*Supported debug values: key1 key2 key3 all help*");
}
static void
test_codeset (void)
{
gchar *c;
const gchar *c2;
c = g_get_codeset ();
g_get_charset (&c2);
g_assert_cmpstr (c, ==, c2);
g_free (c);
}
static void
test_codeset2 (void)
{
if (g_test_subprocess ())
{
const gchar *c;
g_setenv ("CHARSET", "UTF-8", TRUE);
g_get_charset (&c);
g_assert_cmpstr (c, ==, "UTF-8");
return;
}
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_passed ();
}
static void
test_console_charset (void)
{
const gchar *c1;
const gchar *c2;
#ifdef G_OS_WIN32
/* store current environment and unset $LANG to make sure it does not interfere */
const unsigned int initial_cp = GetConsoleOutputCP ();
gchar *initial_lang = g_strdup (g_getenv ("LANG"));
g_unsetenv ("LANG");
/* set console output codepage to something specific (ISO-8859-1 aka CP28591) and query it */
SetConsoleOutputCP (28591);
g_get_console_charset (&c1);
g_assert_cmpstr (c1, ==, "ISO-8859-1");
/* set $LANG to something specific (should override the console output codepage) and query it */
g_setenv ("LANG", "de_DE.ISO-8859-15@euro", TRUE);
g_get_console_charset (&c2);
g_assert_cmpstr (c2, ==, "ISO-8859-15");
/* reset environment */
if (initial_cp)
SetConsoleOutputCP (initial_cp);
if (initial_lang)
g_setenv ("LANG", initial_lang, TRUE);
g_free (initial_lang);
#else
g_get_charset (&c1);
g_get_console_charset (&c2);
g_assert_cmpstr (c1, ==, c2);
#endif
}
extern const gchar *glib_pgettext (const gchar *msgidctxt, gsize msgidoffset);
static void
test_gettext (void)
{
const gchar *am0, *am1, *am2, *am3;
am0 = glib_pgettext ("GDateTime\004AM", strlen ("GDateTime") + 1);
am1 = g_dpgettext ("glib20", "GDateTime\004AM", strlen ("GDateTime") + 1);
am2 = g_dpgettext ("glib20", "GDateTime|AM", 0);
am3 = g_dpgettext2 ("glib20", "GDateTime", "AM");
g_assert_cmpstr (am0, ==, am1);
g_assert_cmpstr (am1, ==, am2);
g_assert_cmpstr (am2, ==, am3);
}
static void
test_username (void)
{
const gchar *name;
name = g_get_user_name ();
g_assert (name != NULL);
}
static void
test_realname (void)
{
const gchar *name;
name = g_get_real_name ();
g_assert (name != NULL);
}
static void
test_hostname (void)
{
const gchar *name;
name = g_get_host_name ();
g_assert (name != NULL);
g_assert_true (g_utf8_validate (name, -1, NULL));
}
#ifdef G_OS_UNIX
static void
test_xdg_dirs (void)
{
gchar *xdg;
const gchar *dir;
const gchar * const *dirs;
gchar *s;
xdg = g_strdup (g_getenv ("XDG_CONFIG_HOME"));
if (!xdg)
xdg = g_build_filename (g_get_home_dir (), ".config", NULL);
dir = g_get_user_config_dir ();
g_assert_cmpstr (dir, ==, xdg);
g_free (xdg);
xdg = g_strdup (g_getenv ("XDG_DATA_HOME"));
if (!xdg)
xdg = g_build_filename (g_get_home_dir (), ".local", "share", NULL);
dir = g_get_user_data_dir ();
g_assert_cmpstr (dir, ==, xdg);
g_free (xdg);
xdg = g_strdup (g_getenv ("XDG_CACHE_HOME"));
if (!xdg)
xdg = g_build_filename (g_get_home_dir (), ".cache", NULL);
dir = g_get_user_cache_dir ();
g_assert_cmpstr (dir, ==, xdg);
g_free (xdg);
xdg = g_strdup (g_getenv ("XDG_STATE_HOME"));
if (!xdg)
xdg = g_build_filename (g_get_home_dir (), ".local/state", NULL);
dir = g_get_user_state_dir ();
g_assert_cmpstr (dir, ==, xdg);
g_free (xdg);
xdg = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
if (!xdg)
xdg = g_strdup (g_get_user_cache_dir ());
dir = g_get_user_runtime_dir ();
g_assert_cmpstr (dir, ==, xdg);
g_free (xdg);
xdg = (gchar *)g_getenv ("XDG_CONFIG_DIRS");
if (!xdg)
xdg = "/etc/xdg";
dirs = g_get_system_config_dirs ();
s = g_strjoinv (":", (gchar **)dirs);
g_assert_cmpstr (s, ==, xdg);
g_free (s);
}
#endif
static void
test_special_dir (void)
{
const gchar *dir, *dir2;
dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
g_reload_user_special_dirs_cache ();
dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
g_assert_cmpstr (dir, ==, dir2);
}
static void
test_desktop_special_dir (void)
{
const gchar *dir, *dir2;
dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
g_assert (dir != NULL);
g_reload_user_special_dirs_cache ();
dir2 = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
g_assert (dir2 != NULL);
}
static void
test_os_info (void)
{
gchar *name;
gchar *contents = NULL;
#if defined (G_OS_UNIX) && !(defined (G_OS_WIN32) || defined (__APPLE__))
struct utsname info;
#endif
/* Whether this is implemented or not, it must not crash */
name = g_get_os_info (G_OS_INFO_KEY_NAME);
g_test_message ("%s: %s",
G_OS_INFO_KEY_NAME,
name == NULL ? "(null)" : name);
#if defined (G_OS_WIN32) || defined (__APPLE__)
/* These OSs have a special case so NAME should always succeed */
g_assert_nonnull (name);
#elif defined (G_OS_UNIX)
if (g_file_get_contents ("/etc/os-release", &contents, NULL, NULL) ||
g_file_get_contents ("/usr/lib/os-release", &contents, NULL, NULL) ||
uname (&info) == 0)
g_assert_nonnull (name);
else
g_test_skip ("os-release(5) API not implemented on this platform");
#else
g_test_skip ("g_get_os_info() not supported on this platform");
#endif
g_free (name);
g_free (contents);
}
static gboolean
source_test (gpointer data)
{
g_assert_not_reached ();
return G_SOURCE_REMOVE;
}
static void
test_clear_source (void)
{
guint id;
id = g_idle_add (source_test, NULL);
g_assert_cmpuint (id, >, 0);
g_clear_handle_id (&id, g_source_remove);
g_assert_cmpuint (id, ==, 0);
id = g_timeout_add (100, source_test, NULL);
g_assert_cmpuint (id, >, 0);
g_clear_handle_id (&id, g_source_remove);
g_assert_cmpuint (id, ==, 0);
}
static void
test_clear_pointer (void)
{
gpointer a;
a = g_malloc (5);
g_clear_pointer (&a, g_free);
g_assert (a == NULL);
a = g_malloc (5);
(g_clear_pointer) (&a, g_free);
g_assert (a == NULL);
}
/* Test that g_clear_pointer() works with a GDestroyNotify which contains a cast.
* See https://gitlab.gnome.org/GNOME/glib/issues/1425 */
static void
test_clear_pointer_cast (void)
{
GHashTable *hash_table = NULL;
hash_table = g_hash_table_new (g_str_hash, g_str_equal);
g_assert_nonnull (hash_table);
g_clear_pointer (&hash_table, (void (*) (GHashTable *)) g_hash_table_destroy);
g_assert_null (hash_table);
}
/* Test that the macro version of g_clear_pointer() only evaluates its argument
* once, just like the function version would. */
static void
test_clear_pointer_side_effects (void)
{
gchar **my_string_array, **i;
my_string_array = g_new0 (gchar*, 3);
my_string_array[0] = g_strdup ("hello");
my_string_array[1] = g_strdup ("there");
my_string_array[2] = NULL;
i = my_string_array;
g_clear_pointer (i++, g_free);
g_assert_true (i == &my_string_array[1]);
g_assert_null (my_string_array[0]);
g_assert_nonnull (my_string_array[1]);
g_assert_null (my_string_array[2]);
g_free (my_string_array[1]);
g_free (my_string_array[2]);
g_free (my_string_array);
}
static int obj_count;
static void
get_obj (gpointer *obj_out)
{
gpointer obj = g_malloc (5);
obj_count++;
if (obj_out)
*obj_out = g_steal_pointer (&obj);
if (obj)
{
g_free (obj);
obj_count--;
}
}
static void
test_take_pointer (void)
{
gpointer a;
gpointer b;
get_obj (NULL);
get_obj (&a);
g_assert (a);
/* ensure that it works to skip the macro */
b = (g_steal_pointer) (&a);
g_assert (!a);
obj_count--;
g_free (b);
g_assert (!obj_count);
}
static void
test_misc_mem (void)
{
gpointer a;
a = g_try_malloc (0);
g_assert (a == NULL);
a = g_try_malloc0 (0);
g_assert (a == NULL);
a = g_malloc (16);
a = g_try_realloc (a, 20);
a = g_try_realloc (a, 0);
g_assert (a == NULL);
}
static void
aligned_alloc_nz (void)
{
gpointer a;
/* Test an alignment thats zero */
a = g_aligned_alloc (16, sizeof(char), 0);
g_aligned_free (a);
exit (0);
}
static void
aligned_alloc_npot (void)
{
gpointer a;
/* Test an alignment thats not a power of two */
a = g_aligned_alloc (16, sizeof(char), 15);
g_aligned_free (a);
exit (0);
}
static void
aligned_alloc_nmov (void)
{
gpointer a;
/* Test an alignment thats not a multiple of sizeof(void*) */
a = g_aligned_alloc (16, sizeof(char), sizeof(void *) / 2);
g_aligned_free (a);
exit (0);
}
static void
test_aligned_mem (void)
{
gpointer a;
g_test_summary ("Aligned memory allocator");
a = g_aligned_alloc (0, sizeof(int), 8);
g_assert_null (a);
a = g_aligned_alloc0 (0, sizeof(int), 8);
g_assert_null (a);
a = g_aligned_alloc (16, 0, 8);
g_assert_null (a);
#define CHECK_SUBPROCESS_FAIL(name,msg) do { \
if (g_test_undefined ()) \
{ \
g_test_message (msg); \
g_test_trap_subprocess ("/utils/aligned-mem/subprocess/" #name, 0, 0); \
g_test_trap_assert_failed (); \
} \
} while (0)
CHECK_SUBPROCESS_FAIL (aligned_alloc_nz, "Alignment must not be zero");
CHECK_SUBPROCESS_FAIL (aligned_alloc_npot, "Alignment must be a power of two");
CHECK_SUBPROCESS_FAIL (aligned_alloc_nmov, "Alignment must be a multiple of sizeof(void*)");
}
static void
test_aligned_mem_alignment (void)
{
gchar *p;
g_test_summary ("Check that g_aligned_alloc() returns a correctly aligned pointer");
p = g_aligned_alloc (5, sizeof (*p), 256);
g_assert_nonnull (p);
g_assert_cmpuint (((guintptr) p) % 256, ==, 0);
g_aligned_free (p);
}
static void
test_aligned_mem_zeroed (void)
{
gsize n_blocks = 10;
guint *p;
gsize i;
g_test_summary ("Check that g_aligned_alloc0() zeroes out its allocation");
p = g_aligned_alloc0 (n_blocks, sizeof (*p), 16);
g_assert_nonnull (p);
for (i = 0; i < n_blocks; i++)
g_assert_cmpuint (p[i], ==, 0);
g_aligned_free (p);
}
static void
test_nullify (void)
{
gpointer p = &test_nullify;
g_assert (p != NULL);
g_nullify_pointer (&p);
g_assert (p == NULL);
}
static void
atexit_func (void)
{
g_print ("atexit called");
}
static void
test_atexit (void)
{
if (g_test_subprocess ())
{
g_atexit (atexit_func);
return;
}
g_test_trap_subprocess (NULL, 0, 0);
g_test_trap_assert_passed ();
g_test_trap_assert_stdout ("*atexit called*");
}
static void
test_check_setuid (void)
{
gboolean res;
res = GLIB_PRIVATE_CALL(g_check_setuid) ();
g_assert (!res);
}
/* Test the defined integer limits are correct, as some compilers have had
* problems with signed/unsigned conversion in the past. These limits should not
* vary between platforms, compilers or architectures.
*
* Use string comparisons to avoid the same systematic problems with unary minus
* application in C++. See https://gitlab.gnome.org/GNOME/glib/issues/1663. */
static void
test_int_limits (void)
{
gchar *str = NULL;
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1663");
str = g_strdup_printf ("%d %d %u\n"
"%" G_GINT16_FORMAT " %" G_GINT16_FORMAT " %" G_GUINT16_FORMAT "\n"
"%" G_GINT32_FORMAT " %" G_GINT32_FORMAT " %" G_GUINT32_FORMAT "\n"
"%" G_GINT64_FORMAT " %" G_GINT64_FORMAT " %" G_GUINT64_FORMAT "\n",
G_MININT8, G_MAXINT8, G_MAXUINT8,
G_MININT16, G_MAXINT16, G_MAXUINT16,
G_MININT32, G_MAXINT32, G_MAXUINT32,
G_MININT64, G_MAXINT64, G_MAXUINT64);
g_assert_cmpstr (str, ==,
"-128 127 255\n"
"-32768 32767 65535\n"
"-2147483648 2147483647 4294967295\n"
"-9223372036854775808 9223372036854775807 18446744073709551615\n");
g_free (str);
}
static void
test_clear_list (void)
{
GList *list = NULL;
g_clear_list (&list, NULL);
g_assert_null (list);
list = g_list_prepend (list, "test");
g_assert_nonnull (list);
g_clear_list (&list, NULL);
g_assert_null (list);
g_clear_list (&list, g_free);
g_assert_null (list);
list = g_list_prepend (list, g_malloc (16));
g_assert_nonnull (list);
g_clear_list (&list, g_free);
g_assert_null (list);
}
static void
test_clear_slist (void)
{
GSList *slist = NULL;
g_clear_slist (&slist, NULL);
g_assert_null (slist);
slist = g_slist_prepend (slist, "test");
g_assert_nonnull (slist);
g_clear_slist (&slist, NULL);
g_assert_null (slist);
g_clear_slist (&slist, g_free);
g_assert_null (slist);
slist = g_slist_prepend (slist, g_malloc (16));
g_assert_nonnull (slist);
g_clear_slist (&slist, g_free);
g_assert_null (slist);
}
int
main (int argc,
char *argv[])
{
argv0 = argv[0];
/* for tmpdir test, need to do this early before g_get_any_init */
g_setenv ("TMPDIR", "", TRUE);
g_unsetenv ("TMP");
g_unsetenv ("TEMP");
/* g_test_init() only calls g_set_prgname() if g_get_prgname()
* returns %NULL, but g_get_prgname() on Windows never returns NULL.
* So we need to do this by hand to make test_appname() work on
* Windows.
*/
g_set_prgname (argv[0]);
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/utils/language-names", test_language_names);
g_test_add_func ("/utils/locale-variants", test_locale_variants);
g_test_add_func ("/utils/version", test_version);
g_test_add_func ("/utils/appname", test_appname);
g_test_add_func ("/utils/prgname-thread-safety", test_prgname_thread_safety);
g_test_add_func ("/utils/tmpdir", test_tmpdir);
g_test_add_func ("/utils/basic_bits", test_basic_bits);
g_test_add_func ("/utils/bits", test_bits);
g_test_add_func ("/utils/swap", test_swap);
g_test_add_func ("/utils/find-program", test_find_program);
g_test_add_func ("/utils/debug", test_debug);
g_test_add_func ("/utils/codeset", test_codeset);
g_test_add_func ("/utils/codeset2", test_codeset2);
g_test_add_func ("/utils/console-charset", test_console_charset);
g_test_add_func ("/utils/gettext", test_gettext);
g_test_add_func ("/utils/username", test_username);
g_test_add_func ("/utils/realname", test_realname);
g_test_add_func ("/utils/hostname", test_hostname);
#ifdef G_OS_UNIX
g_test_add_func ("/utils/xdgdirs", test_xdg_dirs);
#endif
g_test_add_func ("/utils/specialdir", test_special_dir);
g_test_add_func ("/utils/specialdir/desktop", test_desktop_special_dir);
g_test_add_func ("/utils/os-info", test_os_info);
g_test_add_func ("/utils/clear-pointer", test_clear_pointer);
g_test_add_func ("/utils/clear-pointer-cast", test_clear_pointer_cast);
g_test_add_func ("/utils/clear-pointer/side-effects", test_clear_pointer_side_effects);
g_test_add_func ("/utils/take-pointer", test_take_pointer);
g_test_add_func ("/utils/clear-source", test_clear_source);
g_test_add_func ("/utils/misc-mem", test_misc_mem);
g_test_add_func ("/utils/aligned-mem", test_aligned_mem);
g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_nz", aligned_alloc_nz);
g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_npot", aligned_alloc_npot);
g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_nmov", aligned_alloc_nmov);
g_test_add_func ("/utils/aligned-mem/alignment", test_aligned_mem_alignment);
g_test_add_func ("/utils/aligned-mem/zeroed", test_aligned_mem_zeroed);
g_test_add_func ("/utils/nullify", test_nullify);
g_test_add_func ("/utils/atexit", test_atexit);
g_test_add_func ("/utils/check-setuid", test_check_setuid);
g_test_add_func ("/utils/int-limits", test_int_limits);
g_test_add_func ("/utils/clear-list", test_clear_list);
g_test_add_func ("/utils/clear-slist", test_clear_slist);
return g_test_run ();
}