342 lines
10 KiB
Bash
342 lines
10 KiB
Bash
#! /bin/sh
|
||
# Copyright (C) 2010-2017 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 2, 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/>.
|
||
|
||
# Check that building from, or installing to, directories with shell
|
||
# metacharacters succeed.
|
||
# Original report from James Amundson about file names with spaces.
|
||
# Other characters added by Paul Eggert.
|
||
|
||
. test-init.sh
|
||
|
||
# Usage: is_in_list ITEM [LIST...]
|
||
is_in_list ()
|
||
{
|
||
item=$1; shift;
|
||
case " $* " in
|
||
*[\ \ ]"$item"[\ \ ]*) return 0;;
|
||
*) return 1;;
|
||
esac
|
||
}
|
||
|
||
# Helper subroutine for test data definition.
|
||
# Usage: define_problematic_string NAME STRING
|
||
define_problematic_string ()
|
||
{
|
||
tst=$1; shift
|
||
eval "instspc__$tst=\$1" \
|
||
|| fatal_ "define_problematic_string: bad argument: '$tst'"
|
||
shift
|
||
all_test_names_list="$all_test_names_list $tst"
|
||
# Some of the "problematic" characters cannot be used in the name of
|
||
# a build or install directory on a POSIX host. These lists should
|
||
# be empty, but are not due to limitations in Autoconf, Automake, Make,
|
||
# M4, or the shell.
|
||
if is_in_list fail-builddir "$@"; then
|
||
builddir_xfails="$builddir_xfails $tst"
|
||
fi
|
||
if is_in_list fail-destdir "$@"; then
|
||
destdir_xfails="$destdir_xfails $tst"
|
||
fi
|
||
}
|
||
|
||
# Be sure to avoid interferences from the environment.
|
||
all_test_names_list=''
|
||
builddir_xfails=''
|
||
destdir_xfails=''
|
||
|
||
expected_to_fail ()
|
||
{
|
||
case $1 in
|
||
build) is_in_list "$2" $builddir_xfails;;
|
||
dest) is_in_list "$2" $destdir_xfails;;
|
||
*) fatal_ "incorrect 'expected_to_fail' usage";;
|
||
esac
|
||
}
|
||
|
||
# Helper subroutines for creation of input data files.
|
||
create_input_data ()
|
||
{
|
||
mkdir sub
|
||
|
||
unindent >> configure.ac << 'EOF'
|
||
AC_PROG_CC
|
||
AM_PROG_AR
|
||
AC_PROG_RANLIB
|
||
AC_OUTPUT
|
||
EOF
|
||
|
||
: > sub/base.h
|
||
: > sub/nobase.h
|
||
: > sub/base.dat
|
||
: > sub/nobase.dat
|
||
: > sub/base.sh
|
||
: > sub/nobase.sh
|
||
|
||
unindent > source.c << 'EOF'
|
||
int
|
||
main (int argc, char **argv)
|
||
{
|
||
return 0;
|
||
}
|
||
EOF
|
||
|
||
unindent > Makefile.am << 'EOF'
|
||
foodir = $(prefix)/foo
|
||
fooexecdir = $(prefix)/foo
|
||
|
||
foo_HEADERS = sub/base.h
|
||
nobase_foo_HEADERS = sub/nobase.h
|
||
|
||
dist_foo_DATA = sub/base.dat
|
||
nobase_dist_foo_DATA = sub/nobase.dat
|
||
|
||
dist_fooexec_SCRIPTS = sub/base.sh
|
||
nobase_dist_fooexec_SCRIPTS = sub/nobase.sh
|
||
|
||
fooexec_PROGRAMS = sub/base
|
||
nobase_fooexec_PROGRAMS = sub/nobase
|
||
sub_base_SOURCES = source.c
|
||
sub_nobase_SOURCES = source.c
|
||
|
||
fooexec_LIBRARIES = sub/libbase.a
|
||
nobase_fooexec_LIBRARIES = sub/libnobase.a
|
||
sub_libbase_a_SOURCES = source.c
|
||
sub_libnobase_a_SOURCES = source.c
|
||
|
||
.PHONY: test-inst
|
||
test-inst: install
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/sub/nobase.h'
|
||
test ! -f '$(DESTDIR)/$(file)-prefix/foo/nobase.h'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/base.h'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/sub/nobase.dat'
|
||
test ! -f '$(DESTDIR)/$(file)-prefix/foo/nobase.dat'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/base.dat'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/sub/nobase.sh'
|
||
test ! -f '$(DESTDIR)/$(file)-prefix/foo/nobase.sh'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/base.sh'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/sub/nobase$(EXEEXT)'
|
||
test ! -f '$(DESTDIR)/$(file)-prefix/foo/nobase$(EXEEXT)'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/base$(EXEEXT)'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/sub/libnobase.a'
|
||
test ! -f '$(DESTDIR)/$(file)-prefix/foo/libnobase.a'
|
||
test -f '$(DESTDIR)/$(file)-prefix/foo/libbase.a'
|
||
EOF
|
||
|
||
$ACLOCAL || framework_failure_ "aclocal failed"
|
||
$AUTOCONF || framework_failure_ "autoconf failed"
|
||
$AUTOMAKE -a || framework_failure_ "automake failed"
|
||
}
|
||
|
||
# ================= #
|
||
# Test data begin #
|
||
# ----------------- #
|
||
|
||
# Some control characters that are white space.
|
||
bs='' # back space
|
||
cr='
|
||
' # carriage return
|
||
ff='' # form feed
|
||
ht=' ' # horizontal tab
|
||
lf='
|
||
' # line feed (aka newline)
|
||
|
||
# Hack to save typing and make code visually clearer.
|
||
def=define_problematic_string
|
||
|
||
$def squote \' fail-builddir fail-destdir
|
||
$def dquote '"' fail-builddir fail-destdir
|
||
$def bquote '`' fail-builddir fail-destdir
|
||
$def sharp '#' fail-builddir fail-destdir
|
||
$def dollar '$' fail-builddir fail-destdir
|
||
$def bang '!'
|
||
$def bslash '\' fail-builddir
|
||
$def ampersand '&' fail-builddir
|
||
$def percent '%'
|
||
$def leftpar '('
|
||
$def rightpar ')'
|
||
$def pipe '|'
|
||
$def caret '^'
|
||
$def tilde '~'
|
||
$def qmark '?'
|
||
$def star '*'
|
||
$def plus '+'
|
||
$def minus '-'
|
||
$def comma ','
|
||
$def colon ':'
|
||
$def semicol ';'
|
||
$def equal '='
|
||
$def less '<'
|
||
$def more '>'
|
||
$def at '@'
|
||
$def lqbrack '['
|
||
$def rqbrack ']'
|
||
$def lcbrack '{'
|
||
$def rcbrack '}'
|
||
$def space ' '
|
||
$def tab "$ht"
|
||
$def linefeed "$lf" fail-builddir fail-destdir
|
||
$def backspace "$bs"
|
||
$def formfeed "$ff"
|
||
$def carriageret "$cr"
|
||
$def quadrigraph0 '@&t@' fail-builddir
|
||
$def quadrigraph1 '@<:@'
|
||
$def quadrigraph2 '@:>@'
|
||
$def quadrigraph3 '@S|@'
|
||
$def quadrigraph4 '@%:@'
|
||
$def a_b 'a b'
|
||
$def a__b 'a b'
|
||
$def a_lf_b "a${lf}b" fail-builddir fail-destdir
|
||
$def dotdotdot '...'
|
||
$def dosdrive 'a:'
|
||
$def miscglob1 '?[a-z]*'
|
||
$def miscglob2 '.*?[0-9]'
|
||
|
||
unset def
|
||
|
||
# --------------- #
|
||
# Test data end #
|
||
# =============== #
|
||
|
||
# Allow the user to select a subset of the tests.
|
||
if test $# -gt 0; then
|
||
test_names_list=$*
|
||
for test_name in $test_names_list; do
|
||
case " $all_test_names_list " in
|
||
*" $test_name "*);;
|
||
*) fatal_ "invalid user-specified test_name '$test_name'"
|
||
esac
|
||
done
|
||
# We need to determine the TAP plan adaptively.
|
||
n=$(for t in $test_names_list; do echo $t; done | wc -l)
|
||
plan_ $(($n * 2)) # Two tests per "problematic string".
|
||
unset n
|
||
else
|
||
test_names_list=$all_test_names_list
|
||
# Prefer static TAP plan if possible, it minimizes the chance of errors.
|
||
plan_ 94
|
||
fi
|
||
|
||
ocwd=$(pwd) || fatal_ "getting current working directory"
|
||
|
||
create_input_data
|
||
|
||
for test_name in $test_names_list; do
|
||
|
||
eval "test_string=\${instspc__$test_name}" \
|
||
|| fatal_ "invalid test name: '$test_name'"
|
||
|
||
if test x"$test_string" = x; then
|
||
if test x"$test_name" != xcarriageret; then
|
||
fatal_ "invalid test name: '$test_name'"
|
||
else
|
||
# MSYS version 1.0.17 still mishandles carriage returns; see
|
||
# automake bug#7849.
|
||
skip_ -r "carriage-return treated as null char" "$test_name in builddir"
|
||
skip_ -r "carriage-return treated as null char" "$test_name in destdir"
|
||
continue
|
||
fi
|
||
fi
|
||
|
||
# Skip the next checks if this system doesn't support the required
|
||
# characters in file names.
|
||
|
||
mkdir "./$test_string" || {
|
||
skip_ -r "mkdir failed" "$test_name in builddir"
|
||
skip_ -r "mkdir failed" "$test_name in destdir"
|
||
continue
|
||
}
|
||
|
||
case $test_string in
|
||
*:*)
|
||
# On MSYS 1.0.17, "mkdir ./a:" creates ./a, and "cd ./a:" takes you
|
||
# to a strange directory with pwd equal to "a". But only for
|
||
# interactive shells. Or something? In this script, "cd ./a:" fails
|
||
# on MSYS. Marvelous.
|
||
( cd "./$test_string" ) || {
|
||
rmdir "./$test_string" || fatal_ "removing directory"
|
||
skip_ -r "cd failed" "$test_name in builddir"
|
||
skip_ -r "cd failed" "$test_name in destdir"
|
||
continue
|
||
}
|
||
;;
|
||
esac
|
||
|
||
# Where are the "weird" characters going to be used, in $(builddir)
|
||
# or in $(DESTDIR)? They are always going to be used in $(prefix)
|
||
# though; should we maybe separate this into a dedicated check?
|
||
for where in build dest; do
|
||
|
||
case $where in
|
||
build)
|
||
build=./$test_string
|
||
dest=$ocwd/dest-$test_name
|
||
;;
|
||
dest)
|
||
build=build-$test_name
|
||
# Also use $test_name in the definition of $dest, to avoid
|
||
# interferences among different tests in case $test_string
|
||
# is strangely munged (which is not unexpected, considering
|
||
# how tricky its characters are). With some shells, this
|
||
# has already happened (at least on OpenIndiana 11 and on
|
||
# Solaris 10).
|
||
dest=$ocwd/dest-$test_name/$test_string
|
||
mkdir "$build" || fatal_ "cannot create '$build'"
|
||
;;
|
||
*)
|
||
fatal_ "invalid where '$where'"
|
||
;;
|
||
esac
|
||
|
||
cd "$build" || fatal_ "cannot chdir into '$build'"
|
||
|
||
# Some make implementations eliminate leading and trailing whitespace
|
||
# from macros passed on the command line, and some eliminate leading
|
||
# whitespace from macros set from environment variables, so prepend
|
||
# './' and use the latter here.
|
||
r=ok
|
||
../configure --prefix "/$test_string-prefix" \
|
||
&& $MAKE all \
|
||
&& DESTDIR="$dest" file="./$test_string" $MAKE test-inst \
|
||
|| r='not ok'
|
||
|
||
description="$test_name in ${where}dir"
|
||
if expected_to_fail "$where" "$test_name"; then
|
||
directive=TODO
|
||
reason="long-standing limitation"
|
||
else
|
||
directive=
|
||
reason=
|
||
fi
|
||
# Test case outcome is here.
|
||
result_ "$r" -D "$directive" -r "$reason" -- "$description"
|
||
|
||
cd "$ocwd" || fatal_ "cannot chdir back to test directory"
|
||
|
||
# Remove subdirectories for tests that have passed, to avoid ending up
|
||
# with a too big test directory. This is especially important since
|
||
# some tests in this tests are expected to fail, and this will cause
|
||
# the test directory not to be removed when the script terminates.
|
||
if not am_keeping_testdirs && test "$r" = ok; then
|
||
rm_rf_ "$build" "$dest" || fatal_ "removing temporary subdirectory"
|
||
fi
|
||
|
||
: For shells with busted 'set -e'.
|
||
|
||
done # $instspc_action
|
||
|
||
done # $test_name
|
||
|
||
:
|