diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-07 12:05:19 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-06-07 13:06:17 +0300 |
commit | 453cd17f7a4be5ceaa8411a8a3ebd9fddd88df8e (patch) | |
tree | 3c919d804a8df24c01bc26854bcec4e0c5db21b6 /testsuite/cwdrepl.c | |
parent | 491bec23a77b19df8b9c0442696ce57e3fc5c604 (diff) | |
download | mailutils-453cd17f7a4be5ceaa8411a8a3ebd9fddd88df8e.tar.gz mailutils-453cd17f7a4be5ceaa8411a8a3ebd9fddd88df8e.tar.bz2 |
Fix tests when logical and physical CWD differ
MH testsuite produced false negatives when run in a directory accessed
by its logical name (symlink). To fix this, avoiding at the same time
the use of non-portable "pwd -P" & "pwd -L", this commit adds a filter
utility that replaces both logical and physical cwd with a dot on
output. The MH testsuite is updated to use this utility.
* testsuite/cwdrepl.c: New utility
* testsuite/Makefile.am: Build cwdrepl
* testsuite/.gitignore: Update.
* testsuite/cwdrepl.at: New test.
* testsuite/testsuite.at: Include new test.
* mh/tests/atlocal.in (PATH): Add testsuite
(remove_curdir): Remove function.
* mh/tests/comp.at: Use cwdrepl, fix expected output.
* mh/tests/forw.at: Likewise.
* mh/tests/mhn.at: Likewise.
* mh/tests/mhpath.at: Likewise.
* mh/tests/repl.at: Likewise.
Diffstat (limited to 'testsuite/cwdrepl.c')
-rw-r--r-- | testsuite/cwdrepl.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/testsuite/cwdrepl.c b/testsuite/cwdrepl.c new file mode 100644 index 000000000..9f6525f18 --- /dev/null +++ b/testsuite/cwdrepl.c @@ -0,0 +1,176 @@ +/* This file is part of GNU Mailutils testsuite. + Copyright (C) 2017 Free Software Foundation, Inc. + + GNU Mailutils 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, or (at your option) + any later version. + + GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +/* + +NAME + + cwdrepl - replace occurrences of CWD with . + +SYNOPSIS + + COMMAND | cwdrepl [DIR REPL]... + +DESCRIPTION + + Some testcases operate programs that produce full file names as part + of their output. To make this output independent of the actual file + location, this tool replaces every occurrence of the current working + directory with dot. Both logical (as given by the PWD environment + variable) and physical (as returned by getcwd(3)) locations are replaced. + + The same effect could have been achieved by using "pwd -P", "pwd -L" + and sed, but this would pose portability problems. + + Additionally, any number of DIR REPL pairs can be supplied in the command + line. Each pair instructs the tool to replace every occurrence of DIR + with REPL on output. Note that these pairs take precedence over the + default ones, so running "cwdrepl $PWD 'PWD'" will replace occurrences + of the logical current working directory name with the string PWS, instead + of the default dot. + +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <mailutils/mailutils.h> + +struct dirtrans +{ + char *dir; + size_t dirlen; + char const *trans; + ssize_t translen; +}; + +mu_list_t translist; + +static int +transcmp (const void *a, const void *b) +{ + struct dirtrans const *trans1 = a; + struct dirtrans const *trans2 = b; + return strcmp (trans1->dir, trans2->dir); +} + +static void +newdir (char const *dir, char const *trans) +{ + if (dir) + { + size_t dirlen = strlen (dir); + size_t translen = strlen (trans); + struct dirtrans *dt = mu_alloc (sizeof *dt); + + while (dirlen > 0 && dir[dirlen-1] == '/') + dirlen--; + + dt->dir = mu_alloc (dirlen + 1); + memcpy (dt->dir, dir, dirlen); + dt->dir[dirlen] = 0; + dt->dirlen = dirlen; + dt->trans = trans; + dt->translen = translen; + + if (!translist) + { + MU_ASSERT (mu_list_create (&translist)); + mu_list_set_comparator (translist, transcmp); + } + else if (mu_list_locate (translist, dt, NULL) == 0) + { + free (dt->dir); + free (dt); + return; + } + + MU_ASSERT (mu_list_append (translist, dt)); + } +} + +static inline int +isbnd (int c) +{ + return mu_c_is_class (c, MU_CTYPE_CNTRL|MU_CTYPE_PUNCT|MU_CTYPE_SPACE); +} + +int +main (int argc, char **argv) +{ + int i; + int rc; + char *buf = NULL; + size_t size, n; + mu_iterator_t itr; + + mu_set_program_name (argv[0]); + mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); + + for (i = 1; i < argc; i += 2) + newdir (argv[i], (i + 1 < argc) ? argv[i + 1] : ""); + + newdir (getenv ("PWD"), "."); + newdir (mu_getcwd (), "."); + + MU_ASSERT (mu_list_get_iterator (translist, &itr)); + while ((rc = mu_stream_getline (mu_strin, &buf, &size, &n)) == 0 && n > 0) + { + n = mu_rtrim_class (buf, MU_CTYPE_SPACE); + for (mu_iterator_first (itr); !mu_iterator_is_done (itr); + mu_iterator_next (itr)) + { + struct dirtrans *dt; + size_t start = 0; + char *p; + + mu_iterator_current (itr, (void**) &dt); + while ((p = strstr (buf + start, dt->dir))) + { + if (isbnd (p[dt->dirlen])) + { + size_t off = p - buf; + size_t rest = n - start; + ssize_t d = (ssize_t)dt->translen - dt->dirlen; + + if (d > 0) + { + if (n + d + 1 > size) + { + size = n + d + 1; + buf = mu_realloc (buf, size); + p = buf + off; + } + } + + memmove (p + dt->translen, p + dt->dirlen, + rest - dt->dirlen + 1); + memcpy (p, dt->trans, dt->translen); + + n += d; + start = off + dt->translen; + } + else + start++; + } + } + mu_stream_write (mu_strout, buf, n, NULL); + mu_stream_write (mu_strout, "\n", 1, NULL); + } + return 0; +} |