diff options
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | t/errors.t | 104 | ||||
-rwxr-xr-x | t/limits.t | 24 | ||||
-rwxr-xr-x | t/percent.t | 110 | ||||
-rwxr-xr-x | t/regressions.t | 14 | ||||
-rwxr-xr-x | t/simple.t | 269 | ||||
-rwxr-xr-x | t/slow.t | 43 | ||||
-rwxr-xr-x | tap3 | 105 | ||||
-rwxr-xr-x | tests | 361 |
9 files changed, 670 insertions, 362 deletions
diff --git a/Makefile b/Makefile index 8025ba0..32f481d 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ clean: FRC rm -f $(ALL) check: FRC all - prove -v ./tests + prove -v install: FRC all mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1 diff --git a/t/errors.t b/t/errors.t new file mode 100755 index 0000000..c2ecd5e --- /dev/null +++ b/t/errors.t @@ -0,0 +1,104 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..13\n' +printf '# error handling\n' + +tap3 'exit code on success' <<'EOF' +xe +>>>= 0 +EOF + +tap3 'exit code on other error' <<'EOF' +true | xe -j NaN +>>>= 1 +EOF + +tap3 'exit code on when command fails with 1-125' <<'EOF' +xe -s 'exit 42' +<<< +a +>>>= 123 +EOF + +tap3 'exit code on when command fails with 255' <<'EOF' +xe -s 'exit 255' +<<< +a +>>>= 124 +EOF + +tap3 'exit code when process was killed' <<'EOF' +xe perl -e 'kill "KILL", $$' +<<< +a +>>>= 125 +EOF + +# possible false positive result when exec returns ENOENT instead of ENOTDIR here +tap3 'exit code when command cannot be run' <<'EOF' +xe /dev/null/calc.exe +<<< +a +>>>= 126 +EOF + +tap3 'exit code when command was not found' <<'EOF' +xe /bin/calc.exe +<<< +a +>>>= 127 +EOF + +tap3 'exit code on empty input when run with -R' <<'EOF' +xe -R echo a +>>>= 122 +EOF + +tap3 'doesn'\''t stop on errors by default' <<'EOF' +xe -s 'if [ b = $1 ]; then false; else echo $1; fi' +<<< +a +b +c +>>> +a +c +>>>= 123 +EOF + +tap3 'stops on first error with -F' <<'EOF' +xe -F -s 'if [ b = $1 ]; then false; else echo $1; fi' +<<< +a +b +c +>>> +a +>>>= 123 +EOF + +tap3 'should close stdin when arguments were read from it' <<'EOF' +xe -s 'sed q' +<<< +a +b +c +>>> +EOF + +tap3 'should not close stdin when arguments were read from command line' <<'EOF' +yes | xe -a -s "sed q" -- 1 2 3 +>>> +y +y +y +EOF + +tap3 'should not close stdin when arguments were read from file' <<'EOF' +yes | xe -f NEWS.md -s 'sed q' 2>&1 | sed 3q +>>> +y +y +y +EOF diff --git a/t/limits.t b/t/limits.t new file mode 100755 index 0000000..8692a2e --- /dev/null +++ b/t/limits.t @@ -0,0 +1,24 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..2\n' +printf '# limit checks, expecting maximal POSIX limits available\n' + +tap3 'argscap check' <<'EOF' +dd if=/dev/zero bs=1 count=17711 2>/dev/null | + tr "\0" "\012" | + xe -N0 -s 'echo $#' +>>> +8187 +8187 +1337 +EOF + +tap3 'argslen check' <<'EOF' +perl -e 'print "x"x8000, "\n" for 1..42' | + xe -N0 -s 'echo $#' +>>> +16 +16 +10 +EOF diff --git a/t/percent.t b/t/percent.t new file mode 100755 index 0000000..c3b97b7 --- /dev/null +++ b/t/percent.t @@ -0,0 +1,110 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..13\n' +printf '# percent rules\n' + +tap3 'literal matches' <<'EOF' +xe -ap bcd echo found -- abc bcd defg +>>> +found +EOF + +tap3 'multiple patterns' <<'EOF' +xe -ap one echo 1 + two echo 2 + three echo 3 -- zero one two three four five +>>> +1 +2 +3 +EOF + +tap3 '{} expansion' <<'EOF' +xe -ap bcd echo {} -- abc bcd defg +>>> +bcd +EOF + +tap3 '% expansion' <<'EOF' +xe -ap bcd echo % -- abc bcd defg +>>> +bcd +EOF + +tap3 'dirnames' <<'EOF' +xe -ap bcd echo % -- abc bcd /tmp/bcd /tmp/abc +>>> +bcd +/tmp/bcd +EOF + +tap3 '? glob' <<'EOF' +xe -ap "b?d" echo % -- abc bcd b3d defg +>>> +bcd +b3d +EOF + +tap3 '* glob' <<'EOF' +xe -ap "b*d" echo % -- bd bed bad bugged bx zbd b/d +>>> +bd +bed +bad +bugged +EOF + +tap3 'multiple * glob' <<'EOF' +xe -ap "b*g*d" echo % -- bd bed bugged bx zbd bagdad badger ba/gd/ad +>>> +bugged +bagdad +EOF + +tap3 'multiple ** glob' <<'EOF' +xe -ap "b**g**d" echo % -- bd bed bugged bx zbd bagdad badger ba/gd/ad +>>> +bugged +bagdad +ba/gd/ad +EOF + +tap3 '/ slash' <<'EOF' +xe -ap a/b echo 1 + c///d echo 2 + "*" echo 3 -- a/b a//b a/ b c/d /c////d +>>> +1 +1 +3 +3 +2 +3 +EOF + +tap3 '[] ranges' <<'EOF' +xe -ap "[abc]" echo "1%" + "[d-g]" echo "2%" + "[^xyz-]" echo "3%" + "[!-vw]" echo "4%" + % echo "5%" -- a c d e g h w x - +>>> +1a +1c +2d +2e +2g +3h +3w +4x +5- +EOF + +tap3 '{} alternation' <<'EOF' +xe -ap "{a,bc,def*}" echo % -- x a abc bc bcd def defx xdef +>>> +a +bc +def +defx +EOF + +tap3 '% match' <<'EOF' +xe -ap %.c echo obj/%.o -- foo.c bar.cc meh/quux.c +>>> +obj/foo.o +meh/obj/quux.o +EOF diff --git a/t/regressions.t b/t/regressions.t new file mode 100755 index 0000000..9b50585 --- /dev/null +++ b/t/regressions.t @@ -0,0 +1,14 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..1\n' +printf '# regressions\n' + +tap3 '0fb64a4 quoting of empty strings' <<'EOF' +xe -N2 -v true +<<< +foo + +>>>2 +true foo '' +EOF diff --git a/t/simple.t b/t/simple.t new file mode 100755 index 0000000..b418d39 --- /dev/null +++ b/t/simple.t @@ -0,0 +1,269 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..27\n' +printf '# simple tests\n' + +tap3 'single argument run' <<'EOF' +xe echo +<<< +1 +2 +3 +>>> +1 +2 +3 +EOF + +tap3 'dual argument run' <<'EOF' +xe -N2 echo +<<< +1 +2 +3 +4 +5 +>>> +1 2 +3 4 +5 +EOF + +tap3 'unlimited argument run' <<'EOF' +xe -N0 echo +<<< +1 +2 +3 +4 +5 +>>> +1 2 3 4 5 +EOF + +tap3 'empty input run' <<'EOF' +true | xe echo a +>>> +EOF + +tap3 'dry run' <<'EOF' +xe -n echo x +<<< +a +b +c +>>>2 +echo x a +echo x b +echo x c +EOF + +tap3 'dry run quoting' <<'EOF' +xe -n echo x +<<< +a +b b +c +>>>2 +echo x a +echo x 'b b' +echo x c +EOF + +tap3 'verbose run' <<'EOF' +xe -v echo x +<<< +a +b +c +>>> +x a +x b +x c +>>>2 +echo x a +echo x b +echo x c +EOF + +tap3 'with no command' <<'EOF' +xe -N2 +<<< +1 +2 +3 +>>> +1 +2 +3 +EOF + +tap3 'using {}' <<'EOF' +xe echo a {} x +<<< +1 +2 +3 +>>> +a 1 x +a 2 x +a 3 x +EOF + +tap3 'using {} twice' <<'EOF' +xe echo {} x {} +<<< +1 +2 +3 +>>> +1 x {} +2 x {} +3 x {} +EOF + +tap3 'using -I%' <<'EOF' +xe -I% echo {} x % +<<< +1 +2 +3 +>>> +{} x 1 +{} x 2 +{} x 3 +EOF + +tap3 'using -I "" to disable' <<'EOF' +xe -I "" echo {} x % +<<< +1 +2 +3 +>>> +{} x % 1 +{} x % 2 +{} x % 3 +EOF + +tap3 'using {} with multiple arguments' <<'EOF' +xe -N2 echo a {} x {} +<<< +1 +2 +3 +>>> +a 1 2 x {} +a 3 x {} +EOF + +tap3 'using -0' <<'EOF' +printf "foo\0bar\0quux" | xe -0 echo +>>> +foo +bar +quux +EOF + +tap3 'using -a' <<'EOF' +xe -a echo -- 1 2 3 +>>> +1 +2 +3 +EOF + +tap3 'using -a with no arguments' <<'EOF' +xe -a echo +>>> +EOF + +tap3 'using -a with no command' <<'EOF' +xe -N2 -a -- 1 2 3 +>>> +1 +2 +3 +EOF + +tap3 'using -A%' <<'EOF' +xe -A% echo -- % 1 2 3 +>>> +-- 1 +-- 2 +-- 3 +EOF + +tap3 'using -A% with no arguments' <<'EOF' +xe -A% echo +>>>2 +xe: '-A %' used but no separator '%' found in command line. +EOF + +tap3 'using -A% with no command' <<'EOF' +xe -N2 -A% % 1 2 3 +>>> +1 +2 +3 +EOF + +tap3 'using -f' <<'EOF' +echo notme | xe -f Makefile echo +>>> /DESTDIR/ +EOF + +tap3 'using -s' <<'EOF' +xe -s 'echo x$1' +<<< +1 +2 +3 +>>> +x1 +x2 +x3 +EOF + +tap3 'using -s with -N0' <<'EOF' +xe -N0 -s 'echo x$@' +<<< +1 +2 +3 +>>> +x1 2 3 +EOF + +tap3 'using -s with -a' <<'EOF' +xe -s 'echo x$@' -a 1 2 3 +>>> +x1 +x2 +x3 +EOF + +tap3 'using -s with -a' <<'EOF' +xe -a -s 'echo x$@' 1 2 3 +>>> +x1 +x2 +x3 +EOF + +tap3 'using -s with -a' <<'EOF' +xe -a -s 'echo x$@' -- 1 2 3 +>>> +x1 +x2 +x3 +EOF + +tap3 'with ITER' <<'EOF' +xe -a -s 'echo $ITER' -- a b c +>>> +1 +2 +3 +EOF diff --git a/t/slow.t b/t/slow.t new file mode 100755 index 0000000..74ba2e9 --- /dev/null +++ b/t/slow.t @@ -0,0 +1,43 @@ +#!/bin/sh +export "PATH=.:$PATH" + +printf '1..4\n' +printf '# slow tests\n' + +tap3 'is eager' <<'EOF' +{ { echo 1; sleep 1; echo 11 >/dev/stderr; echo 2; } | xe echo; } 2>&1 +>>> +1 +11 +2 +EOF + +tap3 'using -L' <<'EOF' +{ echo 1; sleep 1; + echo 2; sleep 1; + echo 3; } | + xe -j2 -L -s 'printf $1; sleep 1; echo $1' +>>> +11 +22 +33 +EOF + +tap3 'using -LL' <<'EOF' +{ echo 1; sleep 1; + echo 2; sleep 1; + echo 3; } | + xe -j2 -LL -s 'printf $1; sleep 1; echo $1' +>>> +0001= 11 +0002= 22 +0003= 33 +EOF + +tap3 'using -vvL' <<'EOF' +{ echo 1; sleep 1; + echo 2; sleep 1; + echo 3; } | + xe -j2 -vvL -s 'printf %s $1; sleep 1; echo $1' | wc -l +>>> /\s*9$/ +EOF diff --git a/tap3 b/tap3 new file mode 100755 index 0000000..53ddc80 --- /dev/null +++ b/tap3 @@ -0,0 +1,105 @@ +#!/usr/bin/perl -w +# tap3 [DESC] - check output/error/status of a command against a specification +# +# A tiny variant of shelltestrunner (format v1), just takes one test +# case and outputs a TAP line. +# +# Input format: +# +# CMD +# <<< +# INPUT +# >>> +# OUTPUT +# >>> /OUTPUT REGEX/ +# >>>2 +# STDERR +# >>>2 /STDERR REGEX/ +# >>>= STATUS +# >>>= !STATUS +# +# All but CMD are optional and can be put in any order, +# By default, STATUS is set to 0 and STDERR assumed empty. +# +# To the extent possible under law, the creator of this work has waived +# all copyright and related or neighboring rights to this work. +# http://creativecommons.org/publicdomain/zero/1.0/ + +use strict; +use Symbol 'gensym'; +use IPC::Open3; + +my $cmd = ""; +my ($input, $output, $output_rx, $stderr, $stderr_rx, $status, $status_not); +my $ignored = ""; + +my $var = \$cmd; +while (<STDIN>) { + if (/^#!? /) { next; } + if (/^<<<$/) { $var = \$input; $input = ""; next; } + if (/^>>>$/) { $var = \$output; $output = ""; next; } + if (/^>>>2$/) { $var = \$stderr; $stderr = ""; next; } + if (/^>>>\s*\/(.*)\/$/) { $output_rx = $1; next; } + if (/^>>>2\s*\/(.*)\/$/) { $stderr_rx = $1; next; } + if (/^>>>=\s+(\d+)$/) { $var = \$ignored; $status = $1; next; } + if (/^>>>=\s+!(\d+)$/) { $var = \$ignored; $status_not = $1; next; } + $$var .= $_; +} + +chomp($cmd); +die "No command to check given\n" if !$cmd; + +my ($wtr, $rdr); +my $err = gensym; +my $pid = open3($wtr, $rdr, $err, "/bin/sh", "-c", $cmd); + +my $desc = shift || $cmd; + +print $wtr $input if (defined($input)); +close $wtr; +my $real_output = do { local $/; <$rdr>; }; +my $real_stderr = do { local $/; <$err>; }; +waitpid($pid, 0); +my $real_status = $? >> 8; + +my $r = 0; + +sub not_ok { + print "not ok - $desc\n" if (!$r); + $r = 1; + $_[0] =~ s/^/# /mg; + print $_[0]; +} + +if (defined($output) && $real_output ne $output) { + not_ok("wrong output:\n$real_output"); +} +if (defined($output_rx) && $real_output !~ $output_rx) { + not_ok("output doesn't match /$output_rx/:\n$real_output\n"); +} +if (defined($stderr) && $real_stderr ne $stderr) { + not_ok("wrong stderr:\n$real_stderr"); +} +if (defined($stderr_rx) && $real_stderr !~ $stderr_rx) { + not_ok("stderr doesn't match /$stderr_rx/:\n$real_stderr\n"); +} +if (!defined($stderr) && !defined($stderr_rx) && + !defined($status) && !defined($status_not) && + $real_stderr) { + not_ok("output to stderr:\n$real_stderr\n"); +} +if (defined($status) && $real_status != $status) { + not_ok("wrong status: $real_status (expected $status)\n"); +} +if (defined($status_not) && $real_status == $status_not) { + not_ok("wrong status: $real_status (expected anything else)\n"); +} +if (!defined($status) && !defined($status_not) && + !defined($stderr) && !defined($stderr_rx) && + $real_status != 0) { + not_ok("wrong status: $real_status (command failed)\n"); +} + +print "ok - $desc\n" if (!$r); + +exit $r; diff --git a/tests b/tests deleted file mode 100755 index 6a035a4..0000000 --- a/tests +++ /dev/null @@ -1,361 +0,0 @@ -#!/bin/sh -printf '1..60\n' - -set -e - -xe() { "${XE:-./xe}" "$@"; } - -necho() { for a; do printf '%s\n' "$a"; done; } - -check_output() { - msg=$1 - expected="$(cat)" - shift - if output="$(eval "$@" 2>&1)"; then - if [ "$output" = "$expected" ]; then - printf 'ok - %s\n' "$msg" - return - fi - fi - printf 'not ok - %s\n' "$msg" - if [ "$output" != "$expected" ]; then - printf 'Unexpected output:\n%s\n' "$output" | sed 's/^/# /' - fi -} - -printf '# simple tests\n' - -check_output 'single argument run' 'necho 1 2 3 | xe echo' <<EOF -1 -2 -3 -EOF - -check_output 'dual argument run' 'necho 1 2 3 4 5 | xe -N2 echo' <<EOF -1 2 -3 4 -5 -EOF - -check_output 'unlimited argument run' 'necho 1 2 3 4 5 | xe -N0 echo' <<EOF -1 2 3 4 5 -EOF - -check_output 'empty input run' 'true | xe echo a' <<EOF -EOF - -check_output 'dry run' 'necho a b c | xe -n echo x' <<EOF -echo x a -echo x b -echo x c -EOF - -check_output 'dry run quoting' 'necho a "b b" c | xe -n echo x' <<EOF -echo x a -echo x 'b b' -echo x c -EOF - -check_output 'verbose run' 'necho a b c | xe -v echo x' <<EOF -echo x a -x a -echo x b -x b -echo x c -x c -EOF - -check_output 'with no command' 'necho 1 2 3 | xe -N2' <<EOF -1 -2 -3 -EOF - -check_output 'using {}' 'necho 1 2 3 | xe echo a {} x' <<EOF -a 1 x -a 2 x -a 3 x -EOF - -check_output 'using {} twice' 'necho 1 2 3 | xe echo {} x {}' <<EOF -1 x {} -2 x {} -3 x {} -EOF - -check_output 'using -I%' 'necho 1 2 3 | xe -I% echo {} x %' <<EOF -{} x 1 -{} x 2 -{} x 3 -EOF - -check_output 'using -I "" to disable' 'necho 1 2 3 | xe -I "" echo {} x %' <<EOF -{} x % 1 -{} x % 2 -{} x % 3 -EOF - -check_output 'using {} with multiple arguments' 'necho 1 2 3 | xe -N2 echo a {} x {}' <<EOF -a 1 2 x {} -a 3 x {} -EOF - -check_output 'using -0' 'printf "foo\0bar\0quux" | xe -0 echo' <<EOF -foo -bar -quux -EOF - -check_output 'using -a' 'xe -a echo -- 1 2 3' <<EOF -1 -2 -3 -EOF - -check_output 'using -a with no arguments' 'xe -a echo' <<EOF -EOF - -check_output 'using -a with no command' 'xe -N2 -a -- 1 2 3' <<EOF -1 -2 -3 -EOF - -check_output 'using -A%' 'xe -A% echo -- % 1 2 3' <<EOF --- 1 --- 2 --- 3 -EOF - -check_output 'using -A% with no arguments' 'xe -A% echo || true' <<EOF -xe: '-A %' used but no separator '%' found in command line. -EOF - -check_output 'using -A% with no command' 'xe -N2 -A% % 1 2 3' <<EOF -1 -2 -3 -EOF - -check_output 'using -f' 'necho notme | xe -f tests echo | grep ^notme || echo success' <<EOF -success -EOF - -check_output 'using -s' 'necho 1 2 3 | xe -s "echo x\$1"' <<EOF -x1 -x2 -x3 -EOF - -check_output 'using -s with -N0' 'necho 1 2 3 | xe -N0 -s "echo x\$@"' <<EOF -x1 2 3 -EOF - -check_output 'using -s with -a' 'xe -s "echo x\$@" -a 1 2 3' <<EOF -x1 -x2 -x3 -EOF - -check_output 'using -s with -a' 'xe -a -s "echo x\$@" 1 2 3' <<EOF -x1 -x2 -x3 -EOF - -check_output 'using -s with -a' 'xe -a -s "echo x\$@" -- 1 2 3' <<EOF -x1 -x2 -x3 -EOF - -check_output 'with ITER' 'xe -a -s "echo \$ITER" -- a b c' <<EOF -1 -2 -3 -EOF - -check_output 'is eager' '{ echo 1; sleep 1; echo 11 >/dev/stderr; echo 2; } | xe echo' <<EOF -1 -11 -2 -EOF - -check_output 'using -L' '{ echo 1; sleep 1; echo 2; sleep 1; echo 3; } | xe -j2 -L -s "printf \$1; sleep 1; echo \$1"' <<EOF -11 -22 -33 -EOF - -check_output 'using -LL' '{ echo 1; sleep 1; echo 2; sleep 1; echo 3; } | xe -j2 -LL -s "printf \$1; sleep 1; echo \$1"' <<EOF -0001= 11 -0002= 22 -0003= 33 -EOF - -check_output 'using -vvL' '{ echo 1; sleep 1; echo 2; sleep 1; echo 3; } | xe -j2 -vvL -s "printf %s \$1; sleep 1; echo \$1" | wc -l | tr -d " "' <<EOF -9 -EOF - -printf '# error handling\n' - -check_output 'exit code on success' 'true | xe; echo $?' <<EOF -0 -EOF - -check_output 'exit code on other error' 'true | xe -j NaN 2>/dev/null || echo $?' <<EOF -1 -EOF - -check_output 'exit code on when command fails with 1-125' 'necho a | xe -s "exit 42" || echo $?' <<EOF -123 -EOF - -check_output 'exit code on when command fails with 255' 'necho a | xe -s "exit 255" 2>/dev/null || echo $?' <<EOF -124 -EOF - -check_output 'exit code when process was killed' 'necho a | xe perl -e '\''kill "KILL", $$'\'' 2>/dev/null || echo $?' <<EOF -125 -EOF - -# possible false positive result when exec returns ENOENT instead of ENOTDIR here -check_output 'exit code when command cannot be run' 'necho a | xe /dev/null/calc.exe 2>/dev/null || echo $?' <<EOF -126 -EOF - -check_output 'exit code when command was not found' 'necho a | xe /bin/calc.exe 2>/dev/null || echo $?' <<EOF -127 -EOF - -check_output 'exit code on empty input when run with -R' 'true | xe -R echo a || echo $?' <<EOF -122 -EOF - -check_output 'doesn'\''t stop on errors by default' 'necho a b c | xe -s "if [ b = \$1 ]; then false; else echo \$1; fi" || echo $?' <<EOF -a -c -123 -EOF - -check_output 'stops on first error with -F' 'necho a b c | xe -F -s "if [ b = \$1 ]; then false; else echo \$1; fi" 2>/dev/null || echo $?' <<EOF -a -123 -EOF - -check_output 'should close stdin when arguments were read from it' 'necho a b c | xe -s "sed q"' <<EOF -EOF - -check_output 'should not close stdin when arguments were read from command line' 'yes | xe -a -s "sed q" -- 1 2 3' <<EOF -y -y -y -EOF - -check_output 'should not close stdin when arguments were read from file' 'yes | xe -f tests -s "sed q" 2>&1 | sed 3q' <<EOF -y -y -y -EOF - -printf '# regressions\n' - -check_output '0fb64a4 quoting of empty strings' 'printf "foo\n\n" | xe -N2 -v true' <<EOF -true foo '' -EOF - -printf '# limit checks, expecting maximal POSIX limits available\n' - -check_output 'argscap check' 'dd if=/dev/zero bs=1 count=17711 2>/dev/null | tr "\0" "\012" | xe -N0 -s "echo \$#"' <<EOF -8187 -8187 -1337 -EOF - -bloat() { perl -e 'print "x"x8000, "\n" for 1..42'; } -check_output 'argslen check' 'bloat | xe -N0 -s "echo \$#"' <<EOF -16 -16 -10 -EOF - -printf '# percent rules\n' - -check_output 'literal matches' 'xe -ap bcd echo found -- abc bcd defg' <<EOF -found -EOF - -check_output 'multiple patterns' 'xe -ap one echo 1 + two echo 2 + three echo 3 -- zero one two three four five' <<EOF -1 -2 -3 -EOF - -check_output '{} expansion' 'xe -ap bcd echo {} -- abc bcd defg' <<EOF -bcd -EOF - -check_output '% expansion' 'xe -ap bcd echo % -- abc bcd defg' <<EOF -bcd -EOF - -check_output 'dirnames' 'xe -ap bcd echo % -- abc bcd /tmp/bcd /tmp/abc' <<EOF -bcd -/tmp/bcd -EOF - -check_output '? glob' 'xe -ap "b?d" echo % -- abc bcd b3d defg' <<EOF -bcd -b3d -EOF - -check_output '* glob' 'xe -ap "b*d" echo % -- bd bed bad bugged bx zbd b/d' <<EOF -bd -bed -bad -bugged -EOF - -check_output 'multiple * glob' 'xe -ap "b*g*d" echo % -- bd bed bugged bx zbd bagdad badger ba/gd/ad' <<EOF -bugged -bagdad -EOF - -check_output 'multiple ** glob' 'xe -ap "b**g**d" echo % -- bd bed bugged bx zbd bagdad badger ba/gd/ad' <<EOF -bugged -bagdad -ba/gd/ad -EOF - -check_output '/ slash' 'xe -ap a/b echo 1 + c///d echo 2 + "*" echo 3 -- a/b a//b a/ b c/d /c////d' <<EOF -1 -1 -3 -3 -2 -3 -EOF - -check_output '[] ranges' 'xe -ap "[abc]" echo "1%" + "[d-g]" echo "2%" + "[^xyz-]" echo "3%" + "[!-vw]" echo "4%" + % echo "5%" -- a c d e g h w x -' <<EOF -1a -1c -2d -2e -2g -3h -3w -4x -5- -EOF - -check_output '{} alternation' 'xe -ap "{a,bc,def*}" echo % -- x a abc bc bcd def defx xdef' <<EOF -a -bc -def -defx -EOF - -check_output '% match' 'xe -ap %.c echo obj/%.o -- foo.c bar.cc meh/quux.c' <<EOF -obj/foo.o -meh/obj/quux.o -EOF |