aboutsummaryrefslogtreecommitdiff
path: root/locale/tst-localedef-path-norm.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/tst-localedef-path-norm.c')
-rw-r--r--locale/tst-localedef-path-norm.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/locale/tst-localedef-path-norm.c b/locale/tst-localedef-path-norm.c
new file mode 100644
index 0000000..2ef1d26
--- /dev/null
+++ b/locale/tst-localedef-path-norm.c
@@ -0,0 +1,242 @@
+/* Test for localedef path name handling and normalization.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C 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.
+
+ The GNU C 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* The test runs localedef with various named paths to test for expected
+ behaviours dealing with codeset name normalization. That is to say that use
+ of UTF-8, and it's variations, are normalized to utf8. Likewise that values
+ after the @ are not normalized and left as-is. The test needs to run
+ localedef with known input values and then check that the generated path
+ matches the expected value after normalization. */
+
+/* Note: In some cases adding -v (verbose) to localedef changes the exit
+ status to a non-zero value because some warnings are only enabled in verbose
+ mode. This should probably be changed so warnings are either present or not
+ present, regardless of verbosity. POSIX requires that any warnings cause the
+ exit status to be non-zero. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+
+/* Full path to localedef. */
+char *prog;
+
+/* Execute localedef in a subprocess. */
+static void
+execv_wrapper (void *args)
+{
+ char **argv = args;
+
+ execv (prog, argv);
+ FAIL_EXIT1 ("execv: %m");
+}
+
+struct test_closure
+{
+ /* Arguments for running localedef. */
+ const char *const argv[16];
+ /* Expected directory name for compiled locale. */
+ const char *exp;
+ /* Expected path to compiled locale. */
+ const char *complocaledir;
+};
+
+/* Run localedef with DATA.ARGV arguments (NULL terminated), and expect path to
+ the compiled locale is "DATA.COMPLOCALEDIR/DATA.EXP". */
+static void
+run_test (struct test_closure data)
+{
+ const char * const *args = data.argv;
+ const char *exp = data.exp;
+ const char *complocaledir = data.complocaledir;
+ struct stat64 fs;
+
+ /* Expected output path. */
+ const char *path = xasprintf ("%s/%s", complocaledir, exp);
+
+ /* Run test. */
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (execv_wrapper, (void *)args);
+ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none);
+ support_capture_subprocess_free (&result);
+
+ /* Verify path is present and is a directory. */
+ xstat (path, &fs);
+ TEST_VERIFY_EXIT (S_ISDIR (fs.st_mode));
+ printf ("info: Directory '%s' exists.\n", path);
+}
+
+static int
+do_test (void)
+{
+ /* We are running as root inside the container. */
+ prog = xasprintf ("%s/localedef", support_bindir_prefix);
+
+ /* Create the needed directories:
+ - We need the default compiled locale dir for default output.
+ - We need an arbitrary absolute path for localedef output.
+
+ Note: Writing to a non-default absolute path disables any kind
+ of path normalization since we expect the user wants the path
+ exactly as they specified it. */
+ xmkdirp (support_complocaledir_prefix, 0777);
+ xmkdirp ("/output", 0777);
+
+ /* It takes ~10 seconds to serially execute 9 localedef test. We
+ could run the compilations in parallel if we want to reduce test
+ time. We don't want to split this out into distinct tests because
+ it would require multiple chroots. Batching the same localedef
+ tests saves disk space during testing. */
+
+ /* Test 1: Expected normalization.
+ Run localedef and expect output in /usr/lib/locale/en_US1.utf8,
+ with normalization changing UTF-8 to utf8. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US1.UTF-8", NULL },
+ .exp = "en_US1.utf8",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 2: No normalization past '@'.
+ Run localedef and expect output in /usr/lib/locale/en_US2.utf8@tEsT,
+ with normalization changing UTF-8@tEsT to utf8@tEsT (everything after
+ @ is untouched). */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US2.UTF-8@tEsT", NULL },
+ .exp = "en_US2.utf8@tEsT",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 3: No normalization past '@' despite period.
+ Run localedef and expect output in /usr/lib/locale/en_US3@tEsT.UTF-8,
+ with normalization changing nothing (everything after @ is untouched)
+ despite there being a period near the end. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US3@tEsT.UTF-8", NULL },
+ .exp = "en_US3@tEsT.UTF-8",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 4: Normalize numeric codeset by adding 'iso' prefix.
+ Run localedef and expect output in /usr/lib/locale/en_US4.88591,
+ with normalization changing 88591 to iso88591. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US4.88591", NULL },
+ .exp = "en_US4.iso88591",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 5: Don't add 'iso' prefix if first char is alpha.
+ Run localedef and expect output in /usr/lib/locale/en_US5.a88591,
+ with normalization changing nothing. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US5.a88591", NULL },
+ .exp = "en_US5.a88591",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 6: Don't add 'iso' prefix if last char is alpha.
+ Run localedef and expect output in /usr/lib/locale/en_US6.88591a,
+ with normalization changing nothing. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "en_US6.88591a", NULL },
+ .exp = "en_US6.88591a",
+ .complocaledir = support_complocaledir_prefix
+ });
+
+ /* Test 7: Don't normalize anything with an absolute path.
+ Run localedef and expect output in /output/en_US7.UTF-8,
+ with normalization changing nothing. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "/output/en_US7.UTF-8", NULL },
+ .exp = "en_US7.UTF-8",
+ .complocaledir = "/output"
+ });
+
+ /* Test 8: Don't normalize anything with an absolute path.
+ Run localedef and expect output in /output/en_US8.UTF-8@tEsT,
+ with normalization changing nothing. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "/output/en_US8.UTF-8@tEsT", NULL },
+ .exp = "en_US8.UTF-8@tEsT",
+ .complocaledir = "/output"
+ });
+
+ /* Test 9: Don't normalize anything with an absolute path.
+ Run localedef and expect output in /output/en_US9@tEsT.UTF-8,
+ with normalization changing nothing. */
+ run_test ((struct test_closure)
+ {
+ .argv = { prog,
+ "--no-archive",
+ "-i", "en_US",
+ "-f", "UTF-8",
+ "/output/en_US9@tEsT.UTF-8", NULL },
+ .exp = "en_US9@tEsT.UTF-8",
+ .complocaledir = "/output"
+ });
+
+ return 0;
+}
+
+#include <support/test-driver.c>