cmd/tests: Add tests for variable delayed expansion.
[wine/multimedia.git] / programs / cmd / tests / test_builtins.cmd
blob3f8c72e9ad0e3e78e6d1ed6b7a8d830f1953d591
1 echo Tests for cmd's builtin commands
3 @echo on
4 echo ------------ Testing 'echo' [ON] --------------
5 echo word
6 echo 'singlequotedword'
7 echo "doublequotedword"
8 @echo at-echoed-word
9 echo "/?"
10 echo.
11 echo .
12 echo.word
13 echo .word
14 echo:
15 echo :
16 echo:word
17 echo :word
18 echo word@space@
19 echo word@space@@space@
21 @echo off
22 echo ------------ Testing 'echo' [OFF] --------------
23 echo word
24 echo 'singlequotedword'
25 echo "doublequotedword"
26 @echo at-echoed-word
27 echo "/?"
28 echo.
29 echo .
30 echo.word
31 echo .word
32 echo:
33 echo :
34 echo:word
35 echo :word
36 echo word@space@
37 echo word@space@@space@
39 echo ------------ Testing redirection operators --------------
40 mkdir foobar & cd foobar
41 echo ...stdout redirection
42 echo foo>foo
43 type foo
44 echo foo 1> foo
45 type foo
46 echo foo1> foo
47 type foo
48 echo foo11> foo
49 type foo
50 echo foo12> foo
51 type foo
52 echo ...stdout appending
53 echo foo>foo
54 echo foo >>foo
55 type foo
56 del foo
57 echo foob >> foo
58 type foo
59 echo fooc 1>>foo
60 type foo
61 echo food1>>foo
62 type foo
63 echo food2>>foo
64 type foo
65 del foo
66 echo food21>>foo
67 type foo
68 cd ..
69 rd /s/q foobar
71 echo ------------ Testing ^^ escape character --------------
72 rem Using something like "echo foo^" asks for an additional char after a "More?" prompt on the following line; it's not possible to currently test that non-interactively
73 echo ^hell^o, world
74 echo hell^o, world
75 echo hell^^o, world
76 echo hell^^^o, world
77 mkdir foobar
78 echo baz> foobar\baz
79 type foobar\baz
80 type foobar^\baz
81 rd /s/q foobar
82 echo foo ^| echo bar
83 echo foo ^& echo bar
84 call :setError 0
85 echo bak ^&& echo baz 2> nul
86 echo %ErrorLevel%
87 echo foo ^> foo
88 echo ^<> foo
89 type foo
90 del foo
91 set FOO=oof
92 echo ff^%FOO%
93 set FOO=bar ^| baz
94 set FOO
95 rem FIXME: echoing %FOO% gives an error (baz not recognized) but prematurely
96 rem exits the script on windows; redirecting stdout and/or stderr doesn't help
97 echo %ErrorLevel%
98 call :setError 0
99 set FOO=bar ^^^| baz
100 set FOO
101 echo %FOO%
102 echo %ErrorLevel%
103 set FOO=
105 echo ------------ Testing 'set' --------------
106 call :setError 0
107 set FOOBAR 2> nul > nul
108 echo %ErrorLevel%
109 set FOOBAR = baz
110 echo %ErrorLevel%
111 echo %FOOBAR%FOOBAR not defined
112 echo %FOOBAR %
113 set FOOBAR 2> nul
114 set FOOBAR = baz2
115 echo %ErrorLevel%
116 echo %fOObAr %
117 set FOOBAR= bar
118 echo %ErrorLevel%
119 echo %FOOBAR%
120 set FOO
121 set FOOBAR=
122 set FOOB
123 echo %FOOBAR%FOOBAR not defined
124 set FOOBAR =
125 set FOOBA 2> nul > nul
126 echo %ErrorLevel%
127 set FOO=bar
128 echo %FOO%
129 set FOO=foo
130 set BAR=bar
131 echo %FOO%%BAR%
132 set BAR=
133 set FOO=
134 set FOO=%FOO%
135 echo %FOO%FOO not defined
136 set BAZ%=bazbaz
137 set BA
138 echo %BAZ%%
139 set BAZ%=
140 echo set "FOO=bar" should not include the quotes in the variable value
141 set "FOO=bar"
142 echo %FOO%
143 set FOO=
145 echo ------------ Testing variable expansion --------------
146 call :setError 0
147 echo ~dp0 should be directory containing batch file
148 echo %~dp0
149 mkdir dummydir
150 cd dummydir
151 echo %~dp0
152 cd ..
153 rmdir dummydir
154 echo CD value %CD%
155 echo %%
156 echo P%
157 echo %P
158 echo %UNKNOWN%S
159 echo P%UNKNOWN%
160 echo P%UNKNOWN%S
161 echo %ERRORLEVEL
162 echo %ERRORLEVEL%
163 echo %ERRORLEVEL%%ERRORLEVEL%
164 echo %ERRORLEVEL%ERRORLEVEL%
165 echo %ERRORLEVEL%%
166 echo %ERRORLEVEL%%%
167 echo P%ERRORLEVEL%
168 echo %ERRORLEVEL%S
169 echo P%ERRORLEVEL%S
171 echo ------------ Testing variable delayed expansion --------------
172 rem NT4 doesn't support this
173 echo ...default mode (load-time expansion)
174 set FOO=foo
175 echo %FOO%
176 echo !FOO!
177 if %FOO% == foo (
178 set FOO=bar
179 if %FOO% == bar (echo bar) else echo foo
182 set FOO=foo
183 if %FOO% == foo (
184 set FOO=bar
185 if !FOO! == bar (echo bar) else echo foo
188 echo ...runtime (delayed) expansion mode
189 setlocal EnableDelayedExpansion
190 set FOO=foo
191 echo %FOO%
192 echo !FOO!
193 if %FOO% == foo (
194 set FOO=bar
195 if %FOO% == bar (echo bar) else echo foo
198 set FOO=foo
199 if %FOO% == foo (
200 set FOO=bar
201 if !FOO! == bar (echo bar) else echo foo
203 echo %ErrorLevel%
204 setlocal DisableDelayedExpansion
205 echo %ErrorLevel%
206 set FOO=foo
207 echo %FOO%
208 echo !FOO!
209 set FOO=
211 echo ------------ Testing conditional execution --------------
212 echo ...unconditional ^&
213 call :setError 123 & echo foo1
214 echo bar2 & echo foo2
215 mkdir foobar & cd foobar
216 echo > foobazbar
217 cd .. & rd /s/q foobar
218 if exist foobazbar (
219 echo foobar not deleted!
220 cd ..
221 rd /s/q foobar
222 ) else echo foobar deleted
223 echo ...on success conditional ^&^&
224 call :setError 456 && echo foo3 > foo3
225 if exist foo3 (
226 echo foo3 created
227 del foo3
228 ) else echo foo3 not created
229 echo bar4 && echo foo4
230 echo ...on failure conditional ^|^|
231 call :setError 789 || echo foo5
232 echo foo6 || echo bar6 > bar6
233 if exist bar6 (
234 echo bar6 created
235 del bar6
238 echo ------------ Testing type ------------
239 echo bar> foobaz
240 @echo on
241 type foobaz
242 echo ***
243 @echo off
244 type foobaz
245 echo ***
246 del foobaz
248 echo ------------ Testing NUL ------------
249 md foobar & cd foobar
250 rem NUL file (non) creation + case insensitivity
251 rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround
252 echo > bar
253 echo foo > NUL
254 dir /b /a-d
255 echo foo > nul
256 dir /b /a-d
257 echo foo > NuL
258 dir /b /a-d
259 del bar
260 rem NUL not special everywhere
261 call :setError 123
262 echo NUL> foo
263 if not exist foo (echo foo should have been created) else (
264 type foo
265 del foo
267 rem Empty file creation
268 copy nul foo > nul
269 if exist foo (
270 echo foo created
271 del foo
272 type foo
273 ) else (
274 echo ***
276 cd ..
277 rd foobar
279 echo ------------ Testing if/else --------------
280 echo if/else should work with blocks
281 if 0 == 0 (
282 echo if seems to work
283 ) else (
284 echo if seems to be broken
286 if 1 == 0 (
287 echo else seems to be broken
288 ) else (
289 echo else seems to work
291 if /c==/c (
292 echo if seems not to detect /c as parameter
293 ) else (
294 echo parameter detection seems to be broken
296 echo Testing case sensitivity with and without /i option
297 if bar==BAR echo if does not default to case sensitivity
298 if not bar==BAR echo if seems to default to case sensitivity
299 if /i foo==FOO echo if /i seems to work
300 if /i not foo==FOO echo if /i seems to be broken
301 if /I foo==FOO echo if /I seems to work
302 if /I not foo==FOO echo if /I seems to be broken
304 echo -----------Testing for -----------
305 echo ...plain FOR
306 for %%i in (A B C) do echo %%i
307 for %%i in (A B C) do echo %%I
308 for %%i in (A B C) do echo %%j
309 for %%i in (A B C) do call :forTestFun1 %%i
310 for %%i in (1,4,1) do echo %%i
311 for %%i in (A, B,C) do echo %%i
312 goto :endForTestFun1
313 :forTestFun1
314 echo %1
315 goto :eof
316 :endForTestFun1
317 echo ...imbricated FORs
318 for %%i in (X) do (
319 for %%j in (Y) do (
320 echo %%i %%j))
321 for %%i in (X) do (
322 for %%I in (Y) do (
323 echo %%i %%I))
324 for %%i in (A B) do (
325 for %%j in (C D) do (
326 echo %%i %%j))
327 for %%i in (A B) do (
328 for %%j in (C D) do (
329 call :forTestFun2 %%i %%j ))
330 goto :endForTestFun2
331 :forTestFun2
332 echo %1 %2
333 goto :eof
334 :endForTestFun2
335 mkdir foobar & cd foobar
336 mkdir foo
337 mkdir bar
338 mkdir baz
339 echo > bazbaz
340 echo ...basic wildcards
341 for %%i in (ba*) do echo %%i
342 echo ...for /d
343 for /d %%i in (baz foo bar) do echo %%i
344 rem FIXME for /d incorrectly parses when wildcards are used
345 rem for /d %%i in (bazb*) do echo %%i
346 rem FIXME can't test wildcard expansion here since it's listed in directory
347 rem order, and not in alphabetic order.
348 rem Proper testing would need a currently missing "sort" program implementation.
349 rem for /d %%i in (ba*) do echo %%i>> tmp
350 rem sort < tmp
351 rem del tmp
352 rem for /d %%i in (?a*) do echo %%i>> tmp
353 rem sort < tmp
354 rem del tmp
355 rem for /d %%i in (*) do echo %%i>> tmp
356 rem sort < tmp
357 rem del tmp
358 cd ..
359 rd /s/Q foobar
360 echo ...for /L
361 rem Some cases loop forever writing 0s, like e.g. (1,0,1), (1,a,3) or (a,b,c); those can't be tested here
362 for /L %%i in (1,2,0) do echo %%i
363 for /L %%i in (1,2,6) do echo %%i
364 for /l %%i in (1 ,2,6) do echo %%i
365 for /L %%i in (a,2,3) do echo %%i
366 for /L %%i in (1,2,-1) do echo %%i
367 for /L %%i in (-4,-1,-1) do echo %%i
368 for /L %%i in (1,-2,-2) do echo %%i
369 for /L %%i in (1,2,a) do echo %%i
370 echo ErrorLevel %ErrorLevel%
371 for /L %%i in (1,a,b) do echo %%i
372 echo ErrorLevel %ErrorLevel%
373 rem FIXME: following test cases cannot be currently tested due to an inconsistent/buggy 'for /L' parsing.
374 rem for /L %%i in (a,2,b) do echo %%i
375 rem for /L %%i in (1,1,1) do echo %%i
376 rem for /L %%i in (1,-2,-1) do echo %%i
377 rem for /L %%i in (-1,-1,-1) do echo %%i
378 rem for /L %%i in (1,2, 3) do echo %%i
380 echo -----------Testing del /a-----------
381 del /f/q *.test > nul
382 echo r > r.test
383 attrib +r r.test
384 echo not-r > not-r.test
386 if not exist not-r.test echo not-r.test not found before delete, bad
387 del /a:-r *.test
388 if not exist not-r.test echo not-r.test not found after delete, good
390 if not exist r.test echo r.test not found before delete, bad
391 if exist r.test echo r.test found before delete, good
392 del /a:r *.test
393 if not exist r.test echo r.test not found after delete, good
394 if exist r.test echo r.test found after delete, bad
396 echo ------------ Testing del /q --------------
397 mkdir del_q_dir
398 cd del_q_dir
399 echo abc > file1
400 echo abc > file2.dat
401 rem If /q doesn't work, cmd will prompt and the test case should hang
402 del /q * > nul
403 for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a
404 for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a
405 cd ..
406 rmdir del_q_dir
408 echo ------------ Testing del /s --------------
409 mkdir "foo bar"
410 cd "foo bar"
411 echo hi > file1.dat
412 echo there > file2.dat
413 echo bub > file3.dat
414 echo bye > "file with spaces.dat"
415 cd ..
416 del /s file1.dat > nul
417 del file2.dat /s > nul
418 del "file3.dat" /s > nul
419 del "file with spaces.dat" /s > nul
420 cd "foo bar"
421 for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f
422 for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat
423 if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat"
424 if exist "file with spaces.dat" del "file with spaces.dat"
425 cd ..
426 rmdir "foo bar"
428 echo ----------- Testing mkdir -----------
429 call :setError 0
430 rem md and mkdir are synonymous
431 mkdir foobar
432 echo %ErrorLevel%
433 rmdir foobar
434 md foobar
435 echo %ErrorLevel%
436 rmdir foobar
437 rem Creating an already existing directory/file must fail
438 mkdir foobar
439 md foobar
440 echo %ErrorLevel%
441 rmdir foobar
442 echo > foobar
443 mkdir foobar
444 echo %ErrorLevel%
445 del foobar
446 rem Multi-level path creation
447 mkdir foo
448 echo %ErrorLevel%
449 mkdir foo\bar\baz
450 echo %ErrorLevel%
451 cd foo
452 echo %ErrorLevel%
453 cd bar
454 echo %ErrorLevel%
455 cd baz
456 echo %ErrorLevel%
457 echo > ..\..\bar2
458 mkdir ..\..\..\foo\bar2
459 echo %ErrorLevel%
460 del ..\..\bar2
461 mkdir ..\..\..\foo\bar2
462 echo %ErrorLevel%
463 rmdir ..\..\..\foo\bar2
464 cd ..
465 rmdir baz
466 cd ..
467 rmdir bar
468 cd ..
469 rmdir foo
470 echo %ErrorLevel%
471 rem Trailing backslashes
472 mkdir foo\\\\
473 echo %ErrorLevel%
474 if exist foo (rmdir foo & echo dir created
475 ) else ( echo dir not created )
476 echo %ErrorLevel%
477 rem Invalid chars
478 mkdir ?
479 echo %ErrorLevel%
480 call :setError 0
481 mkdir ?\foo
482 echo %ErrorLevel%
483 call :setError 0
484 mkdir foo\?
485 echo %ErrorLevel%
486 if exist foo (rmdir foo & echo ok, foo created
487 ) else ( echo foo not created )
488 call :setError 0
489 mkdir foo\bar\?
490 echo %ErrorLevel%
491 call :setError 0
492 if not exist foo (
493 echo bad, foo not created
494 ) else (
495 cd foo
496 if exist bar (
497 echo ok, foo\bar created
498 rmdir bar
500 cd ..
501 rmdir foo
503 rem multiples directories at once
504 mkdir foobaz & cd foobaz
505 mkdir foo bar\baz foobar
506 if exist foo (echo foo created) else echo foo not created!
507 if exist bar (echo bar created) else echo bar not created!
508 if exist foobar (echo foobar created) else echo foobar not created!
509 if exist bar\baz (echo bar\baz created) else echo bar\baz not created!
510 cd ..
511 rd /s/q foobaz
513 echo ----------- Testing rmdir -----------
514 call :setError 0
515 rem rd and rmdir are synonymous
516 mkdir foobar
517 rmdir foobar
518 echo %ErrorLevel%
519 if not exist foobar echo dir removed
520 mkdir foobar
521 rd foobar
522 echo %ErrorLevel%
523 if not exist foobar echo dir removed
524 rem Removing non-existent directory
525 rmdir foobar
526 echo %ErrorLevel%
527 rem Removing single-level directories
528 echo > foo
529 rmdir foo
530 echo %ErrorLevel%
531 if exist foo echo file not removed
532 del foo
533 mkdir foo
534 echo > foo\bar
535 rmdir foo
536 echo %ErrorLevel%
537 if exist foo echo non-empty dir not removed
538 del foo\bar
539 mkdir foo\bar
540 rmdir foo
541 echo %ErrorLevel%
542 if exist foo echo non-empty dir not removed
543 rmdir foo\bar
544 rmdir foo
545 rem Recursive rmdir
546 mkdir foo\bar\baz
547 rmdir /s /Q foo
548 if not exist foo (
549 echo recursive rmdir succeeded
550 ) else (
551 rd foo\bar\baz
552 rd foo\bar
553 rd foo
555 mkdir foo\bar\baz
556 echo foo > foo\bar\brol
557 rmdir /s /Q foo
558 if not exist foo (
559 echo recursive rmdir succeeded
560 ) else (
561 rd foo\bar\baz
562 del foo\bar\brol
563 rd foo\bar
564 rd foo
566 rem multiples directories at once
567 mkdir foobaz & cd foobaz
568 mkdir foo
569 mkdir bar\baz
570 mkdir foobar
571 rd /s/q foo bar foobar
572 if not exist foo (echo foo removed) else echo foo not removed!
573 if not exist bar (echo bar removed) else echo bar not removed!
574 if not exist foobar (echo foobar removed) else echo foobar not removed!
575 if not exist bar\baz (echo bar\baz removed) else echo bar\baz not removed!
576 cd ..
577 rd /s/q foobaz
579 echo ------------ Testing CALL --------------
580 mkdir foobar & cd foobar
581 rem External script
582 echo echo foo %%1> foo.cmd
583 call foo
584 call foo.cmd 8
585 echo echo %%1 %%2 > foo.cmd
586 call foo.cmd foo
587 call foo.cmd foo bar
588 call foo.cmd foo ""
589 call foo.cmd "" bar
590 call foo.cmd foo ''
591 call foo.cmd '' bar
592 del foo.cmd
593 rem Internal routines
594 call :testRoutine :testRoutine
595 goto :endTestRoutine
596 :testRoutine
597 echo bar %1
598 goto :eof
599 :endTestRoutine
601 call :testRoutineArgs foo
602 call :testRoutineArgs foo bar
603 call :testRoutineArgs foo ""
604 call :testRoutineArgs "" bar
605 call :testRoutineArgs foo ''
606 call :testRoutineArgs '' bar
607 goto :endTestRoutineArgs
608 :testRoutineArgs
609 echo %1 %2
610 goto :eof
611 :endTestRoutineArgs
613 rem Should work for builtins...
614 call mkdir foo
615 echo %ErrorLevel%
616 if exist foo (echo foo created) else echo foo should exist!
617 rmdir foo
618 set FOOBAZ_VAR=foobaz
619 call echo Should expand %FOOBAZ_VAR%
620 set FOOBAZ_VAR=
621 echo>batfile
622 call dir /b
623 echo>robinfile
624 if 1==1 call del batfile
625 dir /b
626 if exist batfile echo batfile shouldn't exist
627 rem ... but not for 'if' or 'for'
628 call if 1==1 echo bar 2> nul
629 echo %ErrorLevel%
630 call :setError 0
631 call for %%i in (foo bar baz) do echo %%i 2> nul
632 echo %ErrorLevel%
633 rem First look for programs in the path before trying a builtin
634 echo echo non-builtin dir> dir.cmd
635 call dir /b
636 cd ..
637 rd /s/q foobar
639 echo -----------Testing Errorlevel-----------
640 rem WARNING: Do *not* add tests using ErrorLevel after this section
641 should_not_exist 2> nul > nul
642 echo %ErrorLevel%
643 rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak
644 rem See http://www.robvanderwoude.com/exit.php
645 call :setError 1
646 echo %ErrorLevel%
647 if errorlevel 2 echo errorlevel too high, bad
648 if errorlevel 1 echo errorlevel just right, good
649 call :setError 0
650 echo abc%ErrorLevel%def
651 if errorlevel 1 echo errorlevel nonzero, bad
652 if not errorlevel 1 echo errorlevel zero, good
653 rem Now verify that setting a real variable hides its magic variable
654 set errorlevel=7
655 echo %ErrorLevel% should be 7
656 if errorlevel 7 echo setting var worked too well, bad
657 call :setError 3
658 echo %ErrorLevel% should still be 7
660 echo -----------Testing GOTO-----------
661 if a==a goto dest1
662 :dest1
663 echo goto with no leading space worked
664 if b==b goto dest2
665 :dest2
666 echo goto with a leading space worked
667 if c==c goto dest3
668 :dest3
669 echo goto with a leading tab worked
670 if d==d goto dest4
671 :dest4@space@
672 echo goto with a following space worked
674 echo -----------Done, jumping to EOF-----------
675 goto :eof
676 rem Subroutine to set errorlevel and return
677 rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported
678 :setError
679 exit /B %1
680 rem This line runs under cmd in windows NT 4, but not in more modern versions.