From: Pavel Raiskup Date: Sat, 31 Oct 2015 13:33:18 +0000 (+0100) Subject: gl/tests: new tests for func_quote* family X-Git-Tag: v2.4.7~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f323f10d2ba8b0ae55232a4beebb46b6f914a429;p=thirdparty%2Flibtool.git 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. --- diff --git a/cfg.mk b/cfg.mk index 6767b2d52..c04248f1a 100644 --- a/cfg.mk +++ b/cfg.mk @@ -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$$ diff --git a/gl/modules/all-shells-tests b/gl/modules/all-shells-tests new file mode 100644 index 000000000..e47a9439c --- /dev/null +++ b/gl/modules/all-shells-tests @@ -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)' diff --git a/gl/modules/funclib.sh-tests b/gl/modules/funclib.sh-tests new file mode 100644 index 000000000..80991c757 --- /dev/null +++ b/gl/modules/funclib.sh-tests @@ -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 diff --git a/gl/tests/test-all-shells.sh b/gl/tests/test-all-shells.sh new file mode 100644 index 000000000..d56c305b4 --- /dev/null +++ b/gl/tests/test-all-shells.sh @@ -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 . */ + + +# 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" + +: diff --git a/gl/tests/test-funclib-quote.sh b/gl/tests/test-funclib-quote.sh new file mode 100755 index 000000000..7669a44ba --- /dev/null +++ b/gl/tests/test-funclib-quote.sh @@ -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 . */ + + +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*