summaryrefslogtreecommitdiff
path: root/gnulib-tests/test-sh-quote.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnulib-tests/test-sh-quote.c')
-rw-r--r--gnulib-tests/test-sh-quote.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/gnulib-tests/test-sh-quote.c b/gnulib-tests/test-sh-quote.c
new file mode 100644
index 0000000..198d5fa
--- /dev/null
+++ b/gnulib-tests/test-sh-quote.c
@@ -0,0 +1,203 @@
+/* Test of sh-quote module.
+ Copyright (C) 2012-2013 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2012. */
+
+#include <config.h>
+
+/* Specification. */
+#include "sh-quote.h"
+
+#include <limits.h>
+#include <string.h>
+
+#include "macros.h"
+
+static void
+check_one (const char *input, const char *expected)
+{
+ char buf[1000];
+ size_t output_len;
+ char *output;
+ char *bufend;
+
+ output_len = shell_quote_length (input);
+
+ output = shell_quote (input);
+ ASSERT (strlen (output) == output_len);
+
+ ASSERT (output_len <= sizeof (buf) - 2);
+ memset (buf, '\0', output_len + 1);
+ buf[output_len + 1] = '%';
+ bufend = shell_quote_copy (buf, input);
+ ASSERT (bufend == buf + output_len);
+ ASSERT (memcmp (buf, output, output_len + 1) == 0);
+ ASSERT (buf[output_len + 1] == '%');
+
+ ASSERT (strcmp (output, expected) == 0);
+
+ free (output);
+}
+
+int
+main (void)
+{
+ /* Check the shell_quote_length, shell_quote_copy, shell_quote functions. */
+ {
+ int c;
+
+ /* Empty argument. */
+ check_one ("", "''");
+
+ /* Identifier or number. */
+ check_one ("foo", "foo");
+ check_one ("phr0ck", "phr0ck");
+
+ /* Whitespace would be interpreted as argument separator by the shell. */
+ check_one ("foo\tbar", "'foo\tbar'");
+ check_one ("foo\nbar", "'foo\nbar'");
+ check_one ("foo\rbar", "'foo\rbar'");
+ check_one ("foo bar", "'foo bar'");
+
+ /* '!' at the beginning of argv[0] would introduce a negated command. */
+ check_one ("!foo", "'!foo'");
+
+ /* '"' would be interpreted as the start of a string. */
+ check_one ("\"foo\"bar", "'\"foo\"bar'");
+
+ /* '#' at the beginning of an argument would be interpreted as the start
+ of a comment. */
+ check_one ("#foo", "'#foo'");
+
+ /* '$' at the beginning of an argument would be interpreted as a variable
+ reference. */
+ check_one ("$foo", "'$foo'");
+
+ /* '&' at the beginning of an argument would be interpreted as a background
+ task indicator. */
+ check_one ("&", "'&'");
+
+ /* "'" would be interpreted as the start of a string. */
+ check_one ("'foo'bar", "''\\''foo'\\''bar'"); /* or "\"'foo'bar\"" */
+
+ /* '(' at the beginning of argv[0] would introduce a subshell command. */
+ check_one ("(", "'('");
+
+ /* ')' at the beginning of an argument would be interpreted as the end of
+ the command. */
+ check_one (")", "')'");
+
+ /* '*' would be interpreted as a wildcard character. */
+ check_one ("*", "'*'");
+ check_one ("*foo", "'*foo'");
+
+ /* ';' at the beginning of an argument would be interpreted as an empty
+ statement in argv[0] and as the end of the command otherwise. */
+ check_one (";", "';'");
+ check_one ("foo;", "'foo;'");
+
+ /* '<' would be interpreted as a redirection of stdin. */
+ check_one ("<", "'<'");
+
+ /* '=' inside argv[0] would be interpreted as an environment variable
+ assignment. */
+ check_one ("foo=bar", "'foo=bar'");
+
+ /* '>' would be interpreted as a redirection of stdout. */
+ check_one (">", "'>'");
+
+ /* '?' would be interpreted as a wildcard character. */
+ check_one ("?", "'?'");
+ check_one ("foo?bar", "'foo?bar'");
+
+ /* '^' would be interpreted in old /bin/sh, e.g. SunOS 4.1.4. */
+ check_one ("^", "'^'");
+
+ /* "[...]" would be interpreted as a wildcard pattern. */
+ check_one ("[", "'['");
+ check_one ("]", "]"); /* or "']'" */
+
+ /* '\' would be interpreted as an escape character. */
+ check_one ("\\foo", "'\\foo'");
+
+ /* '`' would be interpreted as the start of a command substitution. */
+ check_one ("`foo", "'`foo'");
+
+ /* '{' at the beginning of argv[0] would introduce a complex command. */
+ check_one ("{", "'{'");
+
+ /* '|' at the beginning of an argument would be interpreted as a pipe
+ between commands. */
+ check_one ("|", "'|'");
+
+ /* '}' at the beginning of an argument would be interpreted as the end of
+ the command. */
+ check_one ("}", "'}'");
+
+ /* '~' at the beginning of an argument would be interpreted as a reference
+ to a user's home directory. */
+ check_one ("~", "'~'");
+ check_one ("~foo", "'~foo'");
+
+ /* A string that contains both ' and ". */
+ check_one ("foo'bar\"baz", "'foo'\\''bar\"baz'"); /* or "\"foo'bar\\\"baz\"" */
+
+ /* All other characters don't need quoting. */
+ for (c = 1; c <= UCHAR_MAX; c++)
+ if (strchr ("\t\n\r !\"#$&'()*;<=>?^[\\]`{|}~", c) == NULL)
+ {
+ char s[5];
+ s[0] = 'a';
+ s[1] = (char) c;
+ s[2] = 'z';
+ s[3] = (char) c;
+ s[4] = '\0';
+
+ check_one (s, s);
+ }
+ }
+
+ /* Check the shell_quote_argv function. */
+ {
+ char *argv[1];
+ char *result;
+ argv[0] = NULL;
+ result = shell_quote_argv (argv);
+ ASSERT (strcmp (result, "") == 0);
+ free (result);
+ }
+ {
+ char *argv[2];
+ char *result;
+ argv[0] = (char *) "foo bar/baz";
+ argv[1] = NULL;
+ result = shell_quote_argv (argv);
+ ASSERT (strcmp (result, "'foo bar/baz'") == 0); /* or "\"foo bar/baz\"" */
+ free (result);
+ }
+ {
+ char *argv[3];
+ char *result;
+ argv[0] = (char *) "foo bar/baz";
+ argv[1] = (char *) "$";
+ argv[2] = NULL;
+ result = shell_quote_argv (argv);
+ ASSERT (strcmp (result, "'foo bar/baz' '$'") == 0); /* or "\"foo bar/baz\" \"\\$\"" */
+ free (result);
+ }
+
+ return 0;
+}