https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7f8792e0056f6763cf2b3d...
commit 7f8792e0056f6763cf2b3de0ca052a35f784fa8b Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Mon Jul 27 00:30:24 2020 +0200 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Wed Aug 19 20:35:58 2020 +0200
[CMD_ROSTEST] Add tests for batch execution flow with GOTO and CALL commands.
- Tests for GOTO across IF parenthesized block (parser test with line continuation at closing parenthesis).
- Tests for showing how FOR-loops stop when a GOTO is encountered.
- Tests for EXIT command within IF block. --- modules/rostests/win32/cmd/rsrc.rc | 6 + modules/rostests/win32/cmd/test_goto_call.cmd | 239 ++++++++++++++++++++++ modules/rostests/win32/cmd/test_goto_call.cmd.exp | 214 +++++++++++++++++++ 3 files changed, 459 insertions(+)
diff --git a/modules/rostests/win32/cmd/rsrc.rc b/modules/rostests/win32/cmd/rsrc.rc index 7196b345f36..638cd3ae1a5 100644 --- a/modules/rostests/win32/cmd/rsrc.rc +++ b/modules/rostests/win32/cmd/rsrc.rc @@ -28,3 +28,9 @@ test_echoer_parser.cmd TESTCMD "test_echoer_parser.cmd"
/* @makedep: test_echoer_parser.cmd.exp */ test_echoer_parser.cmd.exp TESTOUT "test_echoer_parser.cmd.exp" + +/* @makedep: test_goto_call.cmd */ +test_goto_call.cmd TESTCMD "test_goto_call.cmd" + +/* @makedep: test_goto_call.cmd.exp */ +test_goto_call.cmd.exp TESTOUT "test_goto_call.cmd.exp" diff --git a/modules/rostests/win32/cmd/test_goto_call.cmd b/modules/rostests/win32/cmd/test_goto_call.cmd new file mode 100644 index 00000000000..44add4cd9ec --- /dev/null +++ b/modules/rostests/win32/cmd/test_goto_call.cmd @@ -0,0 +1,239 @@ +@echo off +setlocal enableextensions +setlocal enabledelayedexpansion + + +:: +:: Tests for GOTO and CALL. +:: + + + +:: +:: Testing GOTO/CALL from and to within parenthesized blocks. +:: + +echo --------- Testing GOTO within block --------- +(echo Block-test 1: Single-line& goto :block2 & echo Unexpected Block-test 1^^!) +echo Unexpected echo 1^^! + +:block2 +( +echo Block-test 2: Multi-line +goto :block3 +echo Unexpected Block-test 2^^! +) +echo Unexpected echo 2-3^^! + +:test_call_block +echo Test CALL in block OK from %0 +:: We exit this CALL invocation +goto :EOF + +( +:block3 +echo --------- Testing CALL within block --------- +echo Block-test 3: CALL in block +call :test_call_block +echo CALL done +) + +goto :block4 +echo Unexpected echo 4^^! +( +:block4 +echo Block-test 4 OK +) + + +:: +:: Testing GOTO/CALL from within FOR and IF. +:: This is a situation similar to the parenthesized blocks. +:: See bug-report CORE-13713 +:: + +:: Testing CALL within FOR +echo --------- Testing CALL within FOR --------- +for /L %%A IN (0,1,3) DO ( + set Number=%%A + if %%A==2 call :out_of_loop_1 %%A + if %%A==2 (echo %%A IS equal to 2) else (echo %%A IS NOT equal to 2) +) +goto :continue_2 +:out_of_loop_1 +echo Out of FOR 1 CALL from %0, number is %1 +:: We exit this CALL invocation +goto :EOF +:continue_2 + + +:: Testing GOTO within FOR +echo --------- Testing GOTO within FOR --------- +for /L %%A IN (0,1,3) DO ( + set Number=%%A + if %%A==2 goto :out_of_loop_2 + echo %%A IS NOT equal to 2 +) +echo Unexpected FOR echo 2^^! +:out_of_loop_2 +echo Out of FOR 2, number is %Number% + + + +:: +:: Show how each different FOR-loop stops when a GOTO is encountered. +:: +echo --------- Testing FOR loop stopping with GOTO --------- + +:: FOR - Stops directly +echo --- FOR +@echo on +for %%A in (1,2,3,4,5,6,7,8,9,10) do ( + set Number=%%A + if %%A==5 goto :out_of_loop_2a +) +echo Unexpected FOR echo 2a^^! +:out_of_loop_2a +echo Out of FOR 2a, number is %Number% +@echo off + + +:: FOR /R - Stops directly +echo --- FOR /R + +:: Use auxiliary directoreis to test for /R +mkdir foobar && cd foobar +mkdir foo1 +mkdir foo2 +mkdir bar1 + +@echo on +for /r %%A in (1,2,3,4,5,6,7,8,9,10) do ( + set Number=%%~nA + if %%~nA==5 goto :out_of_loop_2b +) +echo Unexpected FOR echo 2b^^! +:out_of_loop_2b +echo Out of FOR 2b, number is %Number% +@echo off + +:: Cleanup +cd .. & rd /s/q foobar + + +:: FOR /L - Does not stop directly. It continues looping until the end +:: but does not execute its body code. This can cause problems e.g. for +:: infinite loops "for /l %a in () do ( ... )" that are exited by EXIT /B, +:: since the body code stops being executed, but the loop itself continues +:: running forever. +echo --- FOR /L +@echo on +for /l %%A in (1,1,10) do ( + set Number=%%A + if %%A==5 goto :out_of_loop_2c +) +echo Unexpected FOR echo 2c^^! +:out_of_loop_2c +echo Out of FOR 2c, number is %Number% +@echo off + + +:: FOR /F - Stops directly. +echo --- FOR /F +@echo on +for %%T in ( "1:2:3" "4:5:6:7" "8:9:10" ) do ( + set "pc=%%~T" + for /f "delims=" %%A in (^"!pc::^=^ +% New line % +!^") do ( + + set Number=%%A + if %%A==5 goto :out_of_loop_2d +) +) +echo Unexpected FOR echo 2d^^! +:out_of_loop_2d +echo Out of FOR 2d, number is %Number% +@echo off + + + +:: Testing CALL within IF +echo --------- Testing CALL within IF --------- +if 1==1 ( + call :out_of_if_1 123 + echo Success IF echo 1 +) +goto :continue_3 +:out_of_if_1 +echo Out of IF CALL from %0, number is %1 +:: We exit this CALL invocation +goto :EOF +:continue_3 + + +:: Testing GOTO within IF +echo --------- Testing GOTO within IF --------- +if 1==1 ( + goto :out_of_if_2 + echo Unexpected IF echo 2a^^! +) +echo Unexpected IF echo 2b^^! +:out_of_if_2 +echo Out of IF ok + +:: Same, but with line-continuation at the closing parenthesis of the IF block. +if 1==1 ( +:labelA + echo A +) ^ +else ( +:labelB + echo B + goto :continue +) +:: We are jumping inside the IF, whose block will be interpreted as +:: separate commands; thus we will also run the :labelB block as well. +goto :labelA + + +:: +:: Next suite of tests. +:: +:continue + +:: Testing EXIT within IF +echo --------- Testing EXIT within IF --------- + +:: Use a CALL context, and we will only check EXIT /B. +call :doExitIfTest 1 +call :doExitIfTest 2 +goto :finished + +:doExitIfTest +if %1==1 ( + echo First block + exit /b + echo Unexpected first block^^! +) else ( + echo Second block + exit /b + echo Unexpected second block^^! +) +echo You won't see this^^! +exit /b + + + +:: +:: Finished! +:: +:finished +echo --------- Finished -------------- +goto :EOF + +:: Subroutine to set errorlevel and return +:: in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported +:setError +exit /B %1 +:: This line runs under cmd in windows NT 4, but not in more modern versions. diff --git a/modules/rostests/win32/cmd/test_goto_call.cmd.exp b/modules/rostests/win32/cmd/test_goto_call.cmd.exp new file mode 100644 index 00000000000..802e6c5dca3 --- /dev/null +++ b/modules/rostests/win32/cmd/test_goto_call.cmd.exp @@ -0,0 +1,214 @@ +--------- Testing GOTO within block --------- +Block-test 1: Single-line +Block-test 2: Multi-line +--------- Testing CALL within block --------- +Block-test 3: CALL in block +Test CALL in block OK from :test_call_block +CALL done +Block-test 4 OK +--------- Testing CALL within FOR --------- +0 IS NOT equal to 2 +1 IS NOT equal to 2 +Out of FOR 1 CALL from :out_of_loop_1, number is 2 +2 IS equal to 2 +3 IS NOT equal to 2 +--------- Testing GOTO within FOR --------- +0 IS NOT equal to 2 +1 IS NOT equal to 2 +Out of FOR 2, number is 2 +--------- Testing FOR loop stopping with GOTO --------- +--- FOR + +@pwd@>for %A in (1 2 3 4 5 6 7 8 9 10) do ( +set Number=%A@space@@space@ + if %A == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>( +set Number=1@space@@space@ + if 1 == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>( +set Number=2@space@@space@ + if 2 == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>( +set Number=3@space@@space@ + if 3 == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>( +set Number=4@space@@space@ + if 4 == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>( +set Number=5@space@@space@ + if 5 == 5 goto :out_of_loop_2a@space@ +)@space@ + +@pwd@>echo Out of FOR 2a, number is 5@space@ +Out of FOR 2a, number is 5 +--- FOR /R + +@pwd@\foobar>for /R %A in (1 2 3 4 5 6 7 8 9 10) do ( +set Number=%~nA@space@@space@ + if %~nA == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>( +set Number=1@space@@space@ + if 1 == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>( +set Number=2@space@@space@ + if 2 == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>( +set Number=3@space@@space@ + if 3 == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>( +set Number=4@space@@space@ + if 4 == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>( +set Number=5@space@@space@ + if 5 == 5 goto :out_of_loop_2b@space@ +)@space@ + +@pwd@\foobar>echo Out of FOR 2b, number is 5@space@ +Out of FOR 2b, number is 5 +--- FOR /L + +@pwd@>for /L %A in (1 1 10) do ( +set Number=%A@space@@space@ + if %A == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=1@space@@space@ + if 1 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=2@space@@space@ + if 2 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=3@space@@space@ + if 3 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=4@space@@space@ + if 4 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=5@space@@space@ + if 5 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=6@space@@space@ + if 6 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=7@space@@space@ + if 7 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=8@space@@space@ + if 8 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=9@space@@space@ + if 9 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>( +set Number=10@space@@space@ + if 10 == 5 goto :out_of_loop_2c@space@ +)@space@ + +@pwd@>echo Out of FOR 2c, number is 5@space@ +Out of FOR 2c, number is 5 +--- FOR /F + +@pwd@>for %T in ("1:2:3" "4:5:6:7" "8:9:10") do ( +set "pc=%~T"@space@@space@ + for /F "delims=" %A in ("!pc::= +!") do ( +set Number=%A@space@@space@ + if %A == 5 goto :out_of_loop_2d@space@ +)@space@ +)@space@ + +@pwd@>( +set "pc=1:2:3"@space@@space@ + for /F "delims=" %A in ("!pc::= +!") do ( +set Number=%A@space@@space@ + if %A == 5 goto :out_of_loop_2d@space@ +)@space@ +)@space@ + +@pwd@>( +set Number=1@space@@space@ + if 1 == 5 goto :out_of_loop_2d@space@ +)@space@ + +@pwd@>( +set Number=2@space@@space@ + if 2 == 5 goto :out_of_loop_2d@space@ +)@space@ + +@pwd@>( +set Number=3@space@@space@ + if 3 == 5 goto :out_of_loop_2d@space@ +)@space@ + +@pwd@>( +set "pc=4:5:6:7"@space@@space@ + for /F "delims=" %A in ("!pc::= +!") do ( +set Number=%A@space@@space@ + if %A == 5 goto :out_of_loop_2d@space@ +)@space@ +)@space@ + +@pwd@>( +set Number=4@space@@space@ + if 4 == 5 goto :out_of_loop_2d@space@ +)@space@ + +@pwd@>( +set Number=5@space@@space@ + if 5 == 5 goto :out_of_loop_2d@space@ +)@space@ + +@pwd@>echo Out of FOR 2d, number is 5@space@ +Out of FOR 2d, number is 5 +--------- Testing CALL within IF --------- +Out of IF CALL from :out_of_if_1, number is 123 +Success IF echo 1 +--------- Testing GOTO within IF --------- +Out of IF ok +A +A +B +--------- Testing EXIT within IF --------- +First block +Second block +--------- Finished --------------