diff options
Diffstat (limited to 'locale/tst-localedef-path-norm.c')
-rw-r--r-- | locale/tst-localedef-path-norm.c | 242 |
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> |