xref: /netbsd-src/tests/bin/sh/t_patterns.sh (revision 490e17a0c9f4cd8a5fee00bb61b57a8353af2a33)
1*490e17a0Skre# $NetBSD: t_patterns.sh,v 1.7 2023/05/11 10:08:34 kre Exp $
2bdc738b8Skre#
3bdc738b8Skre# Copyright (c) 2018 The NetBSD Foundation, Inc.
4bdc738b8Skre# All rights reserved.
5bdc738b8Skre#
6bdc738b8Skre# Redistribution and use in source and binary forms, with or without
7bdc738b8Skre# modification, are permitted provided that the following conditions
8bdc738b8Skre# are met:
9bdc738b8Skre# 1. Redistributions of source code must retain the above copyright
10bdc738b8Skre#    notice, this list of conditions and the following disclaimer.
11bdc738b8Skre# 2. Redistributions in binary form must reproduce the above copyright
12bdc738b8Skre#    notice, this list of conditions and the following disclaimer in the
13bdc738b8Skre#    documentation and/or other materials provided with the distribution.
14bdc738b8Skre#
15bdc738b8Skre# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16bdc738b8Skre# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17bdc738b8Skre# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18bdc738b8Skre# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19bdc738b8Skre# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20bdc738b8Skre# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21bdc738b8Skre# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22bdc738b8Skre# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23bdc738b8Skre# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24bdc738b8Skre# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25bdc738b8Skre# POSSIBILITY OF SUCH DAMAGE.
26bdc738b8Skre#
27bdc738b8Skre# the implementation of "sh" to test
28bdc738b8Skre: ${TEST_SH:=/bin/sh}
29bdc738b8Skre
30bdc738b8Skre#
31bdc738b8Skre# This file tests pattern matching (glob)
32bdc738b8Skre#
33bdc738b8Skre# Three forms:
34bdc738b8Skre#	standard filename expansion (echo *.c)
35bdc738b8Skre#	case statements (case word in (*.c) ...;;)
36bdc738b8Skre#	var expansions with substring matching ${var%*.c}
37bdc738b8Skre#
38bdc738b8Skre# Note: the emphasis here is on testing the various possible patterns,
39bdc738b8Skre# not that case statements, or var expansions (etc) work in general.
40bdc738b8Skre
41bdc738b8Skre### Helper functions
42bdc738b8Skre
43bdc738b8Skrenl='
44bdc738b8Skre'
45bdc738b8Skrereset()
46bdc738b8Skre{
47bdc738b8Skre	TEST_NUM=0
48bdc738b8Skre	TEST_FAILURES=''
49bdc738b8Skre	TEST_FAIL_COUNT=0
50bdc738b8Skre	TEST_ID="$1"
51bdc738b8Skre}
52bdc738b8Skre
53bdc738b8Skre# Test run & validate.
54bdc738b8Skre#
55bdc738b8Skre#	$1 is the command to run (via sh -c)
56bdc738b8Skre#	$2 is the expected output (with any \n's in output replaced by spaces)
57bdc738b8Skre#	$3 is the expected exit status from sh
58bdc738b8Skre#
59bdc738b8Skre# Stderr is exxpected to be empty, unless the expected exit code ($3) is != 0
60bdc738b8Skre# in which case some message there is expected (and nothing is a failure).
61bdc738b8Skre# When non-zero exit is expected, we note a different (non-zero) value
62bdc738b8Skre# observed, but do not fail the test because of that.
63bdc738b8Skre
64bdc738b8Skrecheck()
65bdc738b8Skre{
66bdc738b8Skre	fail=false
67bdc738b8Skre	# Note TEMP_FILE must not be in the current directory (or nearby).
68bdc738b8Skre	TEMP_FILE=$( mktemp /tmp/OUT.XXXXXX )
69bdc738b8Skre	TEST_NUM=$(( $TEST_NUM + 1 ))
70bdc738b8Skre	MSG=
71bdc738b8Skre
72bdc738b8Skre	# our local shell (ATF_SHELL) better do quoting correctly...
73bdc738b8Skre	# some of the tests expect us to expand $nl internally...
74bdc738b8Skre	CMD="$1"
75bdc738b8Skre
76bdc738b8Skre	result="$( ${TEST_SH} -c "${CMD}" 2>"${TEMP_FILE}" )"
77bdc738b8Skre	STATUS=$?
78bdc738b8Skre
79bdc738b8Skre	if [ "${STATUS}" -ne "$3" ]; then
80bdc738b8Skre		MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
81bdc738b8Skre		MSG="${MSG} expected exit code $3, got ${STATUS}"
82bdc738b8Skre
83bdc738b8Skre		# don't actually fail just because of wrong exit code
84bdc738b8Skre		# unless we either expected, or received "good"
85bdc738b8Skre		# or something else is detected as incorrect as well.
86bdc738b8Skre		case "$3/${STATUS}" in
87bdc738b8Skre		(*/0|0/*) fail=true;;
88bdc738b8Skre		esac
89bdc738b8Skre	fi
90bdc738b8Skre
91bdc738b8Skre	if [ "$3" -eq 0 ]; then
92bdc738b8Skre		if [ -s "${TEMP_FILE}" ]; then
93bdc738b8Skre			MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
94bdc738b8Skre			MSG="${MSG} Messages produced on stderr unexpected..."
95bdc738b8Skre			MSG="${MSG}${nl}$( cat "${TEMP_FILE}" )"
96bdc738b8Skre			fail=true
97bdc738b8Skre		fi
98bdc738b8Skre	else
99bdc738b8Skre		if ! [ -s "${TEMP_FILE}" ]; then
100bdc738b8Skre			MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
101bdc738b8Skre			MSG="${MSG} Expected messages on stderr,"
102bdc738b8Skre			MSG="${MSG} nothing produced"
103bdc738b8Skre			fail=true
104bdc738b8Skre		fi
105bdc738b8Skre	fi
106bdc738b8Skre	rm -f "${TEMP_FILE}"
107bdc738b8Skre
108bdc738b8Skre	case "${result}" in
109bdc738b8Skre	(*[!0-9" 	$nl"]*)
110bdc738b8Skre		# A word of some kind: at least 1 char that is not digit or wsp
111bdc738b8Skre		# Remove newlines (use local shell for this)
112bdc738b8Skre		result="$(
113bdc738b8Skre			set -f
114bdc738b8Skre			IFS="$nl"
115bdc738b8Skre			set -- $result
116bdc738b8Skre			IFS=' '
117bdc738b8Skre			printf '%s' "$*"
118bdc738b8Skre		)"
119bdc738b8Skre		;;
120bdc738b8Skre	(*[0-9]*)
121bdc738b8Skre		# a numeric result, return just the number, trim whitespace
122bdc738b8Skre		result=$(( ${result} ))
123bdc738b8Skre		;;
124bdc738b8Skre	(*)
125bdc738b8Skre		# whitespace only, or empty string: just leave it as is
126bdc738b8Skre		;;
127bdc738b8Skre	esac
128bdc738b8Skre
129bdc738b8Skre	if [ "$2" != "${result}" ]
130bdc738b8Skre	then
131bdc738b8Skre		MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
132bdc738b8Skre		MSG="${MSG} Expected output '$2', received '$result'"
133bdc738b8Skre		fail=true
134bdc738b8Skre	fi
135bdc738b8Skre
136bdc738b8Skre	if $fail
137bdc738b8Skre	then
138bdc738b8Skre		MSG="${MSG}${MSG:+${nl}}[$TEST_NUM]"
139bdc738b8Skre		MSG="${MSG} Full command: <<${CMD}>>"
140bdc738b8Skre	fi
141bdc738b8Skre
142bdc738b8Skre	$fail && test -n "$TEST_ID" && {
143bdc738b8Skre		TEST_FAILURES="${TEST_FAILURES}${TEST_FAILURES:+${nl}}"
144bdc738b8Skre		TEST_FAILURES="${TEST_FAILURES}${TEST_ID}[$TEST_NUM]:"
145bdc738b8Skre		TEST_FAILURES="${TEST_FAILURES} Test of '$1' failed.";
146bdc738b8Skre		TEST_FAILURES="${TEST_FAILURES}${nl}${MSG}"
147bdc738b8Skre		TEST_FAIL_COUNT=$(( $TEST_FAIL_COUNT + 1 ))
148bdc738b8Skre		return 0
149bdc738b8Skre	}
150bdc738b8Skre	$fail && atf_fail "Test[$TEST_NUM] failed: $(
151bdc738b8Skre	    # ATF does not like newlines in messages, so change them...
152bdc738b8Skre		    printf '%s' "${MSG}" | tr '\n' ';'
153bdc738b8Skre	    )"
154bdc738b8Skre	return 0
155bdc738b8Skre}
156bdc738b8Skre
157bdc738b8Skreresults()
158bdc738b8Skre{
159bdc738b8Skre	test -n "$1" && atf_expect_fail "$1"
160bdc738b8Skre
161bdc738b8Skre	test -z "${TEST_ID}" && return 0
162bdc738b8Skre	test -z "${TEST_FAILURES}" && return 0
163bdc738b8Skre
164bdc738b8Skre	echo >&2 "=========================================="
165bdc738b8Skre	echo >&2 "While testing '${TEST_ID}'"
166bdc738b8Skre	echo >&2 " - - - - - - - - - - - - - - - - -"
167bdc738b8Skre	echo >&2 "${TEST_FAILURES}"
168bdc738b8Skre
169bdc738b8Skre	atf_fail \
170bdc738b8Skre "Test ${TEST_ID}: $TEST_FAIL_COUNT (of $TEST_NUM) subtests failed - see stderr"
171bdc738b8Skre}
172bdc738b8Skre
173bdc738b8Skre####### End helpers
174bdc738b8Skre
175bdc738b8Skreatf_test_case filename_expansion
1767cb4398aSgutteridgefilename_expansion_head() {
177bdc738b8Skre	atf_set descr "Test correct operation of filename expansion"
178bdc738b8Skre}
179bdc738b8Skrefilename_expansion_body() {
180bdc738b8Skre	atf_require_prog mktemp
181bdc738b8Skre	atf_require_prog wc
182bdc738b8Skre	atf_require_prog mv
183bdc738b8Skre	atf_require_prog rm
184bdc738b8Skre	atf_require_prog mkdir
185d903b87aSmartin	atf_require_prog df
186d903b87aSmartin	atf_require_prog awk
187bdc738b8Skre
188bdc738b8Skre	reset filename_expansion
189bdc738b8Skre
190bdc738b8Skre	# First create a known set of filenames to match against
191bdc738b8Skre
192bdc738b8Skre	# Note: This creates almost 17000 files/directories, so
193bdc738b8Skre	# needs at least that many free inodes (only space consumed
194bdc738b8Skre	# is for the directory contents, with a 1K frag size, it
195bdc738b8Skre	# should be about 1.2MiB).  Switching to making links would
196bdc738b8Skre	# save inodes, but would require running "ln" many times, so
197bdc738b8Skre	# would be a lot slower.
198bdc738b8Skre
199d903b87aSmartin	free_inodes=$( df -i . | awk '/^Filesystem/{next}; { print $7 }' )
200d903b87aSmartin	if [ $free_inodes -lt 17000 ]; then
201d903b87aSmartin		atf_skip "not enough space"
202d903b87aSmartin	fi
203d903b87aSmartin
204bdc738b8Skre	# This should work on a case insensitive, but preserving,
205bdc738b8Skre	# filesystem - but case sensitive filesystems are preferred.
206bdc738b8Skre
207bdc738b8Skre	D=$(mktemp -d "DIR.$$.XXXXXX") || atf_fail "mktemp -d failed"
208bdc738b8Skre	cd "${D}" || atf_fail "cd to temp dir '$D' failed"
209bdc738b8Skre
210bdc738b8Skre	# we need another level of directory, so we know what
211bdc738b8Skre	# files to expect in ".." (ie: in $D) - only ".D".
212bdc738b8Skre	mkdir .D && cd .D || atf_fail "failed to make or enter .D in $D"
213bdc738b8Skre
214bdc738b8Skre	> Xx || atf_fail "Unable to make files in temporary directory"
215bdc738b8Skre	case "$( printf '%s\n' *)" in
216bdc738b8Skre		(Xx) rm Xx || atf_fail "Unable to delete file";;
217bdc738b8Skre		(\*) atf_fail "Created file vanished";;
218bdc738b8Skre		(xx|XX|xX) atf_skip "Case preserving filesystem required";;
219bdc738b8Skre		(*) atf_fail "Unexpected file expansion for '*'";;
220bdc738b8Skre	esac
221bdc738b8Skre
222bdc738b8Skre	# from here on we make files/directories that we will be
223bdc738b8Skre	# using in the tests.
224bdc738b8Skre
225bdc738b8Skre	# CAUTION: Change *any* of this and the expected results from the
226bdc738b8Skre	# tests will all need verifying and updating as well.
227bdc738b8Skre
228bdc738b8Skre	mkdir D || atf_fail "mkdir D failed"
229bdc738b8Skre
230bdc738b8Skre	for F in a b c e V W X Y 1 2 3 4 5 \\ \] \[ \* \? \- \! \^ \| \# \' \"
231bdc738b8Skre	do
232bdc738b8Skre		> "${F}"
233bdc738b8Skre		> ".${F}"
234bdc738b8Skre		> "${F}.${F}"
235bdc738b8Skre		> "${F}-${F}"
236bdc738b8Skre		> "${F}${F}${F}${F}"
237bdc738b8Skre		> "x${F}z"
238bdc738b8Skre		> ab"${F}"yz
239bdc738b8Skre		> "m${F}n${F}p${F}q"
240bdc738b8Skre
241bdc738b8Skre		> "D/${F}"
242bdc738b8Skre		> "D/.${F}"
243bdc738b8Skre		> "D/${F}${F}${F}${F}"
244bdc738b8Skre
245bdc738b8Skre		mkdir "D${F}" || atf_fail "mkdir 'D${F}' failed"
246bdc738b8Skre		mkdir ".D${F}" || atf_fail "mkdir '.D${F}' failed"
247bdc738b8Skre
248bdc738b8Skre		for G in a b c e W X Y 0 2 4 6 \\ \] \[ \* \? \- \! \^ \| \#
249bdc738b8Skre		do
250bdc738b8Skre			> "${F}${G}"
251bdc738b8Skre			> "${F}${G}${G}"
252bdc738b8Skre			> "${F}${G}${F}"
253bdc738b8Skre			> "${G}${F}${G}"
254bdc738b8Skre			> "${F}${G}${G}${F}"
255bdc738b8Skre			> "${G}${F}${F}${G}"
256bdc738b8Skre			> "${F}.${G}"
257bdc738b8Skre			> "${F}${G}.${G}${G}"
258bdc738b8Skre			> "${F}${G}${F}${G}.${G}"
259bdc738b8Skre			> "x${F}${G}y"
260bdc738b8Skre			> "${F}z${G}"
261bdc738b8Skre			> "${G}zz${F}"
262bdc738b8Skre			> "${G}+${G}"
263bdc738b8Skre
264bdc738b8Skre			> "D${F}/${G}"
265bdc738b8Skre			> "D${F}/.${G}"
266bdc738b8Skre			> "D${F}/${G}${F}${G}"
267bdc738b8Skre			> "D${F}/.${G}${F}${G}"
268bdc738b8Skre
269bdc738b8Skre			> ".D${F}/${G}"
270bdc738b8Skre			> ".D${F}/.${G}"
271bdc738b8Skre			> ".D${F}/${G}${F}${G}"
272bdc738b8Skre			> ".D${F}/.${G}${F}${G}"
273bdc738b8Skre
274bdc738b8Skre			mkdir "D${F}/D${G}" "D${F}/D${F}${G}" ||
275bdc738b8Skre				atf_fail \
276bdc738b8Skre			    "subdir mkdirs failed D${F}/D${G} D${F}/D${F}${G}"
277bdc738b8Skre
278bdc738b8Skre			> "D${F}/D${G}/${G}"
279bdc738b8Skre			> "D${F}/D${G}.${G}"
280bdc738b8Skre			> "D${F}/D${G}/${F}${G}"
281bdc738b8Skre			> "D${F}/D${G}/${G}${F}${G}"
282bdc738b8Skre			> "D${F}/D${G}/.${G}${F}${G}"
283bdc738b8Skre			> "D${F}/D${G}/.${G}${F}${G}"
284bdc738b8Skre
285bdc738b8Skre			> "D${F}/D${F}${G}/${G}"
286bdc738b8Skre			> "D${F}/D${F}${G}.${G}"
287bdc738b8Skre			> "D${F}/D${F}${G}/${G}${F}"
288bdc738b8Skre			> "D${F}/D${F}${G}/${G}${G}${F}"
289bdc738b8Skre			> "D${F}/D${F}${G}/.${F}${F}${G}"
290bdc738b8Skre			> "D${F}/D${F}${G}/.${G}${F}${F}"
291bdc738b8Skre
292bdc738b8Skre		done
293bdc738b8Skre	done
294bdc738b8Skre
295bdc738b8Skre	# Debug hooks ... run with environment var set to filename
296bdc738b8Skre
297bdc738b8Skre	case "${ATF_TEST_SAVE_FILENAMES}" in
298bdc738b8Skre	'')	;;
299bdc738b8Skre	/*)	ls -R >"${ATF_TEST_SAVE_FILENAMES}" ;;
300bdc738b8Skre	*)	ls -R >"${TMPDIR:-/tmp}/${ATF_TEST_SAVE_FILENAMES}" ;;
301bdc738b8Skre	esac
302bdc738b8Skre	case "${ATF_TEST_SAVE_FILES}" in
303bdc738b8Skre	'')	;;
304*490e17a0Skre	/*)	(cd ..; tar cf "${ATF_TEST_SAVE_FILES}" .D) ;;
305*490e17a0Skre	*)	(cd ..; tar cf "${TMPDIR:-/tmp}/${ATF_TEST_SAVE_FILES}" .D) ;;
306bdc738b8Skre	esac
307bdc738b8Skre
308bdc738b8Skre	# Now we have lots of files, try some matching
309bdc738b8Skre
310bdc738b8Skre	# First just check that "printf | wc -l" works properly...
311bdc738b8Skre	check 'printf "%s\n" 1 2 3 | wc -l'		'3'	0	#1
312bdc738b8Skre
313bdc738b8Skre	# Next a whole bunch of elementary patterns
314bdc738b8Skre	check 'printf "%s\n" ab* | wc -l'		'31'	0
315bdc738b8Skre	check 'printf "%s\n" x*y | wc -l'		'525'	0
316bdc738b8Skre	check 'printf "%s\n" * | wc -l'			'5718'	0
317bdc738b8Skre	check 'printf "%s\n" ? | wc -l'			'26'	0	#5
318bdc738b8Skre	check 'printf "%s\n" ?? | wc -l'		'550'	0
319bdc738b8Skre	check 'printf "%s\n" ??? | wc -l'		'2297'	0
320bdc738b8Skre	check 'printf "%s\n" ???? | wc -l'		'1745'	0
321bdc738b8Skre	check 'printf "%s\n" ????? | wc -l'		'550'	0
322bdc738b8Skre
323bdc738b8Skre	check 'printf "%s\n" ?????? | wc -l'		'525'	0	#10
324bdc738b8Skre	check 'printf "%s\n" ??????? | wc -l'		'25'	0
325bdc738b8Skre	check 'printf "%s\n" ???????? | wc -l'		'1'	0
326bdc738b8Skre	check 'printf "%s\n" ????????'			'????????'	0
327bdc738b8Skre	check 'printf "%s\n" m* | wc -l'		'25'	0
328bdc738b8Skre	check 'printf "%s\n" -* | wc -l'		'206'	0	#15
329bdc738b8Skre	check 'printf "%s\n" *- | wc -l'		'227'	0
330bdc738b8Skre	check 'printf "%s\n" -? | wc -l'		'21'	0
331bdc738b8Skre	check 'printf "%s\n" ?- | wc -l'		'26'	0
332bdc738b8Skre	check 'printf "%s\n" [ab] | wc -l'		'2'	0
333bdc738b8Skre
334bdc738b8Skre	check 'printf "%s\n" [ab]* | wc -l'		'437'	0	#20
335bdc738b8Skre	check 'printf "%s\n" [A-Z]* | wc -l'		'815'	0
336bdc738b8Skre	check 'printf "%s\n" [0-4]* | wc -l'		'830'	0
337bdc738b8Skre	check 'printf "%s\n" [-04]* | wc -l'		'488'	0
338bdc738b8Skre	check 'printf "%s\n" [40-]* | wc -l'		'488'	0
339bdc738b8Skre	check 'printf "%s\n" *[0-9] | wc -l'		'1057'	0	#25
340bdc738b8Skre	check 'printf "%s\n" *[0-9]* | wc -l'		'2109'	0
341bdc738b8Skre	check 'printf "%s\n" ?[0-9]* | wc -l'		'855'	0
342bdc738b8Skre	check 'printf "%s\n" ?[0-9]? | wc -l'		'270'	0
343bdc738b8Skre	check 'printf "%s\n" *[0-9]? | wc -l'		'750'	0
344bdc738b8Skre
345bdc738b8Skre	check 'printf "%s\n" [a-c][0-9]? | wc -l'	'33'	0	#30
346bdc738b8Skre	check 'printf "%s\n" [[:alpha:]] | wc -l'	'9'	0
347bdc738b8Skre	check 'printf "%s\n" [[:alpha:][:digit:]] | wc -l' '14'	0
348bdc738b8Skre	check 'printf "%s\n" [[:alpha:]][[:digit:]] | wc -l' '37' 0
349bdc738b8Skre	check								    \
350bdc738b8Skre	   'printf "%s\n" [[:alpha:][:digit:]][[:alpha:][:digit:]] | wc -l' \
351bdc738b8Skre							'156'	0
352bdc738b8Skre	check 'printf "%s\n" D*/*a | wc -l'		'152'	0	#35
353bdc738b8Skre	check 'printf "%s\n" D?/*a | wc -l'		'150'	0
354bdc738b8Skre	check 'printf "%s\n" D*/?a | wc -l'		'25'	0
355bdc738b8Skre	check 'printf "%s\n" D?/?a | wc -l'		'25'	0
356bdc738b8Skre	check 'printf "%s\n" */*a | wc -l'		'152'	0
357bdc738b8Skre
358bdc738b8Skre	check 'printf "%s\n" [A-Z]*/*a | wc -l'		'152'	0	#40
359bdc738b8Skre	check 'printf "%s\n" ??/*a | wc -l'		'150'	0
360bdc738b8Skre	check 'printf "%s\n" .*/*a | wc -l'		'277'	0
361bdc738b8Skre	check 'printf "%s\n" .?*/*a | wc -l'		'50'	0
362bdc738b8Skre	check 'printf "%s\n" *-/-* | wc -l'		'2'	0
363bdc738b8Skre	check 'printf "%s\n" *-/-*'		'D-/- D-/---'	0	#45
364bdc738b8Skre
365bdc738b8Skre	# now some literal magic chars
366bdc738b8Skre	check 'printf "%s\n" \?* | wc -l'		'206'	0
367bdc738b8Skre	check 'printf "%s\n" *\?* | wc -l'		'471'	0
368bdc738b8Skre	check 'printf "%s\n" \*? | wc -l'		'21'	0
369bdc738b8Skre	check 'printf "%s\n" \** | wc -l'		'206'	0
370bdc738b8Skre
371bdc738b8Skre	check 'printf "%s\n" *\?* | wc -l'		'471'	0	#50
372bdc738b8Skre	check 'printf "%s\n" \[?] | wc -l'		'3'	0
373bdc738b8Skre	check 'printf "%s\n" \[?]'		'[.] []] [z]'	0
374bdc738b8Skre	check 'printf "%s\n" *\[* | wc -l'		'471'	0
375bdc738b8Skre	check 'printf "%s\n" \?\?* | wc -l'		'5'	0
376bdc738b8Skre	check 'printf "%s\n" \?\?*'	'?? ??.?? ??? ???? ????.?' 0	#55
377bdc738b8Skre	check 'printf "%s\n" [A\-C]* | wc -l'		'206'	0
378bdc738b8Skre	check 'printf "%s\n" [-AC]* | wc -l'		'206'	0
379bdc738b8Skre	check 'printf "%s\n" [CA-]* | wc -l'		'206'	0
380bdc738b8Skre	check 'printf "%s\n" [A\]-]? | wc -l'		'42'	0
381bdc738b8Skre
382bdc738b8Skre	check 'printf "%s\n" []A\-]? | wc -l'		'42'	0	#60
383bdc738b8Skre	check 'printf "%s\n" []A-]? | wc -l'		'42'	0
384bdc738b8Skre	check 'printf "%s\n" \\* | wc -l'		'206'	0
385bdc738b8Skre	check 'printf "%s\n" [[-\]]?\?* | wc -l'	'12'	0
386bdc738b8Skre	check 'printf "%s\n" []\\[]?\? | wc -l'		'9'	0
387bdc738b8Skre	check 'printf "%s\n" *\\\\ | wc -l'		'52'	0	#65
388bdc738b8Skre	check 'printf "%s\n" [*][?]* | wc -l'		'6'	0
389bdc738b8Skre	check 'printf "%s\n" "*?"* | wc -l'		'6'	0
390bdc738b8Skre	check "printf '%s\\n' '\\'*\\\\ | wc -l"	'61'	0
391bdc738b8Skre	check 'printf "%s\n" ["a-b"]* | wc -l'		'643'	0
392bdc738b8Skre
393bdc738b8Skre	check 'printf "%s\n" ["A-C"]z[[] | wc -l'	'1'	0	#70
394bdc738b8Skre	check 'printf "%s\n" ["A-C"]z[[]'		'-z['	0
395bdc738b8Skre	check 'printf "%s\n" ?"??"* | wc -l'		'54'	0
396bdc738b8Skre	check 'printf "%s\n" \??\?* | wc -l'		'52'	0
397bdc738b8Skre	check 'printf "%s\n" [?][\?]* | wc -l'		'5'	0
398bdc738b8Skre	check 'printf "%s\n" [?][\?]*'	'?? ??.?? ??? ???? ????.?' 0	#75
399bdc738b8Skre	check 'printf "%s\n" [!ab] | wc -l'		'24'	0
400bdc738b8Skre	check 'printf "%s\n" [!ab]* | wc -l'		'5281'	0
401bdc738b8Skre	check 'printf "%s\n" [!A-D]* | wc -l'		'5692'	0
402bdc738b8Skre	check 'printf "%s\n" [!0-3]* | wc -l'		'5094'	0
403bdc738b8Skre
404bdc738b8Skre	check 'printf "%s\n" [!-03]* | wc -l'		'5265'	0	#80
405bdc738b8Skre	check 'printf "%s\n" [!30-]* | wc -l'		'5265'	0
406bdc738b8Skre	check 'printf "%s\n" [!0\-3]* | wc -l'		'5265'	0
407bdc738b8Skre	check 'printf "%s\n" [\!0-3]* | wc -l'		'830'	0
408bdc738b8Skre	check 'printf "%s\n" [0-3!]* | wc -l'		'830'	0
409bdc738b8Skre	check 'printf "%s\n" [0!-3]* | wc -l'		'1790'	0	#85
410bdc738b8Skre	check 'printf "%s\n" *[!0-3] | wc -l'		'5156'	0
411bdc738b8Skre	check 'printf "%s\n" *[!0-3]* | wc -l'		'5680'	0
412bdc738b8Skre	check 'printf "%s\n" ?[!0-3]* | wc -l'		'5231'	0
413bdc738b8Skre	check 'printf "%s\n" ?[!0-3]? | wc -l'		'2151'	0
414bdc738b8Skre
415bdc738b8Skre	check 'printf "%s\n" *[!0-3]? | wc -l'		'5284'	0	#90
416bdc738b8Skre	check 'printf "%s\n" [!a-c][!0-3]? | wc -l'	'1899'	0
417bdc738b8Skre	check 'printf "%s\n" [![:alpha:]] | wc -l'	'17'	0
418bdc738b8Skre	check 'printf "%s\n" [![:alpha:][:digit:]] | wc -l' '12' 0
419bdc738b8Skre	check 'printf "%s\n" [![:alpha:]][[:digit:]] | wc -l'	'68' 0
420bdc738b8Skre	check 'printf "%s\n" [[:alpha:]][![:digit:]] | wc -l'	'156' 0	#95
421bdc738b8Skre	check 'printf "%s\n" [![:alpha:]][![:digit:]] | wc -l'	'289' 0
422bdc738b8Skre	check 'printf "%s\n" [!A-Z]*/*a | wc -l'	'1'	0
423bdc738b8Skre	check 'printf "%s\n" [!A-Z]*/*a'	'[!A-Z]*/*a'	0
424bdc738b8Skre	check 'printf "%s\n" [!A\-D]* | wc -l'		'5486'	0
425bdc738b8Skre
426bdc738b8Skre	check 'printf "%s\n" [!-AD]* | wc -l'		'5486'	0	#100
427bdc738b8Skre	check 'printf "%s\n" [!DA-]* | wc -l'		'5486'	0
428bdc738b8Skre	check 'printf "%s\n" [!A\]-]? | wc -l'		'508'	0
429bdc738b8Skre	check 'printf "%s\n" [!]A\-]? | wc -l'		'508'	0
430bdc738b8Skre	check 'printf "%s\n" [!]A-]? | wc -l'		'508'	0
431bdc738b8Skre	check 'printf "%s\n" [![-\]]?\?* | wc -l'	'164'	0	#105
432bdc738b8Skre	check 'printf "%s\n" [!]\\[]?\? | wc -l'	'93'	0
433bdc738b8Skre	check 'printf "%s\n" [!*][?]* | wc -l'		'171'	0
434bdc738b8Skre	check 'printf "%s\n" [*][!?]* | wc -l'		'199'	0
435bdc738b8Skre	check 'printf "%s\n" [!*][!?]* | wc -l'		'5316'	0
436bdc738b8Skre
437bdc738b8Skre	check 'printf "%s\n" [!"a-b"]* | wc -l'		'5075'	0	#110
438bdc738b8Skre	check 'printf "%s\n" ["!a-b"]* | wc -l'		'849'	0
439bdc738b8Skre	check 'printf "%s\n" [!"A-D"]z[[] | wc -l'	'24'	0
440bdc738b8Skre	check 'printf "%s\n" ["!A-D"]z[[] | wc -l'	'2'	0
441bdc738b8Skre	check 'printf "%s\n" ["!A-D"]z[[]'	'!z[ -z['	0
442bdc738b8Skre	check 'printf "%s\n" ["A-D"]z[![] | wc -l'	'20'	0	#115
443bdc738b8Skre	check 'printf "%s\n" [!"A-D"]z[![] | wc -l'	'480'	0
444bdc738b8Skre	check 'printf "%s\n" ["!A-D"]z[![] | wc -l'	'40'	0
445bdc738b8Skre	check 'printf "%s\n" [!?][\?]* | wc -l'		'172'	0
446bdc738b8Skre	check 'printf "%s\n" [?][!\?]* | wc -l'		'200'	0
447bdc738b8Skre
448bdc738b8Skre	check 'printf "%s\n" [!?][!\?]* | wc -l'	'5315'	0	#120
449bdc738b8Skre	check 'printf "%s\n" [!?][?!]* | wc -l'		'343'	0
450bdc738b8Skre	check 'printf "%s\n" [?][\?!]* | wc -l'		'11'	0
451bdc738b8Skre	check "printf '%s\\n' [\']*[!#] | wc -l"	'164'	0
452bdc738b8Skre	check 'printf "%s\n" [\"]*[\|] | wc -l'		'6'	0
453bdc738b8Skre	check 'printf "%s\n" [\"]*[\|]' '".| "z| "| "|"|.| "|.|| "||' 0	#125
454bdc738b8Skre	check "printf '%s\\n' '\"['* | wc -l"		'6'	0
455bdc738b8Skre	check "printf '%s\\n' '\"['*" '"[ "[" "["[.[ "[.[[ "[[ "[["' 0
456bdc738b8Skre
457bdc738b8Skre	# Now test cases where the pattern is the result of a
458bdc738b8Skre	# variable expansion (will assume, for now, that cmdsub & arith
459bdc738b8Skre	# work the same way, so omit tests using those)
460bdc738b8Skre	# we need to check both unquoted & quoted var expansions,
461bdc738b8Skre	# expansions that result from ${xxx-xxx} and ${xxx%yyy}
462bdc738b8Skre	# and expansions that form just part of the eventual pattern.
463bdc738b8Skre
464bdc738b8Skre	check 'var="x*y";printf "%s\n" ${var} | wc -l'	'525'	0
465bdc738b8Skre	check 'var="[a-e]?[0-9]";printf "%s\n" ${var} | wc -l' '48' 0
466bdc738b8Skre
467bdc738b8Skre	check 'var="[a-e]?.*";printf "%s\n" ${var} | wc -l' '84' 0	#130
468bdc738b8Skre	check 'var="[a-e]\?.*";printf "%s\n" ${var} | wc -l' '4' 0
469bdc738b8Skre	check 'var="[a-e]\?.*";printf "%s\n" ${var}' 'a?.?? b?.?? c?.?? e?.??' 0
470bdc738b8Skre
471bdc738b8Skre	# and if you're looking for truly weird...
472bdc738b8Skre
473bdc738b8Skre	check 'set -- a b; IFS=\?; printf "%s\n" "$*" | wc -l' '1' 0
474bdc738b8Skre	check 'set -- a b; IFS=\?; printf "%s\n" "$*"'	'a?b'	0
475bdc738b8Skre	check 'set -- a b; IFS=\?; printf "%s\n" $* | wc -l' '2' 0 #boring #135
476bdc738b8Skre	check 'set -- a b; IFS=\?; var=$*; unset IFS; printf "%s\n" ${var}' \
477bdc738b8Skre						'a.b abb azb'	0
478bdc738b8Skre	check 'set -- a b; IFS=\?; var=$*; unset IFS; printf "%s\n" "${var}"' \
479bdc738b8Skre						'a?b'	0
480bdc738b8Skre	check 'set -- a \?; IFS=\\; printf "%s\n" "$*"'	'a\?'	0
481bdc738b8Skre	check 'set -- a \?; IFS=\\; var=$*; unset IFS; printf "%s\n" "${var}"' \
482bdc738b8Skre						'a\?'	0
483bdc738b8Skre
484bdc738b8Skre	check 'set -- a \?; IFS=\\; var=$*; unset IFS; printf "%s\n" ${var}' \
485bdc738b8Skre						'a?'	0		#140
486bdc738b8Skre	mv 'a?' 'a@'
487bdc738b8Skre	check 'set -- a \?; IFS=\\; var=$*; unset IFS; printf "%s\n" ${var}' \
488bdc738b8Skre						'a\?'	0
489bdc738b8Skre	mv 'a@' 'a?'
490bdc738b8Skre
491bdc738b8Skre	# This is unspecified by POSIX, but everyone (sane) does it this way
492bdc738b8Skre	check 'printf "%s\n"  D*[/*] | wc -l'		'6'	0
493bdc738b8Skre	check 'printf "%s\n"  D*[\/*] | wc -l'		'6'	0
494bdc738b8Skre	check 'printf "%s\n"  D*\[/*] | wc -l'		'6'	0
495bdc738b8Skre	check 'printf "%s\n"  D*\[\/*] | wc -l'		'6'	0	#145
496bdc738b8Skre	check 'printf "%s\n"  D*[/*]' \
497bdc738b8Skre		'D[/D[] D[/D[].] D[/D] D[/D].] D[/] D[/][]'	0
498bdc738b8Skre
499bdc738b8Skre	# '^' as the first char in a bracket expr is unspecified by POSIX,
500bdc738b8Skre	# but for compat with REs everyone (sane) makes it the same as !
501fd909972Skre
502fd909972Skre	# But just in case we are testing an insane shell ...
503fd909972Skre    ${TEST_SH} -c 'case "^" in ([^V^]) exit 1;; (*) exit 0;; esac' && {
504fd909972Skre
505bdc738b8Skre	check 'printf "%s\n" [^ab] | wc -l'		'24'	0
506bdc738b8Skre	check 'printf "%s\n" [^ab]* | wc -l'		'5281'	0
507bdc738b8Skre	check 'printf "%s\n" [^A-D]* | wc -l'		'5692'	0
508bdc738b8Skre
509bdc738b8Skre	check 'printf "%s\n" [^0-3]* | wc -l'		'5094'	0	#150
510bdc738b8Skre	check 'printf "%s\n" [^-03]* | wc -l'		'5265'	0
511bdc738b8Skre	check 'printf "%s\n" [^0\-3]* | wc -l'		'5265'	0
512bdc738b8Skre	check 'printf "%s\n" [^-a3]* | wc -l'		'5110'	0
513bdc738b8Skre	check 'printf "%s\n" [\^-a3]* | wc -l'		'608'	0
514bdc738b8Skre	check 'printf "%s\n" [\^0-3]* | wc -l'		'830'	0	#155
515bdc738b8Skre	check 'printf "%s\n" [0-3^]* | wc -l'		'830'	0
516bdc738b8Skre	check 'printf "%s\n" [0^-a]* | wc -l'		'513'	0
517bdc738b8Skre	check 'printf "%s\n" *[^0-3] | wc -l'		'5156'	0
518bdc738b8Skre	check 'printf "%s\n" [!^]? | wc -l'		'529'	0
519bdc738b8Skre
520bdc738b8Skre	check 'printf "%s\n" [^!]? | wc -l'		'529'	0	#160
521bdc738b8Skre	check 'printf "%s\n" [!!^]? | wc -l'		'508'	0
522bdc738b8Skre	check 'printf "%s\n" [!^!]? | wc -l'		'508'	0
523bdc738b8Skre	check 'printf "%s\n" [^!]? | wc -l'		'529'	0
524bdc738b8Skre	check 'printf "%s\n" [^!^]? | wc -l'		'508'	0
525bdc738b8Skre	check 'printf "%s\n" [^^!]? | wc -l'		'508'	0	#165
526bdc738b8Skre	check 'printf "%s\n" [!^-b]? | wc -l'		'487'	0
527bdc738b8Skre	check 'printf "%s\n" [^!-b]? | wc -l'		'63'	0
528bdc738b8Skre
529fd909972Skre    }
530fd909972Skre
531bdc738b8Skre	# No need to clean up the directory, we're in the ATF working
532bdc738b8Skre	# directory, and ATF cleans up for us.
533bdc738b8Skre
534bdc738b8Skre	results
535bdc738b8Skre}
536bdc738b8Skre
537bdc738b8Skreatf_test_case case_matching
538bdc738b8Skrecase_matching_head() {
539bdc738b8Skre	atf_set descr "Test expansion of vars with embedded cmdsub"
540bdc738b8Skre}
541bdc738b8Skre
542bdc738b8Skre# helper functions for case matching
543bdc738b8Skre#
544bdc738b8Skre# usage: cm word [ pattern ] [ preamble ]	(expect word to match pattern)
545bdc738b8Skre#        cf word [ pattern ] [ preamble ]	(expect word to fail to match)
546bdc738b8Skre#
547bdc738b8Skre# The last used (non-null) pattern, and the last used preamble, are
548bdc738b8Skre# remembered and used again if only the word is given.  To give a
549bdc738b8Skre# new preamble while using the last pattern, give '' as the pattern.
550bdc738b8Skre#
551bdc738b8Skre# nb: a null (empty) pattern is a syntax error, to get '' use "''"
552bdc738b8Skre#
553bdc738b8Skrecm() {
554bdc738b8Skre	case "$2" in
555bdc738b8Skre	'')	set -- "$1" "${LAST_PATTERN}" "${3:-${LAST_PFX}}";;
556bdc738b8Skre	*)	LAST_PATTERN="$2";;
557bdc738b8Skre	esac
558bdc738b8Skre	LAST_PFX="$3"
559bdc738b8Skre
560bdc738b8Skre	check \
561bdc738b8Skre	    "${3:+${3}; }case $1 in ($2) printf M;; (*) printf X;; esac" M 0
562bdc738b8Skre}
563bdc738b8Skrecf() {
564bdc738b8Skre	case "$2" in
565bdc738b8Skre	'')	set -- "$1" "${LAST_PATTERN}" "${3:-${LAST_PFX}}";;
566bdc738b8Skre	*)	LAST_PATTERN="$2";;
567bdc738b8Skre	esac
568bdc738b8Skre	LAST_PFX="$3"
569bdc738b8Skre
570bdc738b8Skre	check \
571bdc738b8Skre	    "${3:+${3}; }case $1 in ($2) printf M;; (*) printf X;; esac" X 0
572bdc738b8Skre}
573bdc738b8Skre
574bdc738b8Skrecase_matching_body() {
575bdc738b8Skre
576bdc738b8Skre	# nb: we are not testing execution of case, so no ;& or alternate
577bdc738b8Skre	# patterns (etc) are needed here, we just want to validate the
578bdc738b8Skre	# case variant of pattern matching, so simple one word, one pattern
579bdc738b8Skre	# match or not match.
580bdc738b8Skre
581bdc738b8Skre	reset case_matching
582bdc738b8Skre
583bdc738b8Skre	cm abcd 'ab*'; cf bcda; cf aabce; cm ab				#  4
584bdc738b8Skre	cm abcd '$var' 'var="ab*"'; cf abcd '"$var"' 'var="ab*"'	#  6
585bdc738b8Skre
586bdc738b8Skre	cm xy 'x*y'; cm xyxy; cm '"x*y"'; cf xxyz 			# 10
587bdc738b8Skre
588bdc738b8Skre	cm '""' '*'; cm '\*'; cm '\?'; cm -; cm 12345			# 15
589bdc738b8Skre	cm abcd '$var' 'var="*"'; cf abcd '"$var"' 'var="*"'		# 17
590bdc738b8Skre	cm '"*"' '\*'; cm '"*"' '"*"'; cm '"*"' '"$var"' 'var="*"'	# 20
591bdc738b8Skre
592bdc738b8Skre	cm X '?'; cf XX '?'; cf X '"?"'; cm Y '$var' 'var="?"'		# 24
593bdc738b8Skre	cf Z '"$var"' 'var="?"'; cm '"?"' '"$var"' 'var="?"'		# 26
594bdc738b8Skre
595bdc738b8Skre	cm XA '??'; cf X '??'; cf XX '"??"'; cm YZ '$var' 'var="??"'	# 30
596bdc738b8Skre	cf ZZ '"$var"' 'var="??"'; cm '"??"' '"$var"' 'var="??"'	# 32
597bdc738b8Skre
598bdc738b8Skre	cm a '[ab]'; cm b; cf c; cf aa; cf '"[ab]"'			# 37
599bdc738b8Skre	cm '"[ab]"' '"[ab]"'; cm '"[ab]"' '\[ab]'			# 39
600bdc738b8Skre	cm a '$var' 'var="[ab]"'; cf a '"$var"' 'var="[ab]"'		# 41
601bdc738b8Skre	cm '"[ab]"' '"$var"' 'var="[ab]"'; cm a '["$var"]' 'var=ab'	# 43
602bdc738b8Skre
603bdc738b8Skre	cm b '[a-c]'; cm a '[a-c]'; cm c '[a-c]'; cf d '[a-c]'		# 47
604bdc738b8Skre	cf '"[a-c]"' '[a-c]'; cm '"[a-c]"' '"[a-c]"'			# 49
605bdc738b8Skre	cm '"[a-c]"' '\[a-c]'; cm '"[a-c]"' '[a-c\]'			# 51
606bdc738b8Skre	cm a '$var' 'var="[a-c]"'; cf a '"$var"' 'var="[a-c]"'		# 53
607bdc738b8Skre	cm '"[a-c]"' '"$var"' 'var="[a-c]"'; cf b '["$var"]' 'var=a-c'	# 55
608bdc738b8Skre
609bdc738b8Skre	cm 2 '[0-4]'; cm 0 '[0-4]'; cf - '[0-4]'; cm 0 '[-04]'		# 59
610bdc738b8Skre	cf 2 '[-04]'; cf 2 '[40-]'; cm 0 '[40-]'; cm - '[-04]'		# 63
611bdc738b8Skre	cf 2 '[0\-4]'; cm - '[0\-4]'; cf 2 '["0-4"]'; cm - '["0-4"]'	# 67
612bdc738b8Skre	cf 2 "[0'-'4]"; cm - "[0'-'4]"; cm 4 "[0'-'4]"			# 70
613bdc738b8Skre	cm 0 "['0'-'4']"; cf '"\\"' '[0\-4]'; cm '"\\"' '[\\0-\\4]'	# 73
614bdc738b8Skre
615bdc738b8Skre	cm a '[[:alpha:]]'; cf 0; cf '"["'; cm Z; cf aa; cf .; cf '""'	# 80
616bdc738b8Skre	cf a '[[:digit:]]'; cm 0; cf '"["'; cm 9; cf 10; cf .; cf '""'	# 87
617bdc738b8Skre	cm '"["' '[][:alpha:][]'; cf a '[\[:alpha:]]'; cf a '[[\:alpha:]]' #90
618bdc738b8Skre	cm a '[$var]' 'var="[:alpha:]"'; cm a '[[$var]]' 'var=":alpha:"' # 92
619bdc738b8Skre	cm a '[[:$var:]]' 'var=alpha'; cm B '[[:"$var":]]' 'var=alpha'	# 94
620bdc738b8Skre	cf B '["$var"]' 'var="[:alpha:]"'; cf B '[["$var"]]' 'var=":alpha:"' #96
621bdc738b8Skre	cm '"["' '["$var"]' 'var="[:alpha:]"'				# 97
622bdc738b8Skre	cm '"[]"' '[["$var"]]' 'var=":alpha:"'; 			# 98
623bdc738b8Skre	cm A3 '[[:alpha:]][[:digit:]]'; cf '"[["'			#100
624bdc738b8Skre	cm 3 '[[:alpha:][:digit:]]'; cf '"["'; cm A; cf '":"'		#104
625bdc738b8Skre	for W in AA A7 8x 77; do
626bdc738b8Skre		cm "$W" '[[:alpha:][:digit:]][[:alpha:][:digit:]]'	#108
627bdc738b8Skre	done
628bdc738b8Skre
629bdc738b8Skre	cm dir/file '*/*'; cm /dir/file; cm /dir/file '*/file'		#111
630bdc738b8Skre	for W in aa/bcd /x/y/z .x/.abc --/--- '\\//\\//' '[]/[][]'
631bdc738b8Skre	do
632bdc738b8Skre		cm "'$W'" '??/*'; cm "'$W'" '[-a/.\\[]?/??*[]dzc/-]'
633bdc738b8Skre	done								#123
634bdc738b8Skre
635bdc738b8Skre	cm '"?abc"' '\?*'; cf '"\\abc"'; cm '"?"'			#126
636bdc738b8Skre
637bdc738b8Skre	cm '\\z' '"\\z"'; cf '\z'; cf z; cf '"\\"'			#130
638bdc738b8Skre
639bdc738b8Skre	cm '"[x?abc"' '[[-\]]?\?*'; cm '"]x?abc"'; cm '"\\x?abc"'	#133
640bdc738b8Skre		cf '"-x?abc"'; cf '"[xyzabc"'; cm '"[]?"'		#136
641bdc738b8Skre
642bdc738b8Skre	cm '"[x?"' '[]\\[]?\?'; cm '"]x?"'; cm '"\\y?"'; cm '"[]?"'	#140
643bdc738b8Skre
644bdc738b8Skre	cm "'\z'" '"\z"'; cf z; cm '\\z'; cm '$var' '' 'var="\z"'	#144
645bdc738b8Skre	cm '${var}' '' "var='\z'"; cm '"${var}"'			#146
646fd909972Skre	cf '${var}' '${var}' "var='\z'"; cm '${var}' '"${var}"' "var='\z'" #148
647bdc738b8Skre	cf "'${var}'"; cm "'${var}'" "'${var}'" "var='\z'"		#150
648bdc738b8Skre
649bdc738b8Skre	cf abc '"$*"' 'IFS=?; set -- a c';cf '"a c"';cm "'a?c'";cm '"$*"' #154
650bdc738b8Skre	cf abc '"$*"' 'IFS=*; set -- a c';cf '"a c"';cm "'a*c'";cm '"$*"' #158
651bdc738b8Skre	cf abc '"$*"' 'IFS=\\;set -- a c';cf '"a c"';cm "'a\c'";cm '"$*"' #162
652bdc738b8Skre	cf abc '"$*"' 'IFS="";set -- a c';cf '"a c"';cm "'ac'"; cm '"$*"' #166
653bdc738b8Skre
654bdc738b8Skre	cm a '["$*"]' 'IFS=-; set -- a c';cf b;cm c;cm '-';   cf "']'"	#171
655bdc738b8Skre	cm a '["$*"]' 'IFS=?; set -- a c';cf b;cm c;cm '"?"'; cf "'['"	#176
656bdc738b8Skre	cm a '["$*"]' 'IFS=*; set -- a c';cf b;cm c;cm '"*"'; cf -	#181
657bdc738b8Skre	cm a '["$*"]' 'IFS=\\;set -- a c';cf b;cm c;cm "'\\'";cf "'$'"	#186
658bdc738b8Skre	cm a '["$*"]' 'IFS="";set -- a c';cf b;cm c			#189
659bdc738b8Skre
660bdc738b8Skre
661bdc738b8Skre	# Now repeat the ones using bracket expressions, adding !
662bdc738b8Skre
663bdc738b8Skre	cf a '[!ab]'; cf b; cm c; cf aa; cf '"[!ab]"'; cm a '[ab!]'; cm ! #196
664bdc738b8Skre	cf a '$var' 'var="[!ab]"';cm x;cf a '"$var"' 'var="[!ab]"'; cf x  #200
665bdc738b8Skre	cm '"[!ab]"' '"$var"' 'var="[!ab]"'; cf a; cf b; cf !; cf "'['"	  #205
666bdc738b8Skre	cf a '[!"$var"]' 'var=ab'; cm x; cm a '["!$var"]' 'var=ab'	  #208
667bdc738b8Skre	cf x; cm !; cm a '["$var"]' 'var=!ab'; cf x			  #212
668bdc738b8Skre	cf a '[$var]' 'var=!ab'; cm !					  #214
669bdc738b8Skre
670bdc738b8Skre	cf b '[!a-c]'; cf a; cf c; cm d; cm !; cm -; cm _; cm '\\'	#222
671bdc738b8Skre	cf a '$var' 'var="[!a-c]"'; cf b; cf c; cm d; cm !; cm -	#228
672bdc738b8Skre
673bdc738b8Skre	cf 2 '[!0-4]'; cf 0; cm -; cf 4; cm !; cm "'['"; cm "']'"	#235
674bdc738b8Skre	cm 2 '[!-04]'; cm 2 '[!40-]'; cf 0; cf -; cm !;			#240
675bdc738b8Skre	cm 2 '[!0\-4]'; cf -; cm 2 '[!"0-4"]'; cf -			#244
676bdc738b8Skre
677bdc738b8Skre	cf a '[![:alpha:]]'; cm 0; cm '"["'; cf aa; cm .; cf '""'	#250
678bdc738b8Skre	cf '"["' '[!][:alpha:][!]'; cf a; cm 0; cf !; cf "']'"; cm %	#256
679bdc738b8Skre	cf a '[$var]' 'var="![:alpha:]"'; cm 0; cm !; cm "']'"; cm @	#261
680bdc738b8Skre
6810ebdf0f8Skre	# Next some tests of patterns containing (intended literal) '\'
6820ebdf0f8Skre	# The first of the "set" tests pair was reported as broken bu
6830ebdf0f8Skre	# Martijn Dekker (private mail) (Nov 2018).
6840ebdf0f8Skre
685fa836fadSkre	cm "'\\'" "'\\'"; cf "'\\'" "'\\\\'"				#263
686fa836fadSkre	cm "'\\'" '"$var"' "var='\\'"; cf "'\\'" '$var' "var='\\'"	#265
687fa836fadSkre	cm '$1' '"$2"' 'set -- \\ \\'; cf '$1' '$2' 'set -- \\ \\'	#267
688fa836fadSkre	cf '$1' '"$2"' 'set -- \\ \\\\'; cm '$1' '$2' 'set -- \\ \\\\'	#269
689fa836fadSkre	cm "'\\'" "\$( echo '\\\\' )"; cf "'\\'" "\$( echo '\\' )"	#271
690fa836fadSkre	cm "'\\'" "\"\$( echo '\\' )\""					#272
691fa836fadSkre	cf "'\\'" "\"\$( echo '\\\\' )\""				#273
692fa836fadSkre
693fa836fadSkre	if X=$( ${TEST_SH} -c 'printf %s '"\$'\\\\'" 2>/dev/null ) &&
694fa836fadSkre	    [ "$X" = '\' ]
695fa836fadSkre	then
696fa836fadSkre		# TEST_SH supports $'...' so we can test it as well
697fa836fadSkre		# note these are $'\\' and $'\\\\' as patterns.
698fa836fadSkre		# They should be identical to '\' and '\\'
699fa836fadSkre		cm "'\\'" "\$'\\\\'"; cf "'\\'" "\$'\\\\\\\\'"		#275
700fa836fadSkre	else
701fa836fadSkre		# uncomment this if we need to keep sub-test numbering sane
702fa836fadSkre		# it isn't needed as long as this remains last.
703fa836fadSkre		# (nb: this is just a repeat of sub-test 263)
704fa836fadSkre
705fa836fadSkre		# cm "'\\'" "'\\'"; cf "'\\'" "'\\\\'"			#275
706fa836fadSkre	fi
7070ebdf0f8Skre
708bdc738b8Skre	results
709bdc738b8Skre}
710bdc738b8Skre
711bdc738b8Skreatf_test_case var_substring_matching
712bdc738b8Skrevar_substring_matching_head() {
713bdc738b8Skre	atf_set descr 'Test pattern matching in var expansions'
714bdc738b8Skre}
715bdc738b8Skre
716bdc738b8Skre# Helper function for var substring matching
717bdc738b8Skre#	$1 is the input string
718bdc738b8Skre#	$2 the substring matching operator (# % ## or %%)
719bdc738b8Skre#	$3 is the pattern to match (or reference to one)
720bdc738b8Skre#	$4 is the expected output (result of applying op($2) with pat($3) to $1
721bdc738b8Skre#	$5 (if given, and not null) is a command (or commands) to run first
722bdc738b8Skre#	$6 (if given, and not null) cause the var expansion to be quoted
723bdc738b8Skre#		(ie "${var%pattern}" instead of just ${var%pattern})
724bdc738b8Skre#		any quotes needed in "pattern" should be in $3
725bdc738b8Skre# Note: a variable called "var" is used (set to $1, then expanded).
726bdc738b8Skrevm()
727bdc738b8Skre{
728bdc738b8Skre	check "${5:+${5}; }var='$1';printf '%s\n' ${6:+\"}\${var$2$3}${6:+\"}" \
729bdc738b8Skre		"$4" 0
730bdc738b8Skre}
731bdc738b8Skre
732bdc738b8Skrevar_substring_matching_body() {
733bdc738b8Skre
734bdc738b8Skre	reset var_substring_matching
735bdc738b8Skre
736bdc738b8Skre	vm abc \# a bc; vm aaab \# a aab; vm aaab \## 'a*a' b		#  3
737fd909972Skre	vm aaab % ab aa; vm xawab %% 'a*ab' x; vm abcd \# xyz abcd
738fd909972Skre	vm file.c % .c 'f le' IFS=i ; vm file.c % .c file IFS=i Q
739fd909972Skre	vm file.c % ?c file ; vm file.c % '"?c"' file.c			# 9 10
740bdc738b8Skre
741fd909972Skre	vm abcabcabcded \# 'a*b' cabcabcded; vm abcabcabcded \## 'a*b' cded
742fd909972Skre	vm abcabcabcded % 'c*d' abcabcab; vm abcabcabcded %% 'c*d' ab
743bdc738b8Skre
744bdc738b8Skre	vm abc.jpg % '.[a-z][!0-9]?' abc				# 15
745bdc738b8Skre
746fd909972Skre	vm xxxyyy \# '${P}' yyy P=xxx; vm xxxyyy \# '${P}' yyy 'P=x?x'
747fd909972Skre	vm xxxyyy \# '${P}' yyy 'P=x?x' Q
748fd909972Skre	vm 'x?xyyy' \# '${P}' yyy 'P=x[?]x'
749fd909972Skre	vm xxxyyy \# '${P}' xxxyyy 'P=x[?]x'				# 20
750fd909972Skre	vm 'x?xyyy' \# '${P}' yyy 'P=x?x' Q
751fd909972Skre	vm xxxyyy \# '${P}' yyy 'P=x?x' Q
752fd909972Skre	vm 'x?xyyy' \# '${P}' yyy 'P="x\?x"'
753fd909972Skre	vm 'x?xyyy' \# '${P}' yyy 'P="x\?x"' Q
754bdc738b8Skre	vm 'x?xyyy' \# '${P}' yyy 'P="x?x"' 				# 25
755fd909972Skre	vm 'x?xyyy' \# '${P}' yyy 'P="x?x"' Q
756fd909972Skre	vm 'x?xyyy' \# '"${P}"' 'x?xyyy' 'P="x\?x"'
757fd909972Skre	vm 'x?xyyy' \# '"${P}"' 'x?xyyy' 'P="x\?x"' Q
758fd909972Skre	vm 'x?xyyy' \# '"${P}"' yyy 'P="x?x"'
759fd909972Skre	vm 'x?xyyy' \# '"${P}"' yyy 'P="x?x"' Q				# 30
760fd909972Skre	vm 'x%xyyy' \# '${P}' 'x%xyyy' 'P="x\?x"'
761fd909972Skre	vm 'x%xyyy' \# '${P}' 'x%xyyy' 'P="x\?x"' Q
762fd909972Skre	vm 'x%xyyy' \# '${P}' yyy 'P="x?x"'
763fd909972Skre	vm 'x%xyyy' \# '${P}' yyy 'P="x?x"' Q
764fd909972Skre	vm 'x%xyyy' \# '"${P}"' 'x%xyyy' 'P="x\?x"'			# 35
765fd909972Skre	vm 'x%xyyy' \# '"${P}"' 'x%xyyy' 'P="x\?x"' Q
766fd909972Skre	vm 'x%xyyy' \# '"${P}"' 'x%xyyy' 'P="x?x"'
767fd909972Skre	vm 'x%xyyy' \# '"${P}"' 'x%xyyy' 'P="x?x"' Q
768bdc738b8Skre
769fd909972Skre	vm abc \# '*' abc; vm abc \# '*' abc '' Q			# 39 40
770fd909972Skre	vm abc \# '"*"' abc; vm abc \# '"*"' abc '' Q
771fd909972Skre	vm abc \# '"a"' bc; vm abc \# '"a"' bc '' Q
772fd909972Skre	vm abc \## '*' ''; vm abc \## '*' '' '' Q
773fd909972Skre	vm abc % '*' abc; vm abc % '*' abc '' Q
774fd909972Skre	vm abc %% '*' ''; vm abc %% '*' '' '' Q				# 49 50
775fd909972Skre	vm abc \# '$P' abc 'P="*"'; vm abc \# '$P' abc 'P="*"' Q
776fd909972Skre	vm abc \# '"$P"' abc 'P="*"'; vm abc \# '"$P"' abc 'P="*"' Q
777fd909972Skre	vm abc \# '$P' bc 'P="[a]"'; vm abc \# '$P' bc 'P="[a]"' Q
778fd909972Skre	vm abc \# '"$P"' abc 'P="[a]"'; vm abc \# '"$P"' abc 'P="[a]"' Q
779fd909972Skre	vm '[a]bc' \# '$P' '[a]bc' 'P="[a]"'
780fd909972Skre	vm '[a]bc' \# '"$P"' bc 'P="[a]"'				# 60
781fd909972Skre	vm '[a]bc' \# '"$P"' bc 'P="[a]"' Q
782bdc738b8Skre
783fd909972Skre	# The following two (62 & 63) are actually the same test.
784fd909972Skre	# The double \\ turns into a single \ when parsed.
785fd909972Skre	vm '[a]bc' \# '$P' bc 'P="\[a]"';  vm '[a]bc' \# '$P' bc 'P="\\[a]"'
786fd909972Skre	vm '[a]bc' \# '"$P"' '[a]bc' 'P="\[a]"'
787fd909972Skre	vm '\[a]bc' \# '"$P"' bc 'P="\[a]"'				# 65
788bdc738b8Skre
789fd909972Skre	vm ababcdabcd \#  '[ab]*[ab]' abcdabcd
790fd909972Skre	vm ababcdabcd \## '[ab]*[ab]' cd
791fd909972Skre	vm ababcdabcd \#  '$P'  abcdabcd  'P="[ab]*[ab]"'
792fd909972Skre	vm ababcdabcd \## '$P'  cd	    "P='[ab]*[ab]'"
793fd909972Skre	vm ababcdabcd \#  '$P' 'ab dab d' 'P="[ab]*[ab]"; IFS=c'	# 70
794fd909972Skre	vm ababcdabcd \#  '$P'  abcdabcd  'P="[ab]*[ab]"; IFS=c' Q
795bdc738b8Skre
796fd909972Skre	vm ababcdabcd \#  '[ab]*[ba]'  abcdabcd
797fd909972Skre	vm ababcdabcd \#  '[ab]*[a-b]' abcdabcd
798fd909972Skre	vm ababcdabcd \## '[ba]*[ba]'  cd
799fd909972Skre	vm ababcdabcd \## '[a-b]*[ab]' cd				# 75
800bdc738b8Skre
801fd909972Skre	vm abcde \# '?[b-d]?' de; vm abcde \## '?[b-d]?' de
802fd909972Skre	vm abcde % '?[b-d]?' ab; vm abcde %% '?[b-d]?' ab
803bdc738b8Skre
804fd909972Skre	vm .123. \# '.[0-9][1-8]' 3.; vm .123. % '[0-9][1-8].' .1	# 80 81
805fd909972Skre	vm .123. \# '?[0-9][1-8]' 3.; vm .123. % '[0-9][1-8]?' .1
806fd909972Skre	vm .123. \# '*[0-9][1-8]' 3.; vm .123. % '[0-9][1-8]*' .1	# 85
807fd909972Skre	vm .123. \## '*[0-9][1-8]' .; vm .123. %% '[0-9][1-8]*' .
808fd909972Skre	vm .123. \# '[.][1][2]' 3.  ; vm .123. % '[2][3][.]' .1
809fd909972Skre	vm .123. \# '[?]1[2]' .123. ; vm .123. % '2[3][?]' .123.	# 90 91
810fd909972Skre	vm .123. \# '\.[0-9][1-8]' 3.;vm .123. % '[0-9][1-8]\.' .1
811bdc738b8Skre
812fd909972Skre	vm '[a-c]d-f' \# '[a-c\]' d-f
813fd909972Skre	vm '[abcd]' \# '[[:alpha:]]' '[abcd]'				# 95
814fd909972Skre	vm '[1?234' \# '[[-\]]?\?' 234
815fd909972Skre	vm '1-2-3-\?' % '-${P}' '1-2-3-\?' 'P="\\?"'
816fd909972Skre	vm '1-2-3-\?' % '${P}' '1-2-3-\' 'P="\\?"'
817fd909972Skre	vm '1-2-3-\?' % '-"${P}"' 1-2-3 'P="\\?"'			# 99
818bdc738b8Skre
819bdc738b8Skre	results
820bdc738b8Skre}
821bdc738b8Skre
822bdc738b8Skre
823bdc738b8Skreatf_init_test_cases() {
824bdc738b8Skre	# Listed here in the order ATF runs them, not the order from above
825bdc738b8Skre
826bdc738b8Skre	atf_add_test_case filename_expansion
827bdc738b8Skre	atf_add_test_case case_matching
828bdc738b8Skre	atf_add_test_case var_substring_matching
829bdc738b8Skre}
830