aboutsummaryrefslogtreecommitdiff
path: root/localedata/tst-localedef-hardlinks.c
diff options
context:
space:
mode:
Diffstat (limited to 'localedata/tst-localedef-hardlinks.c')
-rw-r--r--localedata/tst-localedef-hardlinks.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/localedata/tst-localedef-hardlinks.c b/localedata/tst-localedef-hardlinks.c
new file mode 100644
index 0000000000..e8fda167be
--- /dev/null
+++ b/localedata/tst-localedef-hardlinks.c
@@ -0,0 +1,135 @@
+/* Test --no-hard-links option to localedef.
+ Copyright (C) 2020 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 is designed to run in a container and execute localedef
+ once without --no-hard-links, verify that there are 2 hard links to
+ LC_CTYPE, and then run again *with* --no-hard-links and verify there
+ are no hard links and link counts remain at 1. The expectation here
+ is that LC_CTYPE is identical for both locales because they are same
+ empty locale but with a different name. We use tests-container in
+ this test because the hard link optimziation is only carried out for
+ the default locale installation directory, and to write to that we
+ need write access to that directory, enabled by 'su' via
+ tests-container framework. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <support/capture_subprocess.h>
+
+/* Each test compiles a locale to output, and has an expected link count
+ for LC_CTYPE. This test expects that localedef removes the existing
+ files before installing new copies of the files, and we do not
+ cleanup between localedef runs. We can't cleanup between each pair
+ of runs since localedef must see the existing locale in order to
+ determine that space could be saved by using a hardlink. */
+struct test_data
+{
+ /* Arguments to localedef for this step. */
+ const char * argv[16];
+ /* Expected output file generated by running localedef. */
+ const char *output;
+ /* Expected st_nlink count for the output. */
+ int st_nlink;
+};
+
+/* Check for link count. */
+void
+check_link (struct test_data step)
+{
+ struct stat64 locale;
+ char *output;
+
+ output = xasprintf ("%s/%s", support_complocaledir_prefix, step.output);
+ xstat (output, &locale);
+ free (output);
+ TEST_COMPARE (locale.st_nlink, step.st_nlink);
+}
+
+static void
+run_localedef (void *step)
+{
+ const char *prog = xasprintf ("%s/localedef", support_bindir_prefix);
+ struct test_data *one = (struct test_data *) step;
+
+ one->argv[0] = prog;
+ execv (prog, (char * const *) one->argv);
+ FAIL_EXIT1 ("execv: %m");
+}
+
+#define TEST1DIR "test1_locale.dir"
+#define TEST2DIR "test2_locale.dir"
+
+/* The whole test has 4 steps described below. Note the argv[0] NULL
+ will be filled in at runtime by run_localedef. */
+static struct test_data step[4] = {
+ { .argv = { NULL, "--no-archive", "-i", "/test1_locale", TEST1DIR, NULL },
+ .output = TEST1DIR "/LC_CTYPE",
+ .st_nlink = 1 },
+ { .argv = { NULL, "--no-archive", "-i", "/test2_locale", TEST2DIR, NULL },
+ .output = TEST2DIR "/LC_CTYPE",
+ .st_nlink = 2 },
+ { .argv = { NULL, "--no-archive", "--no-hard-links", "-i", "/test1_locale",
+ TEST1DIR, NULL },
+ .output = TEST1DIR "/LC_CTYPE",
+ .st_nlink = 1 },
+ { .argv = { NULL, "--no-archive", "--no-hard-links", "-i", "/test2_locale",
+ TEST1DIR, NULL },
+ .output = TEST2DIR "/LC_CTYPE",
+ .st_nlink = 1 },
+};
+
+static int
+do_test (void)
+{
+ struct support_capture_subprocess result;
+
+ printf ("INFO: $complocaledir is %s\n", support_complocaledir_prefix);
+ /* Compile the first locale. */
+ result = support_capture_subprocess (run_localedef, (void *) &step[0]);
+ support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
+ check_link (step[0]);
+
+ /* This time around we should have link counts of 2 for the second
+ linked locale since categories are identical. */
+ result = support_capture_subprocess (run_localedef, (void *) &step[1]);
+ support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
+ check_link (step[1]);
+
+ /* Again with --no-hard-links (link count is always one). */
+ result = support_capture_subprocess (run_localedef, (void *) &step[2]);
+ support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
+ check_link (step[2]);
+
+ /* Again with --no-hard-links, and the link count must remain 1. */
+ result = support_capture_subprocess (run_localedef, (void *) &step[3]);
+ support_capture_subprocess_check (&result, "execv", 1, sc_allow_stderr);
+ check_link (step[3]);
+
+ /* Tested without and with --no-hard-links and link counts were
+ consistent. */
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>