summaryrefslogtreecommitdiff
path: root/t/instspc.tap
blob: 0625a097c5ddeac57a5fb6e72e1f72a5cb794e5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
#! /bin/sh
# Copyright (C) 2010-2022 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 <https://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

: