From: Bruno Haible Date: Mon, 7 May 2012 01:34:22 +0000 (+0200) Subject: Tests for module 'sh-quote'. X-Git-Tag: v0.1~695 X-Git-Url: http://erislabs.net/gitweb/?p=gnulib.git;a=commitdiff_plain;h=4a582acccd1429cee4fa3f5983ae65db0bf57cc4 Tests for module 'sh-quote'. * modules/sh-quote-tests: New file. * tests/test-sh-quote.c: New file. --- diff --git a/ChangeLog b/ChangeLog index c23333f09..cb1c8e888 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2012-05-06 Bruno Haible + Tests for module 'sh-quote'. + * modules/sh-quote-tests: New file. + * tests/test-sh-quote.c: New file. + +2012-05-06 Bruno Haible + sh-quote: Improve shell_quote_argv's signature. * lib/sh-quote.h (shell_quote_argv): Make argument array a 'const *'. * lib/sh-quote.c (shell_quote_argv): Likewise. diff --git a/modules/sh-quote-tests b/modules/sh-quote-tests new file mode 100644 index 000000000..c4a628624 --- /dev/null +++ b/modules/sh-quote-tests @@ -0,0 +1,10 @@ +Files: +tests/test-sh-quote.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-sh-quote +check_PROGRAMS += test-sh-quote diff --git a/tests/test-sh-quote.c b/tests/test-sh-quote.c new file mode 100644 index 000000000..8ca154121 --- /dev/null +++ b/tests/test-sh-quote.c @@ -0,0 +1,201 @@ +/* Test of sh-quote module. + Copyright (C) 2012 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 . */ + +/* Written by Bruno Haible , 2012. */ + +#include + +/* Specification. */ +#include "sh-quote.h" + +#include +#include + +#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 (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 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; +}