Reactos

[CMD_ROSTEST] Add tests for CALL label parsing, and for CALL and GOTO behaviour.

Tests adapted from https://stackoverflow.com/q/31987023/13530036
and from https://stackoverflow.com/a/38938416/13530036 .

- Test when CALL with a label containing /? actually calls GOTO's help,
and test when CALL's help is displayed instead.

- Test when CALL with a label containing /?, but specified by variables,
do NOT trigger GOTO's or CALL's help.

- Test the effect of the presence of escape carets in CALL label string.

- Test that CALL indeed supports double delayed expansion. Adapted from
https://stackoverflow.com/a/31990563/13530036 .

+316 -1
+270 -1
modules/rostests/win32/cmd/test_goto_call.cmd
··· 54 54 :: and the label name, as well as leading and trailing whitespace. 55 55 :@tab@continue@space@@space@ 56 56 57 + :: CALL does an extra round of variable substitution. 58 + 59 + :: Existing labels (see below) 60 + set VAR=TOTO 61 + call :dest%VAR% 62 + call :dest%%VAR%% 63 + call :dest!VAR! 64 + call :dest!!VAR!! 65 + 66 + set VAR=1 67 + call :dest%VAR% 68 + call :dest%%VAR%% 69 + call :dest!VAR! 70 + call :dest!!VAR!! 71 + 72 + :: Exercise different whitespace separations 73 + call :dest1@space@@tab@ a b c 74 + call @space@:dest1@space@@space@ 75 + 76 + :: Similar to GOTO, whitespace between ':' and the label name parameter are NOT ignored. 77 + call :setError 0 78 + call @space@:@space@dest1@space@@space@ 79 + if %errorlevel% equ 0 (echo Unexpected: CALL did not fail^^!) else echo OK 80 + 81 + :: Only GOTO understands '+' instead of ':'. 82 + :: Here '+dest1' is understood as a (non-existing) command. 83 + call :setError 0 84 + call @space@+dest1@space@@space@ 85 + if %errorlevel% equ 0 (echo Unexpected: CALL did not fail^^!) else echo OK 86 + 87 + 88 + :: Calling a label with escape carets. 89 + call :la^^bel1 57 90 58 91 :: Jumping to a label with escape carets. 59 92 goto :la^^bel2 60 93 94 + 95 + :: Label with percents (should not be called) 96 + :dest%%VAR%% 97 + echo Unexpected CALL/GOTO jump^^! 98 + 99 + :: Valid label (called from the variable substitution tests above) 100 + :destTOTO 101 + echo Hi there^^! 102 + :: We exit this CALL invocation 103 + goto :EOF 104 + 105 + :: Valid label with arbitrary first character before ':' 106 + :: (not just '@' as supposed by cmd_winetests!) 107 + ?:de^st1 108 + echo goto with unrelated first character, and escape carets worked 109 + echo Params: '%0', '%1', '%2', '%3' 110 + :: We exit this CALL invocation 111 + goto :EOF 112 + 113 + 114 + :: Label with escape carets 115 + :la^bel1 116 + echo Unexpected CALL jump^^! 117 + :la^^bel1 118 + echo CALL with escape caret worked 119 + :: We exit this CALL invocation 120 + goto :EOF 121 + 61 122 :la^bel2 62 123 echo Unexpected GOTO jump^^! 63 124 :la^^bel2 ··· 116 177 117 178 :: Use an auxiliary CMD file to test GOTO :EOF 118 179 mkdir foobar && cd foobar 180 + 181 + :: This CALL will fail: :EOF is indeed a reserved label for GOTO only. 182 + call :setError 0 183 + call :EOF 184 + if %errorlevel% equ 0 (echo Unexpected: CALL :EOF did not fail^^!) else echo OK 185 + 186 + :: This CALL will succeed silently: only the first ':' of ::EOF is stripped, 187 + :: thus calling in a new batch context GOTO :EOF. 188 + call :setError 0 189 + call ::EOF 190 + if %errorlevel% neq 0 (echo Unexpected: CALL ::EOF did fail^^!) else echo OK 119 191 120 192 :: GOTO :EOF is available only if commands extensions are enabled 121 193 echo @echo off> tmp.cmd ··· 366 438 :: Use a CALL context, and we will only check EXIT /B. 367 439 call :doExitIfTest 1 368 440 call :doExitIfTest 2 369 - goto :finished 441 + goto :continue 370 442 371 443 :doExitIfTest 372 444 if %1==1 ( ··· 379 451 echo Unexpected second block^^! 380 452 ) 381 453 echo You won't see this^^! 454 + exit /b 455 + 456 + 457 + :: 458 + :: Next suite of tests. 459 + :: 460 + :continue 461 + 462 + echo --------- Testing CALL (triggers GOTO /?) --------- 463 + 464 + :: 465 + :: Test that shows that CALL :label with the label name containing /? 466 + :: at delayed time, internally calls GOTO, and will end up calling GOTO /?, 467 + :: then jumps to the next command. 468 + :: 469 + :: Adapted from https://stackoverflow.com/q/31987023/13530036 470 + :: and from https://stackoverflow.com/a/38938416/13530036 471 + :: The author of this test calls that "anonymous functions". 472 + :: 473 + set "label=/?" 474 + 475 + :: Test 1: GOTO /? will be called. 476 + :: Since it is expected that the code below the CALL will also be called in 477 + :: its context, but we want its output to be redirected to STDOUT, we use a 478 + :: different redirection file so that it does not go into the tmp.txt file. 479 + echo --- Direct label, redirection 480 + 481 + :: Use an auxiliary CMD file 482 + mkdir foobar && cd foobar 483 + 484 + :: Call the label and redirect STDOUT to a file for later filtering. 485 + call :%%label%% argument > tmp.txt 486 + :: The following commands are called also within the CALL context. 487 + :: The message will be displayed both in the CALL context, and in the main one. 488 + echo Test message -- '%0','%*'>> tmpMsg.txt 489 + :: Within the CALL context, this is the expected value of %0. Quit early. 490 + if "%0" == ":/?" ( 491 + echo Arguments: '%*'>> tmpMsg.txt 492 + exit /B 493 + ) 494 + 495 + :: Back to the main context. 496 + :: Display the redirected messages, filtering out the batch file name. 497 + for /f "delims=" %%x in (tmpMsg.txt) do ( 498 + set "msg=%%x" 499 + echo !msg:%0=! 500 + ) 501 + 502 + :: Check whether CALL displayed GOTO help or CALL help. 503 + :: We differentiate between both, because GOTO /? mentions CALL /?, but CALL 504 + :: help does not mention GOTO, and contains the substring "CALL [" (part of the 505 + :: syntax example) that allows to discriminate between both cases. 506 + find "GOTO" tmp.txt > NUL && echo OK, GOTO help.|| echo Unexpected, no GOTO help^^! 507 + find "CALL [" tmp.txt > NUL && echo Unexpected CALL help^^! 508 + 509 + :: Cleanup 510 + del tmp.txt tmpMsg.txt > NUL 511 + 512 + :: Test 2: CALL /? will be called if piping. 513 + echo --- Direct label, piping 514 + 515 + call :%%label%% argument | (find "CALL [" > NUL && echo OK, CALL help.|| echo Unexpected, no CALL help^^!) 516 + echo Test message -- '%0','%*'>> tmpMsg.txt 517 + if "%0" == ":/?" ( 518 + echo Arguments: '%*'>> tmpMsg.txt 519 + exit /B 520 + ) 521 + 522 + :: Back to the main context. 523 + :: Display the redirected messages, filtering out the batch file name. 524 + for /f "delims=" %%x in (tmpMsg.txt) do ( 525 + set "msg=%%x" 526 + echo !msg:%0=! 527 + ) 528 + 529 + :: Cleanup 530 + del tmpMsg.txt > NUL 531 + cd .. & rd /s/q foobar 532 + 533 + 534 + :: 535 + :: Repeat the same tests as above, but now with a slightly different label. 536 + :: 537 + echo --------- Testing CALL with escape carets (triggers GOTO /?) --------- 538 + 539 + set "help=^ /? ^^^^arg" 540 + 541 + :: Test 1: GOTO /? will be called. 542 + :: See the explanations in the previous tests above 543 + echo --- Direct label, redirection 544 + 545 + :: Use an auxiliary CMD file 546 + mkdir foobar && cd foobar 547 + 548 + :: Call the label and redirect STDOUT to a file for later filtering. 549 + call :myLabel%%help%% ^^^^argument > tmp.txt 550 + echo Test message -- '%0','%*'>> tmpMsg.txt 551 + if "%0" == ":myLabel /?" ( 552 + echo Arguments: '%*'>> tmpMsg.txt 553 + exit /B 554 + ) 555 + 556 + :: Back to the main context. 557 + :: Display the redirected messages, filtering out the batch file name. 558 + for /f "delims=" %%x in (tmpMsg.txt) do ( 559 + set "msg=%%x" 560 + echo !msg:%0=! 561 + ) 562 + 563 + :: Check whether CALL displayed GOTO help or CALL help. 564 + find "GOTO" tmp.txt > NUL && echo OK, GOTO help.|| echo Unexpected, no GOTO help^^! 565 + find "CALL [" tmp.txt > NUL && echo Unexpected CALL help^^! 566 + 567 + :: Cleanup 568 + del tmp.txt tmpMsg.txt > NUL 569 + 570 + :: Test 2: CALL /? will be called if piping. 571 + echo --- Direct label, piping 572 + 573 + call :myLabel%%help%% ^^^^argument | (find "CALL [" > NUL && echo OK, CALL help.|| echo Unexpected, no CALL help^^!) 574 + echo Test message -- '%0','%*'>> tmpMsg.txt 575 + if "%0" == ":myLabel /?" ( 576 + echo Arguments: '%*'>> tmpMsg.txt 577 + exit /B 578 + ) 579 + 580 + :: Back to the main context. 581 + :: Display the redirected messages, filtering out the batch file name. 582 + for /f "delims=" %%x in (tmpMsg.txt) do ( 583 + set "msg=%%x" 584 + echo !msg:%0=! 585 + ) 586 + 587 + :: Cleanup 588 + del tmpMsg.txt > NUL 589 + cd .. & rd /s/q foobar 590 + 591 + goto :continue 592 + 593 + :/? 594 + :myLabel 595 + echo Unexpected CALL or GOTO! Arguments: '%*' 596 + exit /b 0 597 + 598 + 599 + :: 600 + :: Next suite of tests. 601 + :: 602 + :continue 603 + 604 + :: 605 + :: This test will actually call the label. 606 + :: Adapted from https://stackoverflow.com/a/38938416/13530036 607 + :: 608 + echo --------- Testing CALL (NOT triggering GOTO /? or CALL /?) --------- 609 + 610 + set "var=/?" 611 + call :sub %%var%% 612 + goto :otherTest 613 + 614 + :sub 615 + echo Arguments: '%*' 616 + exit /b 617 + 618 + 619 + :otherTest 620 + call :sub2 "/?" Hello World 621 + goto :continue 622 + 623 + :sub2 624 + :: 'args' contains the list of arguments 625 + set "args=%*" 626 + :: !args:%1=! will remove the first argument specified by %1 and keep the rest. 627 + echo %~1 | (find "ECHO [" > NUL && echo OK, ECHO help.|| echo Unexpected, no ECHO help^^!) 628 + echo/ 629 + echo !args:%1=! 630 + exit /b 631 + 632 + 633 + :: 634 + :: Next suite of tests. 635 + :: 636 + :continue 637 + 638 + :: 639 + :: CALL supports double delayed expansion. 640 + :: Test from https://stackoverflow.com/a/31990563/13530036 641 + :: 642 + echo --------- Testing CALL double delayed expansion --------- 643 + 644 + set "label=myLabel" 645 + set "pointer=^!label^!" 646 + call :!pointer! 647 + goto :finished 648 + 649 + :myLabel 650 + echo It works^^! 382 651 exit /b 383 652 384 653
+46
modules/rostests/win32/cmd/test_goto_call.cmd.exp
··· 2 2 Test GOTO ok 3 3 --------- Testing CALL within batch --------- 4 4 Test CALL ok from :test_call 5 + Hi there! 6 + Hi there! 7 + Hi there! 8 + Hi there! 9 + goto with unrelated first character, and escape carets worked 10 + Params: ':dest1', '', '', '' 11 + goto with unrelated first character, and escape carets worked 12 + Params: ':dest1', '', '', '' 13 + goto with unrelated first character, and escape carets worked 14 + Params: ':dest1', '', '', '' 15 + goto with unrelated first character, and escape carets worked 16 + Params: ':dest1', '', '', '' 17 + goto with unrelated first character, and escape carets worked 18 + Params: ':dest1', 'a', 'b', 'c' 19 + goto with unrelated first character, and escape carets worked 20 + Params: ':dest1', '', '', '' 21 + OK 22 + OK 23 + CALL with escape caret worked 5 24 GOTO with escape caret worked 6 25 Hi there! 7 26 Hi there! ··· 10 29 Hi there! 11 30 Hi there! 12 31 --------- Testing :EOF support --------- 32 + OK 33 + OK 13 34 OK 14 35 OK 15 36 OK ··· 228 249 --------- Testing EXIT within IF --------- 229 250 First block 230 251 Second block 252 + --------- Testing CALL (triggers GOTO /?) --------- 253 + --- Direct label, redirection 254 + Test message -- ':/?','argument' 255 + Arguments: 'argument' 256 + Test message -- '','' 257 + OK, GOTO help. 258 + --- Direct label, piping 259 + OK, CALL help.@space@ 260 + Test message -- '','' 261 + --------- Testing CALL with escape carets (triggers GOTO /?) --------- 262 + --- Direct label, redirection 263 + Test message -- ':myLabel /?','^arg ^argument' 264 + Arguments: '^arg ^argument' 265 + Test message -- '','' 266 + OK, GOTO help. 267 + --- Direct label, piping 268 + OK, CALL help.@space@ 269 + Test message -- '','' 270 + --------- Testing CALL (NOT triggering GOTO /? or CALL /?) --------- 271 + Arguments: '/?' 272 + OK, ECHO help.@space@ 273 + 274 + Hello World 275 + --------- Testing CALL double delayed expansion --------- 276 + It works! 231 277 --------- Finished --------------