>From 2d1b7501b00dce53481b58b3808313f264c720ea Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 18 Dec 2019 09:41:31 +0100 Subject: [PATCH] hard-locale: Add test. * tests/test-hard-locale.c: New file. * tests/locale.c: New file. * modules/hard-locale-tests: New file. --- ChangeLog | 7 +++ modules/hard-locale-tests | 18 ++++++++ tests/locale.c | 81 ++++++++++++++++++++++++++++++++++ tests/test-hard-locale.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 modules/hard-locale-tests create mode 100644 tests/locale.c create mode 100644 tests/test-hard-locale.c diff --git a/ChangeLog b/ChangeLog index 7988bec..2fffaf2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2019-12-18 Bruno Haible + + hard-locale: Add test. + * tests/test-hard-locale.c: New file. + * tests/locale.c: New file. + * modules/hard-locale-tests: New file. + 2019-12-17 Paul Eggert dfa: do not match invalid UTF-8 diff --git a/modules/hard-locale-tests b/modules/hard-locale-tests new file mode 100644 index 0000000..cdc084e --- /dev/null +++ b/modules/hard-locale-tests @@ -0,0 +1,18 @@ +Files: +tests/test-hard-locale.c +tests/locale.c + +Depends-on: + +configure.ac: +AC_REQUIRE([AC_CANONICAL_HOST]) +case "$host_os" in + *-musl*) AC_DEFINE([MUSL_LIBC], [1], [Define to 1 on musl libc.]) ;; +esac +dnl Distinguish OpenBSD >= 6.2 from OpenBSD < 6.2. +AC_CHECK_FUNCS_ONCE([duplocale]) + +Makefile.am: +TESTS += test-hard-locale +check_PROGRAMS += test-hard-locale +noinst_PROGRAMS += locale diff --git a/tests/locale.c b/tests/locale.c new file mode 100644 index 0000000..ac587ad --- /dev/null +++ b/tests/locale.c @@ -0,0 +1,81 @@ +/* Program that prints the names of the categories of the current locale. + Copyright (C) 2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2019. */ + +#include + +#include +#include +#include + +/* Specification: + + Here we implement only the invocation without any command-line options. */ + +static const char * +defaulted_getenv (const char *variable) +{ + const char *value = getenv (variable); + return (value != NULL ? value : ""); +} + +static void +print_category (int category, const char *variable) +{ + const char *value = defaulted_getenv (variable); + if (value[0] != '\0' && defaulted_getenv ("LC_ALL")[0] == '\0') + /* The variable is set in the environment and not overridden by LC_ALL. */ + printf ("%s=%s\n", variable, value); + else + printf ("%s=\"%s\"\n", variable, setlocale (category, NULL)); +} + +int +main () +{ + setlocale (LC_ALL, ""); + + printf ("LANG=%s\n", defaulted_getenv ("LANG")); + print_category (LC_CTYPE, "LC_CTYPE"); + print_category (LC_NUMERIC, "LC_NUMERIC"); + print_category (LC_TIME, "LC_TIME"); + print_category (LC_COLLATE, "LC_COLLATE"); + print_category (LC_MONETARY, "LC_MONETARY"); + print_category (LC_MESSAGES, "LC_MESSAGES"); +#ifdef LC_PAPER + print_category (LC_PAPER, "LC_PAPER"); +#endif +#ifdef LC_NAME + print_category (LC_NAME, "LC_NAME"); +#endif +#ifdef LC_ADDRESS + print_category (LC_ADDRESS, "LC_ADDRESS"); +#endif +#ifdef LC_TELEPHONE + print_category (LC_TELEPHONE, "LC_TELEPHONE"); +#endif +#ifdef LC_MEASUREMENT + print_category (LC_MEASUREMENT, "LC_MEASUREMENT"); +#endif +#ifdef LC_IDENTIFICATION + print_category (LC_IDENTIFICATION, "LC_IDENTIFICATION"); +#endif + + printf ("LC_ALL=%s\n", defaulted_getenv ("LC_ALL")); + + return 0; +} diff --git a/tests/test-hard-locale.c b/tests/test-hard-locale.c new file mode 100644 index 0000000..f83dc27 --- /dev/null +++ b/tests/test-hard-locale.c @@ -0,0 +1,109 @@ +/* Test of determination whether a locale is different from the "C" locale. + Copyright (C) 2019 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Bruno Haible , 2019. */ + +#include + +#include "hard-locale.h" + +#include +#include +#include +#include + +/* True if all locale names are accepted and all locales are trivial. + This is the case e.g. on OpenBSD 3.8. */ +static bool all_trivial; + +static int +test_one (const char *name, int failure_bitmask) +{ + if (setlocale (LC_ALL, name) != NULL) + { + bool expected; + + /* musl libc has special code for the C.UTF-8 locale; other than that, + all locale names are accepted and all locales are trivial. + OpenBSD returns the locale name that was set, but we don't know how it + behaves under the hood. */ +#if defined MUSL_LIBC || defined __OpenBSD__ + expected = true; +#else + expected = !all_trivial; +#endif + if (hard_locale (LC_CTYPE) != expected) + { + if (expected) + fprintf (stderr, "Unexpected: The category LC_CTYPE of the locale '%s' is not equivalent to C or POSIX.\n", + name); + else + fprintf (stderr, "Unexpected: The category LC_CTYPE of the locale '%s' is equivalent to C or POSIX.\n", + name); + return failure_bitmask; + } + + /* On NetBSD 7.0, some locales such as de_DE.ISO8859-1 and de_DE.UTF-8 + have the LC_COLLATE category set to "C". + Similarly, on musl libc, with the C.UTF-8 locale. */ +#if defined __NetBSD__ + expected = false; +#elif defined MUSL_LIBC + expected = strcmp (name, "C.UTF-8") != 0; +#elif defined __OpenBSD__ && HAVE_DUPLOCALE /* OpenBSD >= 6.2 */ + expected = true; +#else + expected = !all_trivial; +#endif + if (hard_locale (LC_COLLATE) != expected) + { + if (expected) + fprintf (stderr, "Unexpected: The category LC_COLLATE of the locale '%s' is not equivalent to C or POSIX.\n", + name); + else + fprintf (stderr, "Unexpected: The category LC_COLLATE of the locale '%s' is equivalent to C or POSIX.\n", + name); + return failure_bitmask; + } + } + return 0; +} + +int +main () +{ + int fail = 0; + + /* The initial locale is the "C" or "POSIX" locale. */ + if (hard_locale (LC_CTYPE) || hard_locale (LC_COLLATE)) + { + fprintf (stderr, "The initial locale should not be hard!\n"); + fail |= 1; + } + + all_trivial = (setlocale (LC_ALL, "foobar") != NULL); + + fail |= test_one ("de", 2); + fail |= test_one ("de_DE", 4); + fail |= test_one ("de_DE.ISO8859-1", 8); + fail |= test_one ("de_DE.iso88591", 8); + fail |= test_one ("de_DE.UTF-8", 16); + fail |= test_one ("de_DE.utf8", 16); + fail |= test_one ("german", 32); + fail |= test_one ("C.UTF-8", 64); + + return fail; +} -- 2.7.4