glib/glib/tests/strfuncs.c
2010-07-30 19:51:19 -04:00

1275 lines
36 KiB
C

/* Unit tests for gstrfuncs
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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.
*/
#define _XOPEN_SOURCE
#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "glib.h"
#define GLIB_TEST_STRING "el dorado "
#define FOR_ALL_CTYPE(macro) \
macro(isalnum) \
macro(isalpha) \
macro(iscntrl) \
macro(isdigit) \
macro(isgraph) \
macro(islower) \
macro(isprint) \
macro(ispunct) \
macro(isspace) \
macro(isupper) \
macro(isxdigit)
#define DEFINE_CALL_CTYPE(function) \
static int \
call_##function (int c) \
{ \
return function (c); \
}
#define DEFINE_CALL_G_ASCII_CTYPE(function) \
static gboolean \
call_g_ascii_##function (gchar c) \
{ \
return g_ascii_##function (c); \
}
FOR_ALL_CTYPE (DEFINE_CALL_CTYPE)
FOR_ALL_CTYPE (DEFINE_CALL_G_ASCII_CTYPE)
static void
test_is_function (const char *name,
gboolean (* ascii_function) (gchar),
int (* c_library_function) (int),
gboolean (* unicode_function) (gunichar))
{
int c;
for (c = 0; c <= 0x7F; c++)
{
gboolean ascii_result = ascii_function ((gchar)c);
gboolean c_library_result = c_library_function (c) != 0;
gboolean unicode_result = unicode_function ((gunichar) c);
if (ascii_result != c_library_result && c != '\v')
{
g_error ("g_ascii_%s returned %d and %s returned %d for 0x%X",
name, ascii_result, name, c_library_result, c);
}
if (ascii_result != unicode_result)
{
g_error ("g_ascii_%s returned %d and g_unichar_%s returned %d for 0x%X",
name, ascii_result, name, unicode_result, c);
}
}
for (c = 0x80; c <= 0xFF; c++)
{
gboolean ascii_result = ascii_function ((gchar)c);
if (ascii_result)
{
g_error ("g_ascii_%s returned TRUE for 0x%X", name, c);
}
}
}
static void
test_to_function (const char *name,
gchar (* ascii_function) (gchar),
int (* c_library_function) (int),
gunichar (* unicode_function) (gunichar))
{
int c;
for (c = 0; c <= 0x7F; c++)
{
int ascii_result = (guchar) ascii_function ((gchar) c);
int c_library_result = c_library_function (c);
int unicode_result = unicode_function ((gunichar) c);
if (ascii_result != c_library_result)
{
g_error ("g_ascii_%s returned 0x%X and %s returned 0x%X for 0x%X",
name, ascii_result, name, c_library_result, c);
}
if (ascii_result != unicode_result)
{
g_error ("g_ascii_%s returned 0x%X and g_unichar_%s returned 0x%X for 0x%X",
name, ascii_result, name, unicode_result, c);
}
}
for (c = 0x80; c <= 0xFF; c++)
{
int ascii_result = (guchar) ascii_function ((gchar) c);
if (ascii_result != c)
{
g_error ("g_ascii_%s returned 0x%X for 0x%X",
name, ascii_result, c);
}
}
}
static void
test_digit_function (const char *name,
int (* ascii_function) (gchar),
int (* unicode_function) (gunichar))
{
int c;
for (c = 0; c <= 0x7F; c++)
{
int ascii_result = ascii_function ((gchar) c);
int unicode_result = unicode_function ((gunichar) c);
if (ascii_result != unicode_result)
{
g_error ("g_ascii_%s_value returned %d and g_unichar_%s_value returned %d for 0x%X",
name, ascii_result, name, unicode_result, c);
}
}
for (c = 0x80; c <= 0xFF; c++)
{
int ascii_result = ascii_function ((gchar) c);
if (ascii_result != -1)
{
g_error ("g_ascii_%s_value returned %d for 0x%X",
name, ascii_result, c);
}
}
}
static void
test_is_to_digit (void)
{
#define TEST_IS(name) test_is_function (#name, call_g_ascii_##name, call_##name, g_unichar_##name);
FOR_ALL_CTYPE(TEST_IS)
#undef TEST_IS
#define TEST_TO(name) test_to_function (#name, g_ascii_##name, name, g_unichar_##name)
TEST_TO (tolower);
TEST_TO (toupper);
#undef TEST_TO
#define TEST_DIGIT(name) test_digit_function (#name, g_ascii_##name##_value, g_unichar_##name##_value)
TEST_DIGIT (digit);
TEST_DIGIT (xdigit);
#undef TEST_DIGIT
}
static void
test_strdup (void)
{
gchar *str;
str = g_strdup (NULL);
g_assert (str == NULL);
str = g_strdup (GLIB_TEST_STRING);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
g_free (str);
}
static void
test_strndup (void)
{
gchar *str;
str = g_strndup (NULL, 3);
g_assert (str == NULL);
str = g_strndup ("aaaa", 5);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "aaaa");
g_free (str);
str = g_strndup ("aaaa", 2);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "aa");
g_free (str);
}
static void
test_strdup_printf (void)
{
gchar *str;
str = g_strdup_printf ("%05d %-5s", 21, "test");
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "00021 test ");
g_free (str);
}
static void
test_strdupv (void)
{
gchar *vec[] = { "Foo", "Bar", NULL };
gchar **copy;
copy = g_strdupv (NULL);
g_assert (copy == NULL);
copy = g_strdupv (vec);
g_assert (copy != NULL);
g_assert_cmpstr (copy[0], ==, "Foo");
g_assert_cmpstr (copy[1], ==, "Bar");
g_assert (copy[2] == NULL);
g_strfreev (copy);
}
static void
test_strnfill (void)
{
gchar *str;
str = g_strnfill (0, 'a');
g_assert (str != NULL);
g_assert (*str == '\0');
g_free (str);
str = g_strnfill (5, 'a');
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "aaaaa");
g_free (str);
}
static void
test_strconcat (void)
{
gchar *str;
str = g_strconcat (GLIB_TEST_STRING, NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
g_free (str);
str = g_strconcat (GLIB_TEST_STRING,
GLIB_TEST_STRING,
GLIB_TEST_STRING,
NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING GLIB_TEST_STRING GLIB_TEST_STRING);
g_free (str);
}
static void
test_strjoin (void)
{
gchar *str;
str = g_strjoin (NULL, NULL);
g_assert (str != NULL);
g_assert (*str == '\0');
g_free (str);
str = g_strjoin (":", NULL);
g_assert (str != NULL);
g_assert (*str == '\0');
g_free (str);
str = g_strjoin (NULL, GLIB_TEST_STRING, NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
g_free (str);
str = g_strjoin (NULL,
GLIB_TEST_STRING,
GLIB_TEST_STRING,
GLIB_TEST_STRING,
NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING GLIB_TEST_STRING GLIB_TEST_STRING);
g_free (str);
str = g_strjoin (":",
GLIB_TEST_STRING,
GLIB_TEST_STRING,
GLIB_TEST_STRING,
NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING ":" GLIB_TEST_STRING ":" GLIB_TEST_STRING);
g_free (str);
}
static void
test_strcanon (void)
{
gchar *str;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strcanon (NULL, "ab", 'y');
}
g_test_trap_assert_failed ();
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strdup ("abxabxab");
str = g_strcanon (str, NULL, 'y');
g_free (str);
}
g_test_trap_assert_failed ();
str = g_strdup ("abxabxab");
str = g_strcanon (str, "ab", 'y');
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "abyabyab");
g_free (str);
}
static void
test_strcompress_strescape (void)
{
gchar *str;
gchar *tmp;
/* test compress */
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strcompress (NULL);
}
g_test_trap_assert_failed ();
/* trailing slashes are not allowed */
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strcompress ("abc\\");
}
g_test_trap_assert_failed ();
str = g_strcompress ("abc\\\\\\\"\\b\\f\\n\\r\\t\\003\\177\\234\\313\\12345z");
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "abc\\\"\b\f\n\r\t\003\177\234\313\12345z");
g_free (str);
/* test escape */
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strescape (NULL, NULL);
}
g_test_trap_assert_failed ();
str = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313", NULL);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "abc\\\\\\\"\\b\\f\\n\\r\\t\\003\\177\\234\\313");
g_free (str);
str = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313",
"\b\f\001\002\003\004");
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "abc\\\\\\\"\b\f\\n\\r\\t\003\\177\\234\\313");
g_free (str);
/* round trip */
tmp = g_strescape ("abc\\\"\b\f\n\r\t\003\177\234\313", NULL);
str = g_strcompress (tmp);
g_assert (str != NULL);
g_assert_cmpstr (str, ==, "abc\\\"\b\f\n\r\t\003\177\234\313");
g_free (str);
g_free (tmp);
}
static void
test_ascii_strcasecmp (void)
{
gboolean res;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_ascii_strcasecmp ("foo", NULL);
}
g_test_trap_assert_failed ();
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_ascii_strcasecmp (NULL, "foo");
}
g_test_trap_assert_failed ();
res = g_ascii_strcasecmp ("FroboZZ", "frobozz");
g_assert_cmpint (res, ==, 0);
res = g_ascii_strcasecmp ("frobozz", "frobozz");
g_assert_cmpint (res, ==, 0);
res = g_ascii_strcasecmp ("frobozz", "FROBOZZ");
g_assert_cmpint (res, ==, 0);
res = g_ascii_strcasecmp ("FROBOZZ", "froboz");
g_assert_cmpint (res, !=, 0);
res = g_ascii_strcasecmp ("", "");
g_assert_cmpint (res, ==, 0);
res = g_ascii_strcasecmp ("!#%&/()", "!#%&/()");
g_assert_cmpint (res, ==, 0);
res = g_ascii_strcasecmp ("a", "b");
g_assert_cmpint (res, <, 0);
res = g_ascii_strcasecmp ("a", "B");
g_assert_cmpint (res, <, 0);
res = g_ascii_strcasecmp ("A", "b");
g_assert_cmpint (res, <, 0);
res = g_ascii_strcasecmp ("A", "B");
g_assert_cmpint (res, <, 0);
res = g_ascii_strcasecmp ("b", "a");
g_assert_cmpint (res, >, 0);
res = g_ascii_strcasecmp ("b", "A");
g_assert_cmpint (res, >, 0);
res = g_ascii_strcasecmp ("B", "a");
g_assert_cmpint (res, >, 0);
res = g_ascii_strcasecmp ("B", "A");
g_assert_cmpint (res, >, 0);
}
static void
do_test_strchug (const gchar *str, const gchar *expected)
{
gchar *tmp;
gboolean res;
tmp = g_strdup (str);
g_strchug (tmp);
res = (strcmp (tmp, expected) == 0);
g_free (tmp);
g_assert_cmpint (res, ==, TRUE);
}
static void
test_strchug (void)
{
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
g_strchug (NULL);
}
g_test_trap_assert_failed ();
do_test_strchug ("", "");
do_test_strchug (" ", "");
do_test_strchug ("\t\r\n ", "");
do_test_strchug (" a", "a");
do_test_strchug (" a", "a");
do_test_strchug ("a a", "a a");
do_test_strchug (" a a", "a a");
}
static void
do_test_strchomp (const gchar *str, const gchar *expected)
{
gchar *tmp;
gboolean res;
tmp = g_strdup (str);
g_strchomp (tmp);
res = (strcmp (tmp, expected) == 0);
g_free (tmp);
g_assert_cmpint (res, ==, TRUE);
}
static void
test_strchomp (void)
{
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
g_strchomp (NULL);
}
g_test_trap_assert_failed ();
do_test_strchomp ("", "");
do_test_strchomp (" ", "");
do_test_strchomp (" \t\r\n", "");
do_test_strchomp ("a ", "a");
do_test_strchomp ("a ", "a");
do_test_strchomp ("a a", "a a");
do_test_strchomp ("a a ", "a a");
}
static void
test_strreverse (void)
{
gchar *str;
gchar *p;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
str = g_strreverse (NULL);
}
g_test_trap_assert_failed ();
str = p = g_strdup ("abcde");
str = g_strreverse (str);
g_assert (str != NULL);
g_assert (p == str);
g_assert_cmpstr (str, ==, "edcba");
g_free (str);
}
static void
test_strstr (void)
{
gchar *haystack;
gchar *res;
haystack = g_strdup ("FooBarFooBarFoo");
/* strstr_len */
res = g_strstr_len (haystack, 6, "xxx");
g_assert (res == NULL);
res = g_strstr_len (haystack, 6, "FooBarFooBarFooBar");
g_assert (res == NULL);
res = g_strstr_len (haystack, 3, "Bar");
g_assert (res == NULL);
res = g_strstr_len (haystack, 6, "");
g_assert (res == haystack);
g_assert_cmpstr (res, ==, "FooBarFooBarFoo");
res = g_strstr_len (haystack, 6, "Bar");
g_assert (res == haystack + 3);
g_assert_cmpstr (res, ==, "BarFooBarFoo");
res = g_strstr_len (haystack, -1, "Bar");
g_assert (res == haystack + 3);
g_assert_cmpstr (res, ==, "BarFooBarFoo");
/* strrstr */
res = g_strrstr (haystack, "xxx");
g_assert (res == NULL);
res = g_strrstr (haystack, "FooBarFooBarFooBar");
g_assert (res == NULL);
res = g_strrstr (haystack, "");
g_assert (res == haystack);
g_assert_cmpstr (res, ==, "FooBarFooBarFoo");
res = g_strrstr (haystack, "Bar");
g_assert (res == haystack + 9);
g_assert_cmpstr (res, ==, "BarFoo");
/* strrstr_len */
res = g_strrstr_len (haystack, 14, "xxx");
g_assert (res == NULL);
res = g_strrstr_len (haystack, 14, "FooBarFooBarFooBar");
g_assert (res == NULL);
res = g_strrstr_len (haystack, 3, "Bar");
g_assert (res == NULL);
res = g_strrstr_len (haystack, 14, "BarFoo");
g_assert (res == haystack + 3);
g_assert_cmpstr (res, ==, "BarFooBarFoo");
res = g_strrstr_len (haystack, 15, "BarFoo");
g_assert (res == haystack + 9);
g_assert_cmpstr (res, ==, "BarFoo");
res = g_strrstr_len (haystack, -1, "BarFoo");
g_assert (res == haystack + 9);
g_assert_cmpstr (res, ==, "BarFoo");
/* test case for strings with \0 in the middle */
*(haystack + 7) = '\0';
res = g_strstr_len (haystack, 15, "BarFoo");
g_assert (res == NULL);
g_free (haystack);
}
static void
test_has_prefix (void)
{
gboolean res;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_str_has_prefix ("foo", NULL);
}
g_test_trap_assert_failed ();
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_str_has_prefix (NULL, "foo");
}
g_test_trap_assert_failed ();
res = g_str_has_prefix ("foo", "bar");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_prefix ("foo", "foobar");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_prefix ("foobar", "bar");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_prefix ("foobar", "foo");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_prefix ("foo", "");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_prefix ("foo", "foo");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_prefix ("", "");
g_assert_cmpint (res, ==, TRUE);
}
static void
test_has_suffix (void)
{
gboolean res;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_str_has_suffix ("foo", NULL);
}
g_test_trap_assert_failed ();
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
res = g_str_has_suffix (NULL, "foo");
}
g_test_trap_assert_failed ();
res = g_str_has_suffix ("foo", "bar");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_suffix ("bar", "foobar");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_suffix ("foobar", "foo");
g_assert_cmpint (res, ==, FALSE);
res = g_str_has_suffix ("foobar", "bar");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_suffix ("foo", "");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_suffix ("foo", "foo");
g_assert_cmpint (res, ==, TRUE);
res = g_str_has_suffix ("", "");
g_assert_cmpint (res, ==, TRUE);
}
static void
strv_check (gchar **strv, ...)
{
gboolean ok = TRUE;
gint i = 0;
va_list list;
va_start (list, strv);
while (ok)
{
const gchar *str = va_arg (list, const char *);
if (strv[i] == NULL)
{
g_assert (str == NULL);
break;
}
if (str == NULL)
{
ok = FALSE;
}
else
{
g_assert_cmpstr (strv[i], ==, str);
}
i++;
}
va_end (list);
g_strfreev (strv);
}
static void
test_strsplit (void)
{
strv_check (g_strsplit ("", ",", 0), NULL);
strv_check (g_strsplit ("x", ",", 0), "x", NULL);
strv_check (g_strsplit ("x,y", ",", 0), "x", "y", NULL);
strv_check (g_strsplit ("x,y,", ",", 0), "x", "y", "", NULL);
strv_check (g_strsplit (",x,y", ",", 0), "", "x", "y", NULL);
strv_check (g_strsplit (",x,y,", ",", 0), "", "x", "y", "", NULL);
strv_check (g_strsplit ("x,y,z", ",", 0), "x", "y", "z", NULL);
strv_check (g_strsplit ("x,y,z,", ",", 0), "x", "y", "z", "", NULL);
strv_check (g_strsplit (",x,y,z", ",", 0), "", "x", "y", "z", NULL);
strv_check (g_strsplit (",x,y,z,", ",", 0), "", "x", "y", "z", "", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",,", 0), "", "x", "y", "z", "", NULL);
strv_check (g_strsplit ("", ",", 1), NULL);
strv_check (g_strsplit ("x", ",", 1), "x", NULL);
strv_check (g_strsplit ("x,y", ",", 1), "x,y", NULL);
strv_check (g_strsplit ("x,y,", ",", 1), "x,y,", NULL);
strv_check (g_strsplit (",x,y", ",", 1), ",x,y", NULL);
strv_check (g_strsplit (",x,y,", ",", 1), ",x,y,", NULL);
strv_check (g_strsplit ("x,y,z", ",", 1), "x,y,z", NULL);
strv_check (g_strsplit ("x,y,z,", ",", 1), "x,y,z,", NULL);
strv_check (g_strsplit (",x,y,z", ",", 1), ",x,y,z", NULL);
strv_check (g_strsplit (",x,y,z,", ",", 1), ",x,y,z,", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",", 1), ",,x,,y,,z,,", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",,", 1), ",,x,,y,,z,,", NULL);
strv_check (g_strsplit ("", ",", 2), NULL);
strv_check (g_strsplit ("x", ",", 2), "x", NULL);
strv_check (g_strsplit ("x,y", ",", 2), "x", "y", NULL);
strv_check (g_strsplit ("x,y,", ",", 2), "x", "y,", NULL);
strv_check (g_strsplit (",x,y", ",", 2), "", "x,y", NULL);
strv_check (g_strsplit (",x,y,", ",", 2), "", "x,y,", NULL);
strv_check (g_strsplit ("x,y,z", ",", 2), "x", "y,z", NULL);
strv_check (g_strsplit ("x,y,z,", ",", 2), "x", "y,z,", NULL);
strv_check (g_strsplit (",x,y,z", ",", 2), "", "x,y,z", NULL);
strv_check (g_strsplit (",x,y,z,", ",", 2), "", "x,y,z,", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",", 2), "", ",x,,y,,z,,", NULL);
strv_check (g_strsplit (",,x,,y,,z,,", ",,", 2), "", "x,,y,,z,,", NULL);
}
static void
test_strsplit_set (void)
{
strv_check (g_strsplit_set ("", ",/", 0), NULL);
strv_check (g_strsplit_set (":def/ghi:", ":/", -1), "", "def", "ghi", "", NULL);
strv_check (g_strsplit_set ("abc:def/ghi", ":/", -1), "abc", "def", "ghi", NULL);
strv_check (g_strsplit_set (",;,;,;,;", ",;", -1), "", "", "", "", "", "", "", "", "", NULL);
strv_check (g_strsplit_set (",,abc.def", ".,", -1), "", "", "abc", "def", NULL);
strv_check (g_strsplit_set (",x.y", ",.", 0), "", "x", "y", NULL);
strv_check (g_strsplit_set (".x,y,", ",.", 0), "", "x", "y", "", NULL);
strv_check (g_strsplit_set ("x,y.z", ",.", 0), "x", "y", "z", NULL);
strv_check (g_strsplit_set ("x.y,z,", ",.", 0), "x", "y", "z", "", NULL);
strv_check (g_strsplit_set (",x.y,z", ",.", 0), "", "x", "y", "z", NULL);
strv_check (g_strsplit_set (",x,y,z,", ",.", 0), "", "x", "y", "z", "", NULL);
strv_check (g_strsplit_set (",.x,,y,;z..", ".,;", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
strv_check (g_strsplit_set (",,x,,y,,z,,", ",,", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
strv_check (g_strsplit_set ("x,y.z", ",.", 1), "x,y.z", NULL);
strv_check (g_strsplit_set ("x.y,z,", ",.", 1), "x.y,z,", NULL);
strv_check (g_strsplit_set (",x,y,z", ",.", 1), ",x,y,z", NULL);
strv_check (g_strsplit_set (",x,y.z,", ",.", 1), ",x,y.z,", NULL);
strv_check (g_strsplit_set (",,x,.y,,z,,", ",.", 1), ",,x,.y,,z,,", NULL);
strv_check (g_strsplit_set (",.x,,y,,z,,", ",,..", 1), ",.x,,y,,z,,", NULL);
strv_check (g_strsplit_set ("", ",", 0), NULL);
strv_check (g_strsplit_set ("x", ",", 0), "x", NULL);
strv_check (g_strsplit_set ("x,y", ",", 0), "x", "y", NULL);
strv_check (g_strsplit_set ("x,y,", ",", 0), "x", "y", "", NULL);
strv_check (g_strsplit_set (",x,y", ",", 0), "", "x", "y", NULL);
strv_check (g_strsplit_set (",x,y,", ",", 0), "", "x", "y", "", NULL);
strv_check (g_strsplit_set ("x,y,z", ",", 0), "x", "y", "z", NULL);
strv_check (g_strsplit_set ("x,y,z,", ",", 0), "x", "y", "z", "", NULL);
strv_check (g_strsplit_set (",x,y,z", ",", 0), "", "x", "y", "z", NULL);
strv_check (g_strsplit_set (",x,y,z,", ",", 0), "", "x", "y", "z", "", NULL);
strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 0), "", "", "x", "", "y", "", "z", "", "", NULL);
strv_check (g_strsplit_set ("", ",", 1), NULL);
strv_check (g_strsplit_set ("x", ",", 1), "x", NULL);
strv_check (g_strsplit_set ("x,y", ",", 1), "x,y", NULL);
strv_check (g_strsplit_set ("x,y,", ",", 1), "x,y,", NULL);
strv_check (g_strsplit_set (",x,y", ",", 1), ",x,y", NULL);
strv_check (g_strsplit_set (",x,y,", ",", 1), ",x,y,", NULL);
strv_check (g_strsplit_set ("x,y,z", ",", 1), "x,y,z", NULL);
strv_check (g_strsplit_set ("x,y,z,", ",", 1), "x,y,z,", NULL);
strv_check (g_strsplit_set (",x,y,z", ",", 1), ",x,y,z", NULL);
strv_check (g_strsplit_set (",x,y,z,", ",", 1), ",x,y,z,", NULL);
strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 1), ",,x,,y,,z,,", NULL);
strv_check (g_strsplit_set (",,x,,y,,z,,", ",,", 1), ",,x,,y,,z,,", NULL);
strv_check (g_strsplit_set ("", ",", 2), NULL);
strv_check (g_strsplit_set ("x", ",", 2), "x", NULL);
strv_check (g_strsplit_set ("x,y", ",", 2), "x", "y", NULL);
strv_check (g_strsplit_set ("x,y,", ",", 2), "x", "y,", NULL);
strv_check (g_strsplit_set (",x,y", ",", 2), "", "x,y", NULL);
strv_check (g_strsplit_set (",x,y,", ",", 2), "", "x,y,", NULL);
strv_check (g_strsplit_set ("x,y,z", ",", 2), "x", "y,z", NULL);
strv_check (g_strsplit_set ("x,y,z,", ",", 2), "x", "y,z,", NULL);
strv_check (g_strsplit_set (",x,y,z", ",", 2), "", "x,y,z", NULL);
strv_check (g_strsplit_set (",x,y,z,", ",", 2), "", "x,y,z,", NULL);
strv_check (g_strsplit_set (",,x,,y,,z,,", ",", 2), "", ",x,,y,,z,,", NULL);
strv_check (g_strsplit_set (",,x,.y,..z,,", ",.", 3), "", "", "x,.y,..z,,", NULL);
}
static void
test_strv_length (void)
{
guint l;
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
{
l = g_strv_length (NULL);
}
g_test_trap_assert_failed ();
l = g_strv_length (g_strsplit ("1,2,3,4", ",", -1));
g_assert_cmpuint (l, ==, 4);
}
static char *locales[] = {"sv_SE", "en_US", "fa_IR", "C", "ru_RU"};
void
check_strtod_string (gchar *number,
double res,
gboolean check_end,
gint correct_len)
{
double d;
gint l;
gchar *dummy;
/* we try a copy of number, with some free space for malloc before that.
* This is supposed to smash the some wrong pointer calculations. */
dummy = g_malloc (100000);
number = g_strdup (number);
g_free (dummy);
for (l = 0; l < G_N_ELEMENTS (locales); l++)
{
gboolean ok;
gchar *end = "(unset)";
setlocale (LC_NUMERIC, locales[l]);
d = g_ascii_strtod (number, &end);
ok = isnan (res) ? isnan (d) : (d == res);
if (!ok)
{
g_error ("g_ascii_strtod on \"%s\" for locale %s failed\n" \
"expected %f (nan %d) actual %f (nan %d)\n",
number, locales[l],
res, isnan (res),
d, isnan (d));
}
ok = (end - number) == (check_end ? correct_len : strlen (number));
if (!ok) {
if (end == NULL)
g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was NULL\n",
number, locales[l]);
else if (end >= number && end <= number + strlen (number))
g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was wrong, leftover: \"%s\"\n",
number, locales[l], end);
else
g_error ("g_ascii_strtod on \"%s\" for locale %s endptr was REALLY wrong (number=%p, end=%p)\n",
number, locales[l], number, end);
}
}
g_free (number);
}
static void
check_strtod_number (gdouble num, gchar *fmt, gchar *str)
{
int l;
gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
for (l = 0; l < G_N_ELEMENTS (locales); l++)
{
g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, fmt, num);
g_assert_cmpstr (buf, ==, str);
}
}
static void
test_strtod (void)
{
gdouble d, our_nan, our_inf;
char buffer[G_ASCII_DTOSTR_BUF_SIZE];
#ifdef NAN
our_nan = NAN;
#else
/* Do this before any call to setlocale. */
our_nan = atof ("NaN");
#endif
g_assert (isnan (our_nan));
#ifdef INFINITY
our_inf = INFINITY;
#else
our_inf = atof ("Infinity");
#endif
g_assert (our_inf > 1 && our_inf == our_inf / 2);
check_strtod_string ("123.123", 123.123, FALSE, 0);
check_strtod_string ("123.123e2", 123.123e2, FALSE, 0);
check_strtod_string ("123.123e-2", 123.123e-2, FALSE, 0);
check_strtod_string ("-123.123", -123.123, FALSE, 0);
check_strtod_string ("-123.123e2", -123.123e2, FALSE, 0);
check_strtod_string ("-123.123e-2", -123.123e-2, FALSE, 0);
check_strtod_string ("5.4", 5.4, TRUE, 3);
check_strtod_string ("5.4,5.5", 5.4, TRUE, 3);
check_strtod_string ("5,4", 5.0, TRUE, 1);
check_strtod_string ("0xa.b", 10.6875, TRUE, 5);
check_strtod_string ("0xa.bP3", 85.5, TRUE, 7);
check_strtod_string ("0xa.bp+3", 85.5, TRUE, 8);
check_strtod_string ("0xa.bp-2", 2.671875, TRUE, 8);
check_strtod_string ("0xA.BG", 10.6875, TRUE, 5);
/* the following are for #156421 */
check_strtod_string ("1e1", 1e1, FALSE, 0);
check_strtod_string ("NAN", our_nan, FALSE, 0);
check_strtod_string ("-nan", -our_nan, FALSE, 0);
check_strtod_string ("INF", our_inf, FALSE, 0);
check_strtod_string ("-infinity", -our_inf, FALSE, 0);
check_strtod_string ("-.75,0", -0.75, TRUE, 4);
d = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
d = -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
d = pow (2.0, -1024.1);
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
d = -pow (2.0, -1024.1);
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
/* for #343899 */
check_strtod_string (" 0.75", 0.75, FALSE, 0);
check_strtod_string (" +0.75", 0.75, FALSE, 0);
check_strtod_string (" -0.75", -0.75, FALSE, 0);
check_strtod_string ("\f0.75", 0.75, FALSE, 0);
check_strtod_string ("\n0.75", 0.75, FALSE, 0);
check_strtod_string ("\r0.75", 0.75, FALSE, 0);
check_strtod_string ("\t0.75", 0.75, FALSE, 0);
#if 0
/* g_ascii_isspace() returns FALSE for vertical tab, see #59388 */
check_strtod_string ("\v0.75", 0.75, FALSE, 0);
#endif
/* for #343899 */
check_strtod_number (0.75, "%0.2f", "0.75");
check_strtod_number (0.75, "%5.2f", " 0.75");
check_strtod_number (-0.75, "%0.2f", "-0.75");
check_strtod_number (-0.75, "%5.2f", "-0.75");
check_strtod_number (1e99, "%.0e", "1e+99");
}
static void
check_uint64 (const gchar *str,
const gchar *end,
gint base,
guint64 result,
gint error)
{
guint64 actual;
gchar *endptr = NULL;
gint err;
errno = 0;
actual = g_ascii_strtoull (str, &endptr, base);
err = errno;
g_assert (actual == result);
g_assert_cmpstr (end, ==, endptr);
g_assert (err == error);
}
static void
check_int64 (const gchar *str,
const gchar *end,
gint base,
gint64 result,
gint error)
{
gint64 actual;
gchar *endptr = NULL;
gint err;
errno = 0;
actual = g_ascii_strtoll (str, &endptr, base);
err = errno;
g_assert (actual == result);
g_assert_cmpstr (end, ==, endptr);
g_assert (err == error);
}
static void
test_strtoll (void)
{
check_uint64 ("0", "", 10, 0, 0);
check_uint64 ("+0", "", 10, 0, 0);
check_uint64 ("-0", "", 10, 0, 0);
check_uint64 ("18446744073709551615", "", 10, G_MAXUINT64, 0);
check_uint64 ("18446744073709551616", "", 10, G_MAXUINT64, ERANGE);
check_uint64 ("20xyz", "xyz", 10, 20, 0);
check_uint64 ("-1", "", 10, G_MAXUINT64, 0);
check_int64 ("0", "", 10, 0, 0);
check_int64 ("9223372036854775807", "", 10, G_MAXINT64, 0);
check_int64 ("9223372036854775808", "", 10, G_MAXINT64, ERANGE);
check_int64 ("-9223372036854775808", "", 10, G_MININT64, 0);
check_int64 ("-9223372036854775809", "", 10, G_MININT64, ERANGE);
check_int64 ("32768", "", 10, 32768, 0);
check_int64 ("-32768", "", 10, -32768, 0);
check_int64 ("001", "", 10, 1, 0);
check_int64 ("-001", "", 10, -1, 0);
}
static void
test_bounds (void)
{
GMappedFile *file, *before, *after;
char buffer[4097];
char *tmp, *tmp2;
char **array;
char *string;
/* if we allocate the file between two others and then free those
* other two, then hopefully we end up with unmapped memory on either
* side.
*/
before = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
/* quick workaround until #549783 can be fixed */
if (before == NULL)
return;
file = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
after = g_mapped_file_new ("4096-random-bytes", TRUE, NULL);
g_mapped_file_free (before);
g_mapped_file_free (after);
g_assert (file != NULL);
g_assert_cmpint (g_mapped_file_get_length (file), ==, 4096);
string = g_mapped_file_get_contents (file);
/* ensure they're all non-nul */
g_assert (memchr (string, '\0', 4096) == NULL);
/* test set 1: ensure that nothing goes past its maximum length, even in
* light of a missing nul terminator.
*
* we try to test all of the 'n' functions here.
*/
tmp = g_strndup (string, 4096);
g_assert_cmpint (strlen (tmp), ==, 4096);
g_free (tmp);
/* found no bugs in gnome, i hope :) */
g_assert (g_strstr_len (string, 4096, "BUGS") == NULL);
g_strstr_len (string, 4096, "B");
g_strstr_len (string, 4096, ".");
g_strstr_len (string, 4096, "");
g_strrstr_len (string, 4096, "BUGS");
g_strrstr_len (string, 4096, "B");
g_strrstr_len (string, 4096, ".");
g_strrstr_len (string, 4096, "");
g_ascii_strdown (string, 4096);
g_ascii_strdown (string, 4096);
g_ascii_strup (string, 4096);
g_ascii_strup (string, 4096);
g_ascii_strncasecmp (string, string, 4096);
tmp = g_markup_escape_text (string, 4096);
g_free (tmp);
/* test set 2: ensure that nothing reads even one byte past a '\0'.
*/
g_assert_cmpint (string[4095], ==, '\n');
string[4095] = '\0';
tmp = g_strdup (string);
g_assert_cmpint (strlen (tmp), ==, 4095);
g_free (tmp);
tmp = g_strndup (string, 10000);
g_assert_cmpint (strlen (tmp), ==, 4095);
g_free (tmp);
g_stpcpy (buffer, string);
g_assert_cmpint (strlen (buffer), ==, 4095);
g_strstr_len (string, 10000, "BUGS");
g_strstr_len (string, 10000, "B");
g_strstr_len (string, 10000, ".");
g_strstr_len (string, 10000, "");
g_strrstr (string, "BUGS");
g_strrstr (string, "B");
g_strrstr (string, ".");
g_strrstr (string, "");
g_strrstr_len (string, 10000, "BUGS");
g_strrstr_len (string, 10000, "B");
g_strrstr_len (string, 10000, ".");
g_strrstr_len (string, 10000, "");
g_str_has_prefix (string, "this won't do very much...");
g_str_has_suffix (string, "but maybe this will...");
g_str_has_suffix (string, "HMMMM.");
g_str_has_suffix (string, "MMMM.");
g_str_has_suffix (string, "M.");
g_strlcpy (buffer, string, sizeof buffer);
g_assert_cmpint (strlen (buffer), ==, 4095);
g_strlcpy (buffer, string, sizeof buffer);
buffer[0] = '\0';
g_strlcat (buffer, string, sizeof buffer);
g_assert_cmpint (strlen (buffer), ==, 4095);
tmp = g_strdup_printf ("<%s>", string);
g_assert_cmpint (strlen (tmp), ==, 4095 + 2);
g_free (tmp);
g_ascii_strdown (string, -1);
g_ascii_strdown (string, -1);
g_ascii_strup (string, -1);
g_ascii_strup (string, -1);
g_ascii_strcasecmp (string, string);
g_ascii_strncasecmp (string, string, 10000);
g_strreverse (string);
g_strreverse (string);
g_strchug (string);
g_strchomp (string);
g_strstrip (string);
g_assert_cmpint (strlen (string), ==, 4095);
g_strdelimit (string, "M", 'N');
g_strcanon (string, " N.", ':');
g_assert_cmpint (strlen (string), ==, 4095);
array = g_strsplit (string, ".", -1);
tmp = g_strjoinv (".", array);
g_strfreev (array);
g_assert_cmpint (strlen (tmp), ==, 4095);
g_assert (memcmp (tmp, string, 4095) == 0);
g_free (tmp);
tmp = g_strconcat (string, string, string, NULL);
g_assert_cmpint (strlen (tmp), ==, 4095 * 3);
g_free (tmp);
tmp = g_strjoin ("!", string, string, NULL);
g_assert_cmpint (strlen (tmp), ==, 4095 + 1 + 4095);
g_free (tmp);
tmp = g_markup_escape_text (string, -1);
g_free (tmp);
tmp = g_markup_printf_escaped ("%s", string);
g_free (tmp);
tmp = g_strescape (string, NULL);
tmp2 = g_strcompress (tmp);
g_assert_cmpstr (string, ==, tmp2);
g_free (tmp2);
g_free (tmp);
g_mapped_file_free (file);
}
static void
test_strip_context (void)
{
const gchar *msgid;
const gchar *msgval;
const gchar *s;
msgid = "blabla";
msgval = "bla";
s = g_strip_context (msgid, msgval);
g_assert (s == msgval);
msgid = msgval = "blabla";
s = g_strip_context (msgid, msgval);
g_assert (s == msgval);
msgid = msgval = "blabla|foo";
s = g_strip_context (msgid, msgval);
g_assert (s == msgval + 7);
msgid = msgval = "blabla||bar";
s = g_strip_context (msgid, msgval);
g_assert (s == msgval + 7);
}
int
main (int argc,
char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/strfuncs/test-is-to-digit", test_is_to_digit);
g_test_add_func ("/strfuncs/strdup", test_strdup);
g_test_add_func ("/strfuncs/strndup", test_strndup);
g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf);
g_test_add_func ("/strfuncs/strdupv", test_strdupv);
g_test_add_func ("/strfuncs/strnfill", test_strnfill);
g_test_add_func ("/strfuncs/strconcat", test_strconcat);
g_test_add_func ("/strfuncs/strjoin", test_strjoin);
g_test_add_func ("/strfuncs/strcanon", test_strcanon);
g_test_add_func ("/strfuncs/strcompress-strescape", test_strcompress_strescape);
g_test_add_func ("/strfuncs/ascii-strcasecmp", test_ascii_strcasecmp);
g_test_add_func ("/strfuncs/strchug", test_strchug);
g_test_add_func ("/strfuncs/strchomp", test_strchomp);
g_test_add_func ("/strfuncs/strreverse", test_strreverse);
g_test_add_func ("/strfuncs/strstr", test_strstr);
g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
g_test_add_func ("/strfuncs/strsplit", test_strsplit);
g_test_add_func ("/strfuncs/strsplit-set", test_strsplit_set);
g_test_add_func ("/strfuncs/strv-length", test_strv_length);
g_test_add_func ("/strfuncs/strtod", test_strtod);
g_test_add_func ("/strfuncs/strtoull-strtoll", test_strtoll);
g_test_add_func ("/strfuncs/bounds-check", test_bounds);
g_test_add_func ("/strfuncs/strip-context", test_strip_context);
return g_test_run();
}