From 00c71799b538542e2d31e47407f78646f1eebd3a Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Mon, 4 Nov 2024 19:06:08 +0900 Subject: [PATCH] Update tests for POSIX.1-2024 This commit adds test cases for the requirements that were added in POSIX.1-2024 and are already implemented in yash. - Some test cases in bg-p.tst and fg-p.tst no longer examines the standard error because POSIX allows the shell to report suspension of background jobs, which should not fail the test. - Some comments in the test scripts are updated to reflect the changes to POSIX. --- tests/POSIX | 30 +++++++++++++++++++++++------- tests/bg-p.tst | 14 +++++++------- tests/builtins-p.tst | 5 +---- tests/command-y.tst | 1 - tests/dot-p.tst | 7 +++++++ tests/exec-p.tst | 11 +++++++++++ tests/exit-p.tst | 6 +++--- tests/fg-p.tst | 13 +++++++++---- tests/getopts-p.tst | 25 +++++++++++++++++++++++-- tests/read-p.tst | 9 +++++++++ tests/read-y.tst | 11 ----------- tests/test-p.tst | 38 ++++++++++++++++++++++++++++++++++++++ tests/test1-y.tst | 26 -------------------------- tests/test2-y.tst | 9 +-------- 14 files changed, 132 insertions(+), 73 deletions(-) diff --git a/tests/POSIX b/tests/POSIX index aefcb5a1..22dff8ca 100644 --- a/tests/POSIX +++ b/tests/POSIX @@ -86,15 +86,28 @@ Volume 3: Shell & Utilities * error-p.tst 2.9.1 Simple Commands + +2.9.1.1 Order of Processing + * simple-p.tst + +2.9.1.2 Variable Assignments * builtins-p.tst + * simple-p.tst + +2.9.1.3 Commands with no Command Name * redir-p.tst * simple-p.tst -Command Search and Execution +2.9.1.4 Command Search and Execution * builtins-p.tst * builtins-y.tst * simple-p.tst +2.9.1.5 Standard File Descriptors + +2.9.1.6 Non-built-in Utility Execution + * simple-p.tst + 2.9.2 Pipelines * pipeline-p.tst * pipeline-y.tst @@ -126,21 +139,24 @@ Command Search and Execution * trap-p.tst * wait-p.tst -2.12 Shell Execution Environment +2.12 Job Control + * job-p.tst + +2.13 Shell Execution Environment * trap-p.tst -2.13 Pattern Matching Notation +2.14 Pattern Matching Notation -2.13.1 Patterns Matching a Single Character +2.14.1 Patterns Matching a Single Character * fnmatch-p.tst -2.13.2 Patterns Matching Multiple Characters +2.14.2 Patterns Matching Multiple Characters * fnmatch-p.tst -2.13.3 Patterns Used for Filename Expansion +2.14.3 Patterns Used for Filename Expansion * path-p.tst -2.14 Special Built-In Utilities +2.15 Special Built-In Utilities * builtins-p.tst break diff --git a/tests/bg-p.tst b/tests/bg-p.tst index 73fe0e5a..8ec7ee4d 100644 --- a/tests/bg-p.tst +++ b/tests/bg-p.tst @@ -15,7 +15,7 @@ test_O -d -e n 'bg cannot be used when job control is disabled' +m bg __IN__ -test_oE 'default operand chooses most recently suspended job' -m +test_o 'default operand chooses most recently suspended job' -m :& sh -c 'kill -s STOP $$; echo 1' bg >/dev/null @@ -30,13 +30,13 @@ bg >/dev/null kill % __IN__ -test_OE -e 17 'resumed job is awaitable' -m +test_O -e 17 'resumed job is awaitable' -m sh -c 'kill -s STOP $$; exit 17' bg >/dev/null wait % __IN__ -test_oE 'resumed job is in background' -m +test_o 'resumed job is in background' -m sh -c 'kill -s STOP $$; ../checkfg || echo bg' bg >/dev/null wait % @@ -44,7 +44,7 @@ __IN__ bg __OUT__ -test_oE 'specifying job ID' -m +test_o 'specifying job ID' -m ./job1 ./job2 echo - @@ -57,7 +57,7 @@ __IN__ __OUT__ -test_oE 'specifying more than one job ID' -m +test_o 'specifying more than one job ID' -m ./job1 ./job2 echo - @@ -69,13 +69,13 @@ __IN__ __OUT__ -test_OE -e 0 'bg prints resumed job' -m +test_O -e 0 'bg prints resumed job' -m sleep 1& bg >bg.out grep -q '^\[[[:digit:]][[:digit:]]*][[:blank:]]*sleep 1' bg.out __IN__ -test_OE -e 0 'exit status of bg' -m +test_O -e 0 'exit status of bg' -m sh -c 'kill -s STOP $$; exit 17' bg >/dev/null __IN__ diff --git a/tests/builtins-p.tst b/tests/builtins-p.tst index f8d08fc5..2bb1f348 100644 --- a/tests/builtins-p.tst +++ b/tests/builtins-p.tst @@ -226,7 +226,6 @@ test_nonspecial_builtin_function_override "$LINENO" getopts test_nonspecial_builtin_function_override "$LINENO" hash test_nonspecial_builtin_function_override "$LINENO" jobs test_nonspecial_builtin_function_override "$LINENO" kill -test_nonspecial_builtin_function_override "$LINENO" newgrp test_nonspecial_builtin_function_override "$LINENO" pwd test_nonspecial_builtin_function_override "$LINENO" read test_nonspecial_builtin_function_override "$LINENO" true @@ -237,6 +236,7 @@ test_nonspecial_builtin_function_override "$LINENO" unalias test_nonspecial_builtin_function_override "$LINENO" wait test_nonspecial_builtin_function_override "$LINENO" grep +test_nonspecial_builtin_function_override "$LINENO" newgrp test_nonspecial_builtin_function_override "$LINENO" sed ( @@ -353,9 +353,6 @@ test_OE -e 0 'intrinsic built-in kill can be invoked without $PATH' kill -0 $$ __IN__ -# Many shells including yash does not implement newgrp as a built-in. -#TODO: test_OE -e 0 'intrinsic built-in newgrp can be invoked without $PATH' - test_E -e 0 'intrinsic built-in pwd can be invoked without $PATH' pwd __IN__ diff --git a/tests/command-y.tst b/tests/command-y.tst index d834e067..c7e1026d 100644 --- a/tests/command-y.tst +++ b/tests/command-y.tst @@ -80,7 +80,6 @@ trap: a special built-in unset: a special built-in __OUT__ -# `newgrp' is not a mandatory built-in in yash. test_oE -e 0 'describing mandatory built-ins (-V)' command -V alias bg cd command false fg getopts hash jobs kill pwd read true \ type umask unalias wait diff --git a/tests/dot-p.tst b/tests/dot-p.tst index 794b9f8a..b545a896 100644 --- a/tests/dot-p.tst +++ b/tests/dot-p.tst @@ -44,6 +44,13 @@ __IN__ exit 11 __ERR__ +test_oE -e 3 'option-operand separator' +(exit 5) +. -- ./file1 +__IN__ +5 +__OUT__ + ( # Ensure $PWD is safe to assign to $PATH case $PWD in (*[:%]*) diff --git a/tests/exec-p.tst b/tests/exec-p.tst index b2254b2d..1dd2f6c9 100644 --- a/tests/exec-p.tst +++ b/tests/exec-p.tst @@ -12,6 +12,13 @@ __IN__ reached __OUT__ +test_oE 'exec without arguments but -- separator' +exec -- +echo $? +__IN__ +0 +__OUT__ + test_Oe 'exec with redirections' exec >&2 2>/dev/null echo reached @@ -41,6 +48,10 @@ test_OE -e 0 'executing external command with option' exec cat -u /dev/null __IN__ +test_OE -e 0 'executing external command with -- separator' +exec -- cat /dev/null +__IN__ + test_OE -e 0 'process ID of executed process' exec sh -c "[ \$\$ -eq $$ ]" __IN__ diff --git a/tests/exit-p.tst b/tests/exit-p.tst index ca01407f..c2e4afab 100644 --- a/tests/exit-p.tst +++ b/tests/exit-p.tst @@ -70,9 +70,9 @@ trap '(exit 1); exit' EXIT exit __IN__ -# POSIX says the exit status in this case should be that of "the command that -# executed immediately preceding the trap action." Many shells including yash -# interprets it as the exit status of "exit" rather than "trap." +# POSIX says the exit status in this case should be "the value (of the special +# parameter '?') it had immediately preceding the trap action." Many shells +# including yash interpret it as the exit status of "exit" rather than "trap." test_OE -e 1 'default exit status in EXIT trap in exiting with 1' trap exit EXIT exit 1 diff --git a/tests/fg-p.tst b/tests/fg-p.tst index 18c036e5..ef0b6423 100644 --- a/tests/fg-p.tst +++ b/tests/fg-p.tst @@ -21,7 +21,7 @@ test_O -d -e n 'fg cannot be used when job control is disabled' +m fg __IN__ -test_oE 'default operand chooses most recently suspended job' -m +test_o 'default operand chooses most recently suspended job' -m :& sh -c 'kill -s STOP $$; echo 1' fg >/dev/null @@ -29,7 +29,7 @@ __IN__ 1 __OUT__ -test_oE 'resumed job is in foreground' -m +test_o 'resumed job is in foreground' -m sh -c 'kill -s STOP $$; ../checkfg && echo fg' fg >/dev/null __IN__ @@ -45,7 +45,7 @@ fg >/dev/null wait $! __IN__ -test_oE 'specifying job ID' -m +test_o 'specifying job ID' -m ./job1 ./job2 fg %./job1 >/dev/null @@ -57,7 +57,7 @@ a b __OUT__ -test_oE 'fg prints resumed job' -m +test_o 'fg prints resumed job' -m ./job1 fg __IN__ @@ -66,6 +66,11 @@ __IN__ 2 __OUT__ +test_x -e 42 'exit status of fg' -m +sh -c 'kill -s STOP $$; exit 42' +fg +__IN__ + test_O -d -e n 'no existing job' -m fg __IN__ diff --git a/tests/getopts-p.tst b/tests/getopts-p.tst index 8775fa5a..0f5f021a 100644 --- a/tests/getopts-p.tst +++ b/tests/getopts-p.tst @@ -35,13 +35,34 @@ getopts ab:c o -a -b arg -c getopts ab:c o -a -b arg -c __IN__ -test_x -e n 'exit status is non-zero after parsing all options' -e +test_x -e 1 'exit status is one after parsing all options' -e getopts ab:c o -a -b arg -c getopts ab:c o -a -b arg -c getopts ab:c o -a -b arg -c getopts ab:c o -a -b arg -c __IN__ +test_o 'OPTIND is set when option argument is parsed: empty' +getopts a:b o -a '' -b +echo "[$OPTIND]" +__IN__ +[3] +__OUT__ + +test_o 'OPTIND is set when option argument is parsed: non-empty separate' +getopts a:b o -a '-x foo' -b +echo "[$OPTIND]" +__IN__ +[3] +__OUT__ + +test_o 'OPTIND is set when option argument is parsed: non-empty adjoined' +getopts a:b o -a' foo' -b +echo "[$OPTIND]" +__IN__ +[2] +__OUT__ + test_o 'OPTARG is set when option argument is parsed: empty' getopts a: o -a '' echo "[$OPTARG]" @@ -163,7 +184,7 @@ __IN__ 4[?] __OUT__ -test_x -e n 'single hyphen is not option' +test_x -e 1 'single hyphen is not an option but an operand' getopts '' x - __IN__ diff --git a/tests/read-p.tst b/tests/read-p.tst index 8c7ed0c5..69cf1b92 100644 --- a/tests/read-p.tst +++ b/tests/read-p.tst @@ -259,6 +259,15 @@ __IN__ 0 [A] [B] [] [D] [E] [- F\] __OUT__ +test_oE 'input ending without newline' +printf 'A' | { +read a +echo $? $a +} +__IN__ +1 A +__OUT__ + test_oE 'in subshell' (echo A | read a) echoraw $? "[${a-unset}]" diff --git a/tests/read-y.tst b/tests/read-y.tst index d185396e..85cec302 100644 --- a/tests/read-y.tst +++ b/tests/read-y.tst @@ -13,17 +13,6 @@ typeset b='' typeset c='' __OUT__ -test_oE 'input ending without newline' -printf 'A' | { -read a -echo $? -typeset -p a -} -__IN__ -1 -typeset a=A -__OUT__ - test_oE 'input ending with backslash - not raw mode' printf '%s' 'A\' | { read a diff --git a/tests/test-p.tst b/tests/test-p.tst index aa46b159..b77035d0 100644 --- a/tests/test-p.tst +++ b/tests/test-p.tst @@ -21,6 +21,7 @@ chmod u+s setuserid mkfifo fifo +ln file hardlink ln -s file filelink ln -s _no_such_file_ brokenlink ln -s unreadable unreadablelink @@ -34,6 +35,11 @@ ln -s setgroupid setgroupidlink ln -s setuserid setuseridlink ln -s fifo fifolink +touch -t 200001010000 older +touch -t 200101010000 newer +touch -a -t 200101010000 old; touch -m -t 200001010000 old +touch -a -t 200001010000 new; touch -m -t 200101010000 new + # $1 = $LINENO, $2 = expected exit status, $3... = expression assert() ( setup <<\__END__ @@ -334,6 +340,38 @@ assert_false 0 -le -3 assert_false 90 -le -3 assert_true 0 -le 0 +# The behavior of the < and > operators cannot be fully tested. +assert_false 11 '<' 100 +assert_false 11 '<' 11 +assert_true 100 '<' 11 + +assert_true 11 '>' 100 +assert_false 11 '>' 11 +assert_false 100 '>' 11 + +assert_true XXXXX -ot newer +assert_false XXXXX -ot XXXXX +assert_false newer -ot XXXXX +assert_true older -ot newer +assert_false newer -ot newer +assert_false newer -ot older + +assert_false XXXXX -nt newer +assert_false XXXXX -nt XXXXX +assert_true newer -nt XXXXX +assert_false older -nt newer +assert_false older -nt older +assert_true newer -nt older + +assert_false XXXXX -ef newer +assert_false XXXXX -ef XXXXX +assert_false newer -ef XXXXX +assert_false older -ef newer +assert_true older -ef older +assert_false newer -ef older +assert_true file -ef hardlink +assert_false file -ef newer + assert_false "" -a "" assert_false "" -a 1 assert_false 1 -a "" diff --git a/tests/test1-y.tst b/tests/test1-y.tst index 76280179..0af85966 100644 --- a/tests/test1-y.tst +++ b/tests/test1-y.tst @@ -11,10 +11,7 @@ umask u=rwx,go= >file ln -s file filelink ln -s _no_such_file_ brokenlink -ln file hardlink -touch -t 200001010000 older -touch -t 200101010000 newer touch -a -t 200101010000 old; touch -m -t 200001010000 old touch -a -t 200001010000 new; touch -m -t 200101010000 new @@ -93,29 +90,6 @@ assert_true -o \?nonotify assert_true -o \?n-o-n-otify ) -assert_true XXXXX -ot newer -assert_false XXXXX -ot XXXXX -assert_false newer -ot XXXXX -assert_true older -ot newer -assert_false newer -ot newer -assert_false newer -ot older - -assert_false XXXXX -nt newer -assert_false XXXXX -nt XXXXX -assert_true newer -nt XXXXX -assert_false older -nt newer -assert_false older -nt older -assert_true newer -nt older - -assert_false XXXXX -ef newer -assert_false XXXXX -ef XXXXX -assert_false newer -ef XXXXX -assert_false older -ef newer -assert_true older -ef older -assert_false newer -ef older -assert_true file -ef hardlink -assert_false file -ef newer - assert_true 1 -a "(" 1 = 0 -o "(" 2 = 2 ")" ")" -a "(" = ")" assert_true -n = -o -o -n = -n # ( -n = -o ) -o ( -n = -n ) assert_true -n = -a -n = -n # ( -n = ) -a ( -n = -n ) diff --git a/tests/test2-y.tst b/tests/test2-y.tst index 5d594edf..51eac455 100644 --- a/tests/test2-y.tst +++ b/tests/test2-y.tst @@ -16,6 +16,7 @@ assert_true == == == assert_false "(" == ")" # The behavior of the ===, !==, <, <=, >, >= operators cannot be fully tested. +# The < and > operators are tested in test-p.tst. assert_true "" === "" assert_true 1 === 1 assert_true abcde === abcde @@ -34,18 +35,10 @@ assert_false ! !== ! assert_false !== !== !== assert_true "(" !== ")" -assert_false 11 '<' 100 -assert_false 11 '<' 11 -assert_true 100 '<' 11 - assert_false 11 '<=' 100 assert_true 11 '<=' 11 assert_true 100 '<=' 11 -assert_true 11 '>' 100 -assert_false 11 '>' 11 -assert_false 100 '>' 11 - assert_true 11 '>=' 100 assert_true 11 '>=' 11 assert_false 100 '>=' 11