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