gl/tests: new tests for func_quote* family

* gl/modules/funclib.sh-tests: New test module.
* gl/modules/all-shells-tests: New test (helper) module.
* gl/tests/test-funclib-quote.sh: New test case.
* gl/tests/test-all-shells.sh: New gl test helper.
* cfg.mk (sc_useless_braces_in_variable_derefs): Whitelist
new test-funclib-quote.sh as the pattern is used there
intentionally.
(sc_space_tab): Likewise.
(sc_useless_braces_in_variable_derefs): Remove /cvsu pattern as
the file is not used with git.
(sc_prohibit_command_in_subst): New checker.
This commit is contained in:
Pavel Raiskup 2015-10-31 14:33:18 +01:00
parent ed4f739f62
commit f323f10d2b
5 changed files with 320 additions and 4 deletions

14
cfg.mk
View File

@ -112,6 +112,13 @@ sc_prohibit_bracket_as_test:
halt="use 'if test' instead of 'if ['" \
$(_sc_search_regexp)
# : ${foo=`bar`} is not perfectly portable (see Shellology in autoconf's manual)
exclude_file_name_regexp--sc_prohibit_command_in_subst = ^cfg.mk$$
sc_prohibit_command_in_subst:
@prohibit='\$$\{[^`}]*`[^`]*`[^}]*}' \
halt='do not use `command` in $${ } substitution`' \
$(_sc_search_regexp)
# Check for quotes within backquotes within quotes "`"bar"`"
exclude_file_name_regexp--sc_prohibit_nested_quotes = ^cfg.mk$$
sc_prohibit_nested_quotes:
@ -238,7 +245,8 @@ define _sc_search_regexp_or_exclude
fi || :;
endef
exclude_file_name_regexp--sc_useless_braces_in_variable_derefs = /cvsu$$
exclude_file_name_regexp--sc_useless_braces_in_variable_derefs = \
test-funclib-quote.sh$$
sc_useless_braces_in_variable_derefs:
@prohibit='\$${[0-9A-Za-z_]+}[^0-9A-Za-z_]' \
halt='found spurious braces around variable dereference' \
@ -258,11 +266,9 @@ sc_useless_quotes_in_case:
$(_sc_search_regexp)
# List syntax-check exempted files.
exclude_file_name_regexp--sc_error_message_uppercase = \
^$(_build-aux)/cvsu$$
exclude_file_name_regexp--sc_prohibit_strcmp = \
^doc/libtool.texi$$
exclude_file_name_regexp--sc_prohibit_test_minus_ao = \
^m4/libtool.m4$$
exclude_file_name_regexp--sc_space_tab = \.diff$$
exclude_file_name_regexp--sc_space_tab = (\.diff|test-funclib-quote.sh)$$
exclude_file_name_regexp--sc_trailing_blank-non-rfc3676 = \.diff$$

View File

@ -0,0 +1,10 @@
Files:
tests/test-all-shells.sh
Depends-on:
funclib.sh
Makefile.am:
TESTS_ENVIRONMENT += \
abs_aux_dir='$(abs_aux_dir)' \
abs_srcdir='$(abs_srcdir)'

View File

@ -0,0 +1,12 @@
Files:
tests/test-funclib-quote.sh
Depends-on:
test-framework-sh
all-shells-tests
configure.ac:
Makefile.am:
TESTS += \
test-funclib-quote.sh

104
gl/tests/test-all-shells.sh Normal file
View File

@ -0,0 +1,104 @@
#! /bin/sh
# Unit test helper.
#
# Copyright (C) 2015 Free Software Foundation, Inc.
# This file is part of the GNUlib Library.
#
# 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/>. */
# This shell snippet (when sourced) tries to find as many /bin/sh compatible
# shells as possible on tested box -- and then re-executes the calling script
# in all of them. At the end, the default shell (/bin/sh usually) is also
# tested.
#
# To write compatible test-case, you usually need only those lines:
#
# #! /bin/sh
#
# all_shells_script=$0
# . "$abs_srcdir/test-all-shells.sh"
#
# your_check && all_shells_error "failed your_check"
#
# $all_shells_exit_cmd
# List of shells we try to check in.
: ${GL_ALL_SHELLS='ash bash dash ksh zsh busybox'}
# List of directories to search for the shell interpreter.
: ${GL_ALL_SHELLS_DIRS='/bin /sbin'}
# List of shell emulations to test with BusyBox.
: ${GL_ALL_SHELLS_BBE='sh ash'}
. "$abs_aux_dir"/funclib.sh || exit 1
all_shells_exit_cmd=:
: ${all_shells_script=false}
all_shells_error ()
{
$ECHO "error: $*" >&2
all_shells_exit_cmd=false
}
__notify_shell ()
{
$ECHO "== running in '$*' ==" >&2
}
__reexec_in_all_shells ()
{
for _G_dir in $GL_ALL_SHELLS_DIRS
do
for _G_shell in $GL_ALL_SHELLS
do
_G_abs_shell=$_G_dir/$_G_shell
test -f "$_G_abs_shell" || continue
case $_G_abs_shell in
*busybox)
for _G_bbe in $GL_ALL_SHELLS_BBE
do
_G_full_bb="$_G_abs_shell $_G_bbe"
__notify_shell "$_G_full_bb"
__GL_ALL_SHELLS_SHELL="$_G_full_bb" \
"$_G_abs_shell" "$_G_bbe" "$all_shells_script" ${1+"$@"} \
|| all_shells_error "can't run in $_G_bbe"
done
;;
*)
__notify_shell "$_G_abs_shell"
__GL_ALL_SHELLS_SHELL="$_G_abs_shell" \
"$_G_abs_shell" "$all_shells_script" ${1+"$@"} \
|| all_shells_error "can't run in $_G_abs_shell"
;;
esac
done
done
}
test x = "x$__GL_ALL_SHELLS_SHELL" \
&& __reexec_in_all_shells ${1+"$@"} \
&& __notify_shell "default shell"
:

184
gl/tests/test-funclib-quote.sh Executable file
View File

@ -0,0 +1,184 @@
#! /bin/sh
# Unit tests for funclib.sh
#
# Copyright (C) 2015 Free Software Foundation, Inc.
# This file is part of the GNUlib Library.
#
# 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/>. */
all_shells_script=$0
. "$abs_srcdir/test-all-shells.sh" || exit 1
_compare_or_error ()
{
_G_msg="strings differ:
a: $2
b: $3"
test "$2" = "$3" || all_shells_error "$_G_msg"
}
dump_args ()
{
dump_args_result=
_separator=
for arg
do
func_append dump_args_result "$_separator$arg"
_separator=' '
done
}
# test_q_eval DESC ARGs...
# ------------------------
# Apply 'func_quote eval' on ARGs and eval the result. The eval-ed result must
# 100% match the original ARGs.
test_q_eval ()
{
description="$1" ; shift
dump_args ${1+"$@"}
original=$dump_args_result
$ECHO "~> func_quote eval: $description: $original"
# Pretty implementation
func_quote eval,pretty ${1+"$@"} \
|| all_shells_error "can't pretty func_quote args '$*'"
eval "set dummy $func_quote_result" ; shift
dump_args ${1+"$@"}
pretty=$dump_args_result
# Fast implementation (if available)
func_quote eval ${1+"$@"} || all_shells_error "can't fast func_quote args '$*'"
eval "set dummy $func_quote_result" ; shift
dump_args ${1+"$@"}
fast=$dump_args_result
_compare_or_error "$description (pretty)" "$original" "$pretty"
_compare_or_error "$description (fast)" "$original" "$fast"
}
# test_q_arg_eval DESC ARG
# ------------------------
# Apply 'func_quote_arg eval' on ARG and eval the result. Echo-ed result within
# eval must match original echo-ed ARG.
test_q_arg_eval ()
{
description=$1
original=$2
original_echo=`$ECHO "$original"`
$ECHO "~> func_quote_arg eval: $description: $original_echo"
func_quote_arg pretty,unquoted "$original" \
|| all_shells_error "can't quote_arg: $original"
pretty=$func_quote_arg_result
pretty_unquoted=$func_quote_arg_unquoted_result
pretty_echo=`eval '$ECHO '"$pretty"` \
|| all_shells_error "can't eval: $pretty"
pretty_unquoted_echo=`eval '$ECHO '"\"$pretty_unquoted\""` \
|| all_shells_error "can't eval: $pretty"
# Fast implementation.
func_quote_arg eval "$original"
fast=$func_quote_arg_result
fast_echo=`eval '$ECHO '"$fast"` || all_shells_error "can't eval: $pretty"
_compare_or_error "$description (pretty)" \
"$original_echo" "$pretty_echo"
_compare_or_error "$description (pretty_unquoted)" \
"$original_echo" "$pretty_unquoted_echo"
_compare_or_error "$description (fast)" \
"$original_echo" "$fast_echo"
}
# test_q_expand DESC EXP_RESULT ARG
# ---------------------------------
# Test that 'func_quote expand' works fine --> all shell special characters are
# quoted except '$' -- while all variables are expanded.
test_q_expand ()
{
description=$1 ; shift
exp_result=$1 ; shift
dump_args ${1+"$@"}
$ECHO "~> func_quote expand: $description: $dump_args_result"
func_quote expand ${1+"$@"}
eval "set dummy $func_quote_result" ; shift
dump_args ${1+"$@"}
_compare_or_error "$description (expand)" "$exp_result" "$dump_args_result"
}
## ============== ##
## Start testing! ##
## ============== ##
aaa=aaa ; bbb=bbb ; ccc=ccc ; ddd=ddd
# Needed for later testing of globbing.
touch fltestA fltestB
test_q_eval basic a b c
# TODO: Intentionally not checking newline here yet, it never worked.
test_q_eval spaces 'space space' 'tab tab'
test_q_eval empty_arg '' '' ''
test_q_eval globs '*' '.*' '[a-zA-Z0-9_]' '?' '~'
test_q_eval variables '$aaa' '${bbb}' '"${ccc} $ddd"'
test_q_eval exclamation-mark '$!' '!$' '!'
test_q_eval tilde '"~"'
test_q_eval single-quotes "'a'" "'"'$bbb'"'"
test_q_eval shell-vars '$1' '$@' '$*' 'ending$'
test_q_eval complicated-cmd grep b '>' /noperm '<' /noperm
test_q_arg_eval basic a
test_q_arg_eval single-quotes "'''"
test_q_arg_eval double-quotes '"""'
test_q_arg_eval tilde '~'
test_q_arg_eval ampersand '&'
test_q_arg_eval pipe '|'
test_q_arg_eval questionmark 'fltest?'
test_q_arg_eval glob-bracket 'fltest[A-Z]'
test_q_arg_eval space 'space space'
test_q_arg_eval tab 'tab tab'
test_q_arg_eval '`command`' '`false command`'
test_q_arg_eval '$(command)' '$(false command)'
test_q_arg_eval semicolon '; false'
test_q_arg_eval vars '$aaa ${bbb} "${ccc} $ddd"'
test_q_arg_eval if-then-else 'if false; then false; else false; fi'
test_q_arg_eval file-redirect 'echo a > /no-perm 2> /no-perm'
test_q_arg_eval case-stmt 'case $empty in "") false;; a) broken ;; esac'
test_q_arg_eval comment 'unexistent #'
test_q_arg_eval func 'func () { } # syntax error'
test_q_expand basic 'a b c aaa d' a b c '$aaa' d
test_q_expand double-quotes '" " " "bbb"' '"' '" "' '"$bbb"'
test_q_expand spaces ' ccc' ' ' ' ' '${ccc}'
# Note the *no expected space* here!
test_q_expand non-existent '' '$empty' '${empty}'
test_q_expand non-existent-2 '"" ""' '"$empty"' '"${empty}"'
# TODO: Intentionally not checking '$(cmd)' yet.
test_q_expand '`command`' '`aaa bbb`' '`$aaa $empty${bbb}`'
$all_shells_exit_cmd && rm -rf fltest*