cmd: Add support for usebackq (for /f).
[wine] / programs / cmd / tests / test_builtins.cmd
1 echo Tests for cmd's builtin commands
2
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 off now
19 echo word@space@
20 echo word@space@@space@
21  echo word
22 echo@tab@word
23 echo@tab@word @tab@
24 echo@tab@word@tab@@space@
25 @tab@echo word
26 echo @tab@word
27 echo  @tab@word
28 echo@tab@@tab@word
29 echo @tab@ on @space@
30
31 @echo off
32 echo off@tab@@space@
33 @echo noecho1
34  @echo noecho2
35 @@@@@echo echo3
36 echo ------------ Testing 'echo' [OFF] ------------
37 echo word
38 echo 'singlequotedword'
39 echo "doublequotedword"
40 @echo at-echoed-word
41 echo "/?"
42 echo.
43 echo .
44 echo.word
45 echo .word
46 echo:
47 echo :
48 echo:word
49 echo :word
50 echo on again
51 echo word@space@
52 echo word@space@@space@
53  echo word
54 echo@tab@word
55 echo@tab@word @tab@
56 echo@tab@word@tab@@space@
57 @tab@echo word
58 echo @tab@word
59 echo  @tab@word
60 echo@tab@@tab@word
61
62 echo ------------ Testing mixed echo modes ------------
63 echo @echo on> mixedEchoModes.cmd
64 echo if 1==1 echo foo>> mixedEchoModes.cmd
65 echo if 1==1 @echo bar>> mixedEchoModes.cmd
66 echo @echo off>> mixedEchoModes.cmd
67 echo if 1==1 echo foo2>> mixedEchoModes.cmd
68 echo if 1==1 @echo bar2>> mixedEchoModes.cmd
69 type mixedEchoModes.cmd
70 cmd /c mixedEchoModes.cmd
71 del mixedEchoModes.cmd
72
73 echo ------------ Testing parameterization ------------
74 call :TestParm a b c
75 call :TestParm "a b c"
76 call :TestParm "a b"\c
77 call :TestParm a=~`+,.{}!+b
78 call :TestParm a;b
79 call :TestParm "a;b"
80 call :TestParm a^;b
81 call :TestParm a[b]{c}(d)e
82 call :TestParm a&echo second line
83 call :TestParm a   b,,,c
84 call :TestParm a==b;;c
85 call :TestParm       a,,,  b
86 goto :TestRem
87
88 :TestParm
89 echo '%1', '%2', '%3'
90 goto :eof
91
92 :TestRem
93 echo ------------ Testing rem ------------
94 rem Hello
95 rem  Hello
96 rem   Hello || foo
97 rem echo lol
98 rem echo foo & echo bar
99 rem @tab@  Hello
100 rem@tab@  Hello
101 rem@tab@echo foo & echo bar
102 @echo on
103 rem Hello
104 rem  Hello
105 rem   Hello || foo
106 rem echo lol
107 rem echo foo & echo bar
108 rem @tab@  Hello
109 rem@tab@  Hello
110 rem@tab@echo foo & echo bar
111 @echo off
112
113 echo ------------ Testing redirection operators ------------
114 mkdir foobar & cd foobar
115 echo --- stdout redirection
116 echo foo>foo
117 type foo
118 echo foo 1> foo
119 type foo
120 echo foo@tab@1> foo
121 type foo
122 echo foo 1>@tab@foo
123 type foo
124 echo foo@tab@1>@tab@foo
125 type foo
126 echo foo7 7> foo
127 type foo
128 echo foo9 9> foo
129 type foo
130 echo foo1> foo
131 type foo
132 echo foo11> foo
133 type foo
134 echo foo12> foo
135 type foo
136 echo foo13>"foo"
137 type foo
138 echo foo14>."\foo"
139 type foo
140 echo foo15>."\f"oo
141 type foo
142 del foo
143 echo1>foo
144 type foo
145 echo --- stdout appending
146 echo foo>foo
147 echo foo >>foo
148 type foo
149 del foo
150 echo foob >> foo
151 type foo
152 echo fooc 1>>foo
153 type foo
154 echo food1>>foo
155 type foo
156 echo food2>>"foo"
157 type foo
158 del foo
159 echo food21>>foo
160 type foo
161 del foo
162 echo foo> foo
163 echo foo7 7>> foo || (echo not supported & del foo)
164 if exist foo (type foo) else echo not supported
165 echo --- redirections within IF statements
166 if 1==1 echo foo1>bar
167 type bar & del bar
168 echo -----
169 if 1==1 (echo foo2>bar) else echo baz2>bar
170 type bar & del bar
171 if 1==1 (echo foo3) else echo baz3>bar
172 type bar || echo file does not exist, ok
173 if 1==1 (echo foo4>bar) else echo baz4>bar
174 type bar & del bar
175 if 1==0 (echo foo5>bar) else echo baz5>bar
176 type bar & del bar
177 if 1==0 (echo foo6) else echo baz6 1>bar
178 type bar & del bar
179 if 1==0 (echo foo7 1>bar) else echo baz7>bar
180 type bar & del bar
181 if 1==0 (echo foo8 1>bar) else echo baz8>bak
182 type bak
183 if 1==1 (echo foo>bar & echo baz)
184 type bar
185 if 1==1 (
186    echo foo>bar
187    echo baz
188 )
189 type bar
190 (if 1==1 (echo A) else echo B) > C
191 type C
192 (if 1==0 (echo A) else echo B) > C
193 type C
194 (if 1==0 (echo A > B) else echo C)
195 cd .. & rd /s/q foobar
196
197 echo ------------ Testing circumflex escape character ------------
198 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
199 echo ^hell^o, world
200 echo hell^o, world
201 echo hell^^o, world
202 echo hell^^^o, world
203 echo hello^
204 world
205 echo hello^
206
207 world
208 echo hello^
209
210
211 echo finished
212 mkdir foobar
213 echo baz> foobar\baz
214 type foobar\baz
215 type foobar^\baz
216 rd /s/q foobar
217 echo foo ^| echo bar
218 echo foo ^& echo bar
219 call :setError 0
220 echo bak ^&& echo baz 2> nul
221 echo %ErrorLevel%
222 echo foo ^> foo
223 echo ^<> foo
224 type foo
225 del foo
226 set FOO=oof
227 echo ff^%FOO%
228 set FOO=bar ^| baz
229 set FOO
230 rem FIXME: echoing %FOO% gives an error (baz not recognized) but prematurely
231 rem exits the script on windows; redirecting stdout and/or stderr doesn't help
232 echo %ErrorLevel%
233 call :setError 0
234 set FOO=bar ^^^| baz
235 set FOO
236 echo %FOO%
237 echo %ErrorLevel%
238 set FOO=
239
240 echo ------------ Testing 'set' ------------
241 call :setError 0
242 set FOOBAR 2> nul > nul
243 echo %ErrorLevel%
244 set FOOBAR =  baz
245 echo %ErrorLevel%
246 echo %FOOBAR%FOOBAR not defined
247 echo %FOOBAR %
248 set FOOBAR 2> nul
249 set FOOBAR =  baz2
250 echo %ErrorLevel%
251 echo %fOObAr %
252 set FOOBAR= bar
253 echo %ErrorLevel%
254 echo %FOOBAR%
255 set FOO
256 set FOOBAR=
257 set FOOB
258 echo %FOOBAR%FOOBAR not defined
259 set FOOBAR =
260 set FOOBA 2> nul > nul
261 echo %ErrorLevel%
262 set FOO=bar
263 echo %FOO%
264 set FOO=foo
265 set BAR=bar
266 echo %FOO%%BAR%
267 set BAR=
268 set FOO=
269 set FOO=%FOO%
270 echo %FOO%FOO not defined
271 set BAZ%=bazbaz
272 set BA
273 echo %BAZ%%
274 set BAZ%=
275 echo set "FOO=bar" should not include the quotes in the variable value
276 set "FOO=bar"
277 echo %FOO%
278 set@tab@FOO=foo
279 echo %FOO%
280 set@tab@FOO=
281 echo '%FOO%'
282 set FOO=foo@space@
283 echo '%FOO%'
284 set FOO=foo@tab@
285 echo '%FOO%'
286 set FOO=
287
288 echo ------------ Testing variable expansion ------------
289 call :setError 0
290 echo ~dp0 should be directory containing batch file
291 echo %~dp0
292 mkdir dummydir
293 cd dummydir
294 echo %~dp0
295 cd ..
296 rmdir dummydir
297 echo CD value %CD%
298 echo %%
299 echo P%
300 echo %P
301 echo %UNKNOWN%S
302 echo P%UNKNOWN%
303 echo P%UNKNOWN%S
304 echo %ERRORLEVEL
305 echo %ERRORLEVEL%
306 echo %ERRORLEVEL%%ERRORLEVEL%
307 echo %ERRORLEVEL%ERRORLEVEL%
308 echo %ERRORLEVEL%%
309 echo %ERRORLEVEL%%%
310 echo P%ERRORLEVEL%
311 echo %ERRORLEVEL%S
312 echo P%ERRORLEVEL%S
313
314 echo ------------ Testing variable substrings ------------
315 set VAR=qwerty
316 echo %VAR:~0,1%
317 echo %VAR:~0,3%
318 echo %VAR:~2,2%
319 echo '%VAR:~-2,3%'
320 echo '%VAR:~-2,1%'
321 echo %VAR:~2,-1%
322 echo %VAR:~2,-3%
323 echo '%VAR:~-2,-4%'
324 echo %VAR:~-3,-2%
325 set VAR=
326
327 echo ------------ Testing variable substitution ------------
328 echo --- in FOR variables
329 for %%i in ("A B" C) do echo %%i
330 rem check works when prefix with @
331 @for %%i in ("A B" C) do echo %%i
332 rem quotes removal
333 for %%i in ("A B" C) do echo '%%~i'
334 rem fully qualified path
335 for %%f in ("C D" E) do echo %%~ff
336 rem drive letter
337 for %%i in ("F G" H) do echo %%~di
338 rem path
339 for %%d in ("I J" K) do echo %%~pd
340 rem filename
341 for %%i in ("L M" N) do echo %%~ni
342 rem file extension
343 for %%i in ("O. P.OOL" Q.TABC hello) do echo '%%~xi'
344 rem path with short path names
345 for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do echo '%%~sI'
346 rem file attribute
347 for %%i in ("U V" W) do echo '%%~ai'
348 echo foo> foo
349 for %%i in (foo) do echo '%%~ai'
350 for %%i in (foo) do echo '%%~zi'
351 del foo
352 rem file date/time
353 rem Not fully testable, until we can grep dir's output to get foo's creation time in an envvar...
354 for %%i in ("a b" c) do echo '%%~ti'
355 rem file size
356 rem Similar issues as above
357 for %%i in ("a b" c) do echo '%%~zi'
358 rem combined options
359 for %%i in ("d e" f) do echo %%~dpi
360 for %%i in ("g h" i) do echo %%~sdi
361 for %%i in ("g h" i) do echo %%~dsi
362 for %%i in ("j k" l.eh) do echo '%%~xsi'
363
364 echo --- in parameters
365 for %%i in ("A B" C) do call :echoFun %%i
366 rem quotes removal
367 for %%i in ("A B" C) do call :echoFunQ %%i
368 rem fully qualified path
369 for %%f in ("C D" E) do call :echoFunF %%f
370 rem drive letter
371 for %%i in ("F G" H) do call :echoFunD %%i
372 rem path
373 for %%d in ("I J" K) do call :echoFunP %%d
374 rem filename
375 for %%i in ("L M" N) do call :echoFunN %%i
376 rem file extension
377 for %%i in ("O. P.OOL" Q.TABC hello) do call :echoFunX %%i
378 rem path with short path names
379 for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do call :echoFunS %%I
380 rem NT4 aborts whole script execution when encountering ~a, ~t and ~z substitutions, preventing full testing
381 rem combined options
382 for %%i in ("d e" f) do call :echoFunDP %%i
383 for %%i in ("g h" i) do call :echoFunSD %%i
384 for %%i in ("g h" i) do call :echoFunDS %%i
385 for %%i in ("j k" l.eh) do call :echoFunXS %%i
386
387 goto :endEchoFuns
388 :echoFun
389 echo %1
390 goto :eof
391
392 :echoFunQ
393 echo '%~1'
394 goto :eof
395
396 :echoFunF
397 echo %~f1
398 goto :eof
399
400 :echoFunD
401 echo %~d1
402 goto :eof
403
404 :echoFunP
405 echo %~p1
406 goto :eof
407
408 :echoFunN
409 echo %~n1
410 goto :eof
411
412 :echoFunX
413 echo '%~x1'
414 goto :eof
415
416 :echoFunS
417 rem some NT4 workaround
418 set VAR='%~s1'
419 echo %VAR%
420 set VAR=
421 goto :eof
422
423 :echoFunDP
424 echo %~dp1
425 goto :eof
426
427 :echoFunSD
428 echo %~sd1
429 goto :eof
430
431 :echoFunDS
432 echo %~ds1
433 goto :eof
434
435 :echoFunXS
436 echo '%~xs1'
437 goto :eof
438 :endEchoFuns
439
440 echo ------------ Testing variable delayed expansion ------------
441 rem NT4 doesn't support this
442 echo --- default mode (load-time expansion)
443 set FOO=foo
444 echo %FOO%
445 echo !FOO!
446 if %FOO% == foo (
447     set FOO=bar
448     if %FOO% == bar (echo bar) else echo foo
449 )
450
451 set FOO=foo
452 if %FOO% == foo (
453     set FOO=bar
454     if !FOO! == bar (echo bar) else echo foo
455 )
456
457 echo --- runtime (delayed) expansion mode
458 setlocal EnableDelayedExpansion
459 set FOO=foo
460 echo %FOO%
461 echo !FOO!
462 if %FOO% == foo (
463     set FOO=bar
464     if %FOO% == bar (echo bar) else echo foo
465 )
466
467 set FOO=foo
468 if %FOO% == foo (
469     set FOO=bar
470     if !FOO! == bar (echo bar) else echo foo
471 )
472 echo %ErrorLevel%
473 setlocal DisableDelayedExpansion
474 echo %ErrorLevel%
475 set FOO=foo
476 echo %FOO%
477 echo !FOO!
478 set FOO=
479 echo --- using /V cmd flag
480 echo @echo off> tmp.cmd
481 echo set FOO=foo>> tmp.cmd
482 echo echo %%FOO%%>> tmp.cmd
483 echo echo !FOO!>> tmp.cmd
484 echo set FOO=>> tmp.cmd
485 cmd /V:ON /C tmp.cmd
486 cmd /V:OfF /C tmp.cmd
487 del tmp.cmd
488
489 echo ------------ Testing conditional execution ------------
490 echo --- unconditional ampersand
491 call :setError 123 & echo foo1
492 echo bar2 & echo foo2
493 mkdir foobar & cd foobar
494 echo > foobazbar
495 cd .. & rd /s/q foobar
496 if exist foobazbar (
497     echo foobar not deleted!
498     cd ..
499     rd /s/q foobar
500 ) else echo foobar deleted
501 echo --- on success conditional and
502 call :setError 456 && echo foo3 > foo3
503 if exist foo3 (
504     echo foo3 created
505     del foo3
506 ) else echo foo3 not created
507 echo bar4 && echo foo4
508 echo --- on failure conditional or
509 call :setError 789 || echo foo5
510 echo foo6 || echo bar6 > bar6
511 if exist bar6 (
512     echo bar6 created
513     del bar6
514 )
515
516 echo ------------ Testing cd ------------
517 mkdir foobar
518 cd foobar
519 echo blabla > singleFile
520 dir /b
521 echo Current dir: %CD%
522 cd
523 cd ..
524 cd
525 cd foobar@space@
526 cd
527 cd ..
528 cd
529 cd @space@foobar
530 cd
531 cd..
532 cd
533 cd foobar
534 cd..@space@
535 cd
536 if not exist foobar (cd ..)
537 cd foobar
538 cd@tab@..@tab@@space@@tab@
539 cd
540 if not exist foobar (cd ..)
541 cd foobar
542 mkdir "bar bak"
543 cd "bar bak"
544 cd
545 cd ..
546 cd ".\bar bak"
547 cd
548 cd ..
549 cd .\"bar bak"
550 cd
551 cd ..
552 cd bar bak
553 cd
554 cd "bar bak@space@"@tab@@space@
555 cd
556 cd ..\..
557 cd
558 rd /Q/s foobar
559 mkdir foobar
560 cd /d@tab@foobar
561 cd
562 cd ..
563 rd /q/s foobar
564
565 echo ------------ Testing type ------------
566 echo bar> foobaz
567 @echo on
568 type foobaz
569 echo ---
570 @echo off
571 type foobaz@tab@
572 echo ---1
573 type ."\foobaz"
574 echo ---2
575 type ".\foobaz"
576 echo ---3
577 del foobaz
578
579 echo ------------ Testing NUL ------------
580 md foobar & cd foobar
581 rem NUL file (non) creation + case insensitivity
582 rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround
583 echo > bar
584 echo foo > NUL
585 dir /b /a-d
586 echo foo > nul
587 dir /b /a-d
588 echo foo > NuL
589 @tab@dir /b@tab@/a-d
590 del bar
591 rem NUL not special everywhere
592 call :setError 123
593 echo NUL> foo
594 if not exist foo (echo foo should have been created) else (
595     type foo
596     del foo
597 )
598 rem Empty file creation
599 copy nul foo > nul
600 if exist foo (
601     echo foo created
602     del foo
603     type foo
604 ) else (
605     echo ***
606 )
607 cd .. & rd foobar
608
609 echo ------------ Testing if/else ------------
610 echo --- if/else should work with blocks
611 if 0 == 0 (
612   echo if seems to work
613 ) else (
614   echo if seems to be broken
615 )
616 if 1 == 0 (
617   echo else seems to be broken
618 ) else (
619   echo else seems to work
620 )
621 if /c==/c (
622   echo if seems not to detect /c as parameter
623 ) else (
624   echo parameter detection seems to be broken
625 )
626
627 echo --- case sensitivity with and without /i option
628 if bar==BAR echo if does not default to case sensitivity
629 if not bar==BAR echo if seems to default to case sensitivity
630 if /i foo==FOO echo if /i seems to work
631 if /i not foo==FOO echo if /i seems to be broken
632 if /I foo==FOO echo if /I seems to work
633 if /I not foo==FOO echo if /I seems to be broken
634
635 echo --- string comparisons
636 if abc == abc  (echo equal) else echo non equal
637 if abc =="abc" (echo equal) else echo non equal
638 if "abc"== abc (echo equal) else echo non equal
639 if "abc"== "abc" (echo equal) else echo non equal
640
641 echo --- tabs handling
642 if@tab@1==1 echo doom
643 if @tab@1==1 echo doom
644 if 1==1 (echo doom) else@tab@echo quake
645 if@tab@not @tab@1==@tab@0 @tab@echo lol
646 if 1==0@tab@(echo doom) else echo quake
647 if 1==0 (echo doom)@tab@else echo quake
648 if 1==0 (echo doom) else@tab@echo quake
649
650 echo --- comparison operators
651 rem NT4 misevaluates conditionals in for loops so we have to use subroutines as workarounds
652 rem Imbricated for loops parameters are currently not expanded correctly; this prevents usage of simpler imbricated for loops in tests
653 echo ------ for strings
654 rem NT4 stops processing of the whole batch file as soon as it finds a
655 rem comparison operator non fully uppercased, such as lss instead of LSS, so we
656 rem can't test those here.
657 if LSS LSS LSSfoo (echo LSS string can be used as operand for LSS comparison)
658 if LSS LSS LSS (echo bar)
659 if 1.1 LSS 1.10 (echo floats are handled as strings)
660 if "9" LSS "10" (echo numbers in quotes recognized!) else echo numbers in quotes are handled as strings
661 if not "-1" LSS "1" (echo negative numbers as well) else echo NT4
662 if /i foo LSS FoOc echo if /i seems to work for LSS
663 if /I not foo LSS FOOb echo if /I seems to be broken for LSS
664 set STR_PARMS=A B AB BA AA
665 for %%i in (%STR_PARMS%) do call :LSStest %%i A
666 for %%i in (%STR_PARMS%) do call :LSStest %%i B
667 for %%i in (%STR_PARMS%) do call :LSStest %%i AB
668 for %%i in (%STR_PARMS%) do call :LSStest %%i BA
669 for %%i in (%STR_PARMS%) do call :LSStest %%i AA
670 if b LSS B (echo b LSS B) else echo NT4
671 if /I b LSS B echo b LSS B insensitive
672 if b LSS A echo b LSS A
673 if /I b LSS A echo b LSS A insensitive
674 if a LSS B (echo a LSS B) else echo NT4
675 if /I a LSS B echo a LSS B insensitive
676 if A LSS b echo A LSS b
677 if /I A LSS b echo A LSS b insensitive
678 for %%i in (%STR_PARMS%) do call :LEQtest %%i A
679 for %%i in (%STR_PARMS%) do call :LEQtest %%i B
680 for %%i in (%STR_PARMS%) do call :LEQtest %%i AB
681 for %%i in (%STR_PARMS%) do call :LEQtest %%i BA
682 for %%i in (%STR_PARMS%) do call :LEQtest %%i AA
683 if b LEQ B (echo b LEQ B) else echo NT4
684 if /I b LEQ B echo b LEQ B insensitive
685 if b LEQ A echo b LEQ A
686 if /I b LEQ A echo b LEQ A insensitive
687 if a LEQ B (echo a LEQ B) else echo NT4
688 if /I a LEQ B echo a LEQ B insensitive
689 if A LEQ b echo A LEQ b
690 if /I A LEQ b echo A LEQ b insensitive
691 for %%i in (%STR_PARMS%) do call :EQUtest %%i A
692 for %%i in (%STR_PARMS%) do call :EQUtest %%i B
693 for %%i in (%STR_PARMS%) do call :EQUtest %%i AB
694 for %%i in (%STR_PARMS%) do call :EQUtest %%i BA
695 for %%i in (%STR_PARMS%) do call :EQUtest %%i AA
696 if /I A EQU a echo A EQU a insensitive
697 for %%i in (%STR_PARMS%) do call :NEQtest %%i A
698 for %%i in (%STR_PARMS%) do call :NEQtest %%i B
699 for %%i in (%STR_PARMS%) do call :NEQtest %%i AB
700 for %%i in (%STR_PARMS%) do call :NEQtest %%i BA
701 for %%i in (%STR_PARMS%) do call :NEQtest %%i AA
702 for %%i in (%STR_PARMS%) do call :GEQtest %%i A
703 for %%i in (%STR_PARMS%) do call :GEQtest %%i B
704 for %%i in (%STR_PARMS%) do call :GEQtest %%i AB
705 for %%i in (%STR_PARMS%) do call :GEQtest %%i BA
706 for %%i in (%STR_PARMS%) do call :GEQtest %%i AA
707 for %%i in (%STR_PARMS%) do call :GTRtest %%i A
708 for %%i in (%STR_PARMS%) do call :GTRtest %%i B
709 for %%i in (%STR_PARMS%) do call :GTRtest %%i AB
710 for %%i in (%STR_PARMS%) do call :GTRtest %%i BA
711 for %%i in (%STR_PARMS%) do call :GTRtest %%i AA
712 echo ------ for numbers
713 if -1 LSS 1 (echo negative numbers handled)
714 if not -1 LSS -10 (echo negative numbers handled)
715 if not 9 LSS 010 (echo octal handled)
716 if not -010 LSS -8 (echo also in negative form)
717 if 4 LSS 0x5 (echo hexa handled)
718 if not -1 LSS -0x1A (echo also in negative form)
719 if 11 LSS 101 (echo 11 LSS 101)
720 set INT_PARMS=0 1 10 9
721 for %%i in (%INT_PARMS%) do call :LSStest %%i 0
722 for %%i in (%INT_PARMS%) do call :LSStest %%i 1
723 for %%i in (%INT_PARMS%) do call :LSStest %%i 10
724 for %%i in (%INT_PARMS%) do call :LSStest %%i 9
725 for %%i in (%INT_PARMS%) do call :LEQtest %%i 0
726 for %%i in (%INT_PARMS%) do call :LEQtest %%i 1
727 for %%i in (%INT_PARMS%) do call :LEQtest %%i 10
728 for %%i in (%INT_PARMS%) do call :LEQtest %%i 9
729 for %%i in (%INT_PARMS%) do call :EQUtest %%i 0
730 for %%i in (%INT_PARMS%) do call :EQUtest %%i 1
731 for %%i in (%INT_PARMS%) do call :EQUtest %%i 10
732 for %%i in (%INT_PARMS%) do call :EQUtest %%i 9
733 if 011 EQU 9 (echo octal ok)
734 if 0xA1 EQU 161 (echo hexa ok)
735 if 0xA1 EQU "161" (echo hexa should be be recognized) else (echo string/hexa compare ok)
736 if "0xA1" EQU 161 (echo hexa should be be recognized) else (echo string/hexa compare ok)
737 for %%i in (%INT_PARMS%) do call :NEQtest %%i 0
738 for %%i in (%INT_PARMS%) do call :NEQtest %%i 1
739 for %%i in (%INT_PARMS%) do call :NEQtest %%i 10
740 for %%i in (%INT_PARMS%) do call :NEQtest %%i 9
741 for %%i in (%INT_PARMS%) do call :GEQtest %%i 0
742 for %%i in (%INT_PARMS%) do call :GEQtest %%i 1
743 for %%i in (%INT_PARMS%) do call :GEQtest %%i 10
744 for %%i in (%INT_PARMS%) do call :GEQtest %%i 9
745 for %%i in (%INT_PARMS%) do call :GTRtest %%i 0
746 for %%i in (%INT_PARMS%) do call :GTRtest %%i 1
747 for %%i in (%INT_PARMS%) do call :GTRtest %%i 10
748 for %%i in (%INT_PARMS%) do call :GTRtest %%i 9
749 echo ------ for numbers and stringified numbers
750 if not "1" EQU 1 (echo strings and integers not equal) else echo foo
751 if not 1 EQU "1" (echo strings and integers not equal) else echo foo
752 if '1' EQU 1 echo '1' EQU 1
753 if 1 EQU '1' echo 1 EQU '1'
754 if not "1" GEQ 1 (echo foo) else echo bar
755 if "10" GEQ "1" echo "10" GEQ "1"
756 if '1' GEQ 1 (echo '1' GEQ 1) else echo NT4
757 if 1 GEQ "1" echo 1 GEQ "1"
758 if "1" GEQ "1" echo "1" GEQ "1"
759 if '1' GEQ "1" echo '1' GEQ "1"
760 if "10" GEQ "1" echo "10" GEQ "1"
761 if not 1 GEQ '1' (echo non NT4) else echo 1 GEQ '1'
762 for %%i in ("1" '1') do call :GEQtest %%i '1'
763 if "10" GEQ '1' (echo "10" GEQ '1') else echo foo
764 if 1 GEQ "10" (echo 1 GEQ "10") else echo foo
765 if "1" GEQ "10" (echo 1 GEQ "10") else echo foo
766 if '1' GEQ "10" (echo '1' GEQ "10") else echo foo
767 if "10" GEQ "10" (echo "10" GEQ "10")
768 goto :endIfCompOpsSubroutines
769
770 rem IF subroutines helpers
771 :LSStest
772 if %1 LSS %2 echo %1 LSS %2
773 goto :eof
774 :LEQtest
775 if %1 LEQ %2 echo %1 LEQ %2
776 goto :eof
777 :EQUtest
778 if %1 EQU %2 echo %1 EQU %2
779 goto :eof
780 :NEQtest
781 if %1 NEQ %2 echo %1 NEQ %2
782 goto :eof
783 :GEQtest
784 if %1 GEQ %2 echo %1 GEQ %2
785 goto :eof
786 :GTRtest
787 if %1 GTR %2 echo %1 GTR %2
788 goto :eof
789
790 :endIfCompOpsSubroutines
791 set STR_PARMS=
792 set INT_PARMS=
793
794 echo ------------ Testing for ------------
795 echo --- plain FOR
796 for %%i in (A B C) do echo %%i
797 for %%i in (A B C) do echo %%I
798 for %%i in (A B C) do echo %%j
799 for %%i in (A B C) do call :forTestFun1 %%i
800 for %%i in (1,4,1) do echo %%i
801 for %%i in (A, B,C) do echo %%i
802 for %%i in  (X) do echo %%i
803 for@tab@%%i in  (X2) do echo %%i
804 for %%i in@tab@(X3) do echo %%i
805 for %%i in (@tab@ foo@tab@) do echo %%i
806 for@tab@ %%i in@tab@(@tab@M) do echo %%i
807 for %%i@tab@in (X)@tab@do@tab@echo %%i
808 for@tab@ %%j in@tab@(@tab@M, N, O@tab@) do echo %%j
809 for %%i in (`echo A B`) do echo %%i
810 for %%i in ('echo A B') do echo %%i
811 for %%i in ("echo A B") do echo %%i
812 for %%i in ("A B" C) do echo %%i
813 goto :endForTestFun1
814 :forTestFun1
815 echo %1
816 goto :eof
817 :endForTestFun1
818 echo --- imbricated FORs
819 for %%i in (X) do (
820     for %%j in (Y) do (
821         echo %%i %%j))
822 for %%i in (X) do (
823     for %%I in (Y) do (
824         echo %%i %%I))
825 for %%i in (A B) do (
826     for %%j in (C D) do (
827         echo %%i %%j))
828 for %%i in (A B) do (
829     for %%j in (C D) do (
830         call :forTestFun2 %%i %%j ))
831 goto :endForTestFun2
832 :forTestFun2
833 echo %1 %2
834 goto :eof
835 :endForTestFun2
836 mkdir foobar & cd foobar
837 mkdir foo
838 mkdir bar
839 mkdir baz
840 echo > bazbaz
841 echo --- basic wildcards
842 for %%i in (ba*) do echo %%i
843 echo --- for /d
844 for /d %%i in (baz foo bar) do echo %%i 2>&1
845 rem Confirm we don't match files:
846 for /d %%i in (bazb*) do echo %%i 2>&1
847 for /d %%i in (bazb2*) do echo %%i 2>&1
848 rem Show we pass through non wildcards
849 for /d %%i in (PASSED) do echo %%i
850 for /d %%i in (xxx) do (
851   echo %%i - Should be xxx
852   echo Expected second line
853 )
854 rem Show we issue no messages on failures
855 for /d %%i in (FAILED?) do echo %%i 2>&1
856 for /d %%i in (FAILED?) do (
857   echo %%i - Unexpected!
858   echo FAILED Unexpected second line
859 )
860 for /d %%i in (FAILED*) do echo %%i 2>&1
861 for /d %%i in (FAILED*) do (
862   echo %%i - Unexpected!
863   echo FAILED Unexpected second line
864 )
865 rem FIXME can't test wildcard expansion here since it's listed in directory
866 rem order, and not in alphabetic order.
867 rem Proper testing would need a currently missing "sort" program implementation.
868 rem for /d %%i in (ba*) do echo %%i>> tmp
869 rem sort < tmp
870 rem del tmp
871 rem for /d %%i in (?a*) do echo %%i>> tmp
872 rem sort < tmp
873 rem del tmp
874 rem for /d %%i in (*) do echo %%i>> tmp
875 rem sort < tmp
876 rem del tmp
877 echo > baz\bazbaz
878 goto :TestForR
879
880 :SetExpected
881 del temp.bat 2>nul
882 call :WriteLine set found=N
883 for /l %%i in (1,1,%expectedresults%) do (
884   call :WriteLine if "%%%%expectedresults.%%i%%%%"=="%%%%1" set found=Y
885   call :WriteLine if "%%%%found%%%%"=="Y" set expectedresults.%%i=
886   call :WriteLine if "%%%%found%%%%"=="Y" goto :eof
887 )
888 call :WriteLine echo Got unexpected result: "%%%%1"
889 goto :eof
890
891 :WriteLine
892 echo %*>> temp.bat
893 goto :EOF
894
895 :ValidateExpected
896 del temp.bat 2>nul
897 for /l %%i in (1,1,%expectedresults%) do  call :WriteLine if not "%%%%expectedresults.%%i%%%%"=="" echo Found missing result: "%%%%expectedresults.%%i%%%%"
898 call temp.bat
899 del temp.bat 2>nul
900 goto :eof
901
902 :TestForR
903 rem %CD% does not tork on NT4 so use the following workaround
904 for /d %%i in (.) do set CURDIR=%%~dpnxi
905
906 echo --- for /R
907 echo Plain directory enumeration
908 set expectedresults=4
909 set expectedresults.1=%CURDIR%\.
910 set expectedresults.2=%CURDIR%\bar\.
911 set expectedresults.3=%CURDIR%\baz\.
912 set expectedresults.4=%CURDIR%\foo\.
913 call :SetExpected
914 for /R %%i in (.) do call temp.bat %%i
915 call :ValidateExpected
916
917 echo Plain directory enumeration from provided root
918 set expectedresults=4
919 set expectedresults.1=%CURDIR%\.
920 set expectedresults.2=%CURDIR%\bar\.
921 set expectedresults.3=%CURDIR%\baz\.
922 set expectedresults.4=%CURDIR%\foo\.
923 if "%CD%"=="" goto :SkipBrokenNT4
924 call :SetExpected
925 for /R "%CURDIR%" %%i in (.) do call temp.bat %%i
926 call :ValidateExpected
927 :SkipBrokenNT4
928
929 echo File enumeration
930 set expectedresults=2
931 set expectedresults.1=%CURDIR%\baz\bazbaz
932 set expectedresults.2=%CURDIR%\bazbaz
933 call :SetExpected
934 for /R %%i in (baz*) do call temp.bat %%i
935 call :ValidateExpected
936
937 echo File enumeration from provided root
938 set expectedresults=2
939 set expectedresults.1=%CURDIR%\baz\bazbaz
940 set expectedresults.2=%CURDIR%\bazbaz
941 call :SetExpected
942 for /R %%i in (baz*) do call temp.bat %%i
943 call :ValidateExpected
944
945 echo Mixed enumeration
946 set expectedresults=6
947 set expectedresults.1=%CURDIR%\.
948 set expectedresults.2=%CURDIR%\bar\.
949 set expectedresults.3=%CURDIR%\baz\.
950 set expectedresults.4=%CURDIR%\baz\bazbaz
951 set expectedresults.5=%CURDIR%\bazbaz
952 set expectedresults.6=%CURDIR%\foo\.
953 call :SetExpected
954 for /R %%i in (. baz*) do call temp.bat %%i
955 call :ValidateExpected
956
957 echo Mixed enumeration from provided root
958 set expectedresults=6
959 set expectedresults.1=%CURDIR%\.
960 set expectedresults.2=%CURDIR%\bar\.
961 set expectedresults.3=%CURDIR%\baz\.
962 set expectedresults.4=%CURDIR%\baz\bazbaz
963 set expectedresults.5=%CURDIR%\bazbaz
964 set expectedresults.6=%CURDIR%\foo\.
965 call :SetExpected
966 for /R %%i in (. baz*) do call temp.bat %%i
967 call :ValidateExpected
968
969 echo With duplicates enumeration
970 set expectedresults=12
971 set expectedresults.1=%CURDIR%\bar\bazbaz
972 set expectedresults.2=%CURDIR%\bar\fred
973 set expectedresults.3=%CURDIR%\baz\bazbaz
974 set expectedresults.4=%CURDIR%\baz\bazbaz
975 set expectedresults.5=%CURDIR%\baz\bazbaz
976 set expectedresults.6=%CURDIR%\baz\fred
977 set expectedresults.7=%CURDIR%\bazbaz
978 set expectedresults.8=%CURDIR%\bazbaz
979 set expectedresults.9=%CURDIR%\bazbaz
980 set expectedresults.10=%CURDIR%\foo\bazbaz
981 set expectedresults.11=%CURDIR%\foo\fred
982 set expectedresults.12=%CURDIR%\fred
983 call :SetExpected
984 for /R %%i in (baz* bazbaz fred ba*) do call temp.bat %%i
985 call :ValidateExpected
986
987 echo Strip missing wildcards, keep unwildcarded names
988 set expectedresults=6
989 set expectedresults.1=%CURDIR%\bar\jim
990 set expectedresults.2=%CURDIR%\baz\bazbaz
991 set expectedresults.3=%CURDIR%\baz\jim
992 set expectedresults.4=%CURDIR%\bazbaz
993 set expectedresults.5=%CURDIR%\foo\jim
994 set expectedresults.6=%CURDIR%\jim
995 call :SetExpected
996 for /R %%i in (baz* fred* jim) do call temp.bat %%i
997 call :ValidateExpected
998
999 echo for /R passed
1000 cd .. & rd /s/Q foobar
1001 echo --- for /L
1002 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
1003 for /L %%i in (1,2,0) do echo %%i
1004 for@tab@/L %%i in (1,2,0) do echo %%i
1005 for /L %%i in (1,2,6) do echo %%i
1006 for /l %%i in (1 ,2,6) do echo %%i
1007 for /L %%i in (a,2,3) do echo %%i
1008 for /L %%i in (1,2,-1) do echo %%i
1009 for /L %%i in (-4,-1,-1) do echo %%i
1010 for /L %%i in (1,-2,-2) do echo %%i
1011 for /L %%i in (1,2,a) do echo %%i
1012 echo ErrorLevel %ErrorLevel%
1013 for /L %%i in (1,a,b) do echo %%i
1014 echo ErrorLevel %ErrorLevel%
1015 rem Test boundaries
1016 for /l %%i in (1,1,4) do echo %%i
1017 for /l %%i in (1,2,4) do echo %%i
1018 for /l %%i in (4,-1,1) do echo %%i
1019 for /l %%i in (4,-2,1) do echo %%i
1020 for /l %%i in (1,-1,4) do echo %%i
1021 for /l %%i in (4,1,1) do echo %%i
1022 for /L %%i in (a,2,b) do echo %%i
1023 for /L %%i in (1,1,1) do echo %%i
1024 for /L %%i in (1,-2,-1) do echo %%i
1025 for /L %%i in (-1,-1,-1) do echo %%i
1026 for /L %%i in (1,2, 3) do echo %%i
1027 rem Test zero iteration skips the body of the for
1028 for /L %%i in (2,2,1) do (
1029   echo %%i
1030   echo FAILED
1031 )
1032 echo --- for /a
1033 rem No output when using "set expr" syntax, unless in interactive mode
1034 rem Need to use "set envvar=expr" to use in a batch script
1035 echo ------ individual operations
1036 set var=0
1037 set /a var=1 +2 & echo %var%
1038 set /a var=1 +-2 & echo %var%
1039 set /a var=1 --2 & echo %var%
1040 set /a var=2* 3 & echo %var%
1041 set /a var=-2* -5 & echo %var%
1042 set /a var=12/3 & echo %var%
1043 set /a var=13/3 & echo %var%
1044 set /a var=-13/3 & echo %var%
1045 rem FIXME Divide by zero should return an error, but error messages cannot be tested with current infrastructure
1046 set /a var=5 %% 5 & echo %var%
1047 set /a var=5 %% 3 & echo %var%
1048 set /a var=5 %% -3 & echo %var%
1049 set /a var=-5 %% -3 & echo %var%
1050 set /a var=1 ^<^< 0 & echo %var%
1051 set /a var=1 ^<^< 2 & echo %var%
1052 set /a var=1 ^<^< -2 & echo %var%
1053 set /a var=-1 ^<^< -2 & echo %var%
1054 set /a var=-1 ^<^< 2 & echo %var%
1055 set /a var=9 ^>^> 0 & echo %var%
1056 set /a var=9 ^>^> 2 & echo %var%
1057 set /a var=9 ^>^> -2 & echo %var%
1058 set /a var=-9 ^>^> -2 & echo %var%
1059 set /a var=-9 ^>^> 2 & echo %var%
1060 set /a var=5 ^& 0 & echo %var%
1061 set /a var=5 ^& 1 & echo %var%
1062 set /a var=5 ^& 3 & echo %var%
1063 set /a var=5 ^& 4 & echo %var%
1064 set /a var=5 ^& 1 & echo %var%
1065 set /a var=5 ^| 0 & echo %var%
1066 set /a var=5 ^| 1 & echo %var%
1067 set /a var=5 ^| 3 & echo %var%
1068 set /a var=5 ^| 4 & echo %var%
1069 set /a var=5 ^| 1 & echo %var%
1070 set /a var=5 ^^ 0 & echo %var%
1071 set /a var=5 ^^ 1 & echo %var%
1072 set /a var=5 ^^ 3 & echo %var%
1073 set /a var=5 ^^ 4 & echo %var%
1074 set /a var=5 ^^ 1 & echo %var%
1075 echo ------ precedence and grouping
1076 set /a var=4 + 2*3 & echo %var%
1077 set /a var=(4+2)*3 & echo %var%
1078 set /a var=4 * 3/5 & echo %var%
1079 set /a var=(4 * 3)/5 & echo %var%
1080 set /a var=4 * 5 %% 4 & echo %var%
1081 set /a var=4 * (5 %% 4) & echo %var%
1082 set /a var=3 %% (5 + 8 %% 3 ^^ 2) & echo %var%
1083 set /a var=3 %% (5 + 8 %% 3 ^^ -2) & echo %var%
1084 echo ------ octal and hexadecimal
1085 set /a var=0xf + 3 & echo %var%
1086 set /a var=0xF + 3 & echo %var%
1087 set /a var=015 + 2 & echo %var%
1088 set /a var=3, 8+3,0 & echo %var%
1089 echo ------ variables
1090 set /a var=foo=3, foo+1 & echo %var%
1091 if defined foo (echo %foo%) else (
1092     echo foo not defined
1093 )
1094 set /a var=foo=3, foo+=1 & echo %var%
1095 set /a var=foo=3, bar=1, bar+=foo, bar & echo %var%
1096 set /a var=foo*= foo & echo %var%
1097 set /a var=whateverNonExistingVar & echo %var%
1098 set /a var=whateverNonExistingVar + bar & echo %var%
1099 set /a var=foo -= foo + 7 & echo %var%
1100 set /a var=foo /= 3 + 2 & echo %var%
1101 set /a var=foo=5, foo %%=2 & echo %var%
1102 set /a var=foo ^<^<= 2 & echo %var%
1103 set /a var=foo ^>^>= 2 & echo %var%
1104 set /a var=foo ^&= 2 & echo %var%
1105 set /a var=foo=5, foo ^|= 2 & echo %var%
1106 set /a var=foo=5, foo ^^= 2 & echo %var%
1107 set /a var=foo=19, foo %%= 4 + (bar %%= 7) & echo.
1108 set foo=
1109 set bar=
1110 set var=
1111 echo --- for /F
1112 mkdir foobar & cd foobar
1113 echo ------ string argument
1114 for /F %%i in ("a b c") do echo %%i
1115 for /f %%i in ("a ") do echo %%i
1116 for /f %%i in ("a") do echo %%i
1117 fOr /f %%i in (" a") do echo %%i
1118 for /f %%i in (" a ") do echo %%i
1119 echo ------ fileset argument
1120 echo --------- basic blank handling
1121 echo a b c>foo
1122 for /f %%i in (foo) do echo %%i
1123 echo a >foo
1124 for /f %%i in (foo) do echo %%i
1125 echo a>foo
1126 for /f %%i in (foo) do echo %%i
1127 echo  a>foo
1128 for /f %%i in (foo) do echo %%i
1129 echo  a >foo
1130 for /f %%i in (foo) do echo %%i
1131 echo. > foo
1132 for /f %%i in (foo) do echo %%i
1133 echo. >> foo
1134 echo b > foo
1135 for /f %%i in (foo) do echo %%i
1136 echo --------- multi-line with empty lines
1137 echo a Z f> foo
1138 echo. >> foo
1139 echo.>> foo
1140 echo b bC>> foo
1141 echo c>> foo
1142 echo. >> foo
1143 for /f %%b in (foo) do echo %%b
1144 echo --------- multiple files
1145 echo q w > bar
1146 echo.>> bar
1147 echo kkk>>bar
1148 for /f %%k in (foo bar) do echo %%k
1149 for /f %%k in (bar foo) do echo %%k
1150 echo ------ command argument
1151 rem Not implemented on NT4, need to skip it as no way to get output otherwise
1152 if "%CD%"=="" goto :SkipFORFcmdNT4
1153 for /f %%i in ('echo.Passed1') do echo %%i
1154 for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i
1155 for /f usebackq %%i in (`echo.Passed3`) do echo %%i
1156 goto :ContinueFORF
1157 :SkipFORFcmdNT4
1158 for /l %%i in (1,1,3) do echo Missing functionality - Broken%%i
1159 :ContinueFORF
1160 rem FIXME: Rest not testable right now in wine: not implemented and would need
1161 rem preliminary grep-like program implementation (e.g. like findstr or fc) even
1162 rem for a simple todo_wine test
1163 rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported
1164 rem (for /f usebackq %%i in (`echo z a b`) do echo %%i) || echo not supported
1165 echo ------ eol option
1166 if "%CD%"=="" goto :SkipFORFeolNT4
1167 echo Line one>foo
1168 echo and Line two>>foo
1169 echo Line three>>foo
1170 for /f "eol=L" %%i in (foo) do echo %%i
1171 for /f "eol=a" %%i in (foo) do echo %%i
1172 del foo
1173 goto :ContinueFORFeol
1174 :SkipFORFeolNT4
1175 for /l %%i in (1,1,3) do echo Broken NT4 functionality%%i
1176 :ContinueFORFeol
1177 for /f "eol=@" %%i in ("    ad") do echo %%i
1178 for /f "eol=@" %%i in (" z@y") do echo %%i
1179 for /f "eol=|" %%i in ("a|d") do echo %%i
1180 for /f "eol=@" %%i in ("@y") do echo %%i > output_file
1181 if not exist output_file (echo no output) else (del output_file)
1182 for /f "eol==" %%i in ("=y") do echo %%i > output_file
1183 if not exist output_file (echo no output) else (del output_file)
1184 echo ------ delims option
1185 for /f "delims=|" %%i in ("a|d") do echo %%i
1186 for /f "delims=|" %%i in ("a |d") do echo %%i
1187 for /f "delims=|" %%i in ("a d|") do echo %%i
1188 for /f "delims=| " %%i in ("a d|") do echo %%i
1189 for /f "delims==" %%i in ("C r=d|") do echo %%i
1190 for /f "delims=" %%i in ("foo bar baz") do echo %%i
1191 for /f "delims=" %%i in ("c:\foo bar baz\..") do echo %%~fi
1192 echo ------ skip option
1193 echo a > foo
1194 echo b >> foo
1195 echo c >> foo
1196 for /f "skip=2" %%i in (foo) do echo %%i
1197 for /f "skip=3" %%i in (foo) do echo %%i > output_file
1198 if not exist output_file (echo no output) else (del output_file)
1199 for /f "skip=4" %%i in (foo) do echo %%i > output_file
1200 if not exist output_file (echo no output) else (del output_file)
1201 for /f "skip=02" %%i in (foo) do echo %%i
1202 for /f "skip=0x2" %%i in (foo) do echo %%i
1203 for /f "skip=1" %%i in ("skipme") do echo %%i > output_file
1204 if not exist output_file (echo no output) else (del output_file)
1205 cd ..
1206 rd /s/q foobar
1207
1208 echo ------------ Testing del /a ------------
1209 del /f/q *.test > nul
1210 echo r > r.test
1211 attrib +r r.test
1212 echo not-r > not-r.test
1213
1214 if not exist not-r.test echo not-r.test not found before delete, bad
1215 del /a:-r *.test
1216 if not exist not-r.test echo not-r.test not found after delete, good
1217
1218 if not exist r.test echo r.test not found before delete, bad
1219 if exist r.test echo r.test found before delete, good
1220 del /a:r *.test
1221 if not exist r.test echo r.test not found after delete, good
1222 if exist r.test echo r.test found after delete, bad
1223
1224 echo ------------ Testing del /q ------------
1225 mkdir del_q_dir
1226 cd del_q_dir
1227 echo abc > file1
1228 echo abc > file2.dat
1229 rem If /q doesn't work, cmd will prompt and the test case should hang
1230 del /q * > nul
1231 for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a
1232 for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a
1233 cd ..
1234 rmdir del_q_dir
1235
1236 echo ------------ Testing del /s ------------
1237 mkdir "foo bar"
1238 cd "foo bar"
1239 mkdir "foo:"
1240 echo hi > file1.dat
1241 echo there > file2.dat
1242 echo bub > file3.dat
1243 echo bye > "file with spaces.dat"
1244 cd ..
1245 del /s file1.dat > nul
1246 del file2.dat /s > nul
1247 del "file3.dat" /s > nul
1248 del "file with spaces.dat" /s > nul
1249 cd "foo bar"
1250 for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f
1251 for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat
1252 if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat"
1253 if exist "file with spaces.dat" del "file with spaces.dat"
1254 rmdir "foo:"
1255 cd ..
1256 rmdir "foo bar"
1257
1258 echo ------------ Testing rename ------------
1259 mkdir foobar & cd foobar
1260 echo --- ren and rename are synonymous
1261 echo > foo
1262 rename foo bar
1263 if exist foo echo foo should be renamed!
1264 if exist bar echo foo renamed to bar
1265 ren bar foo
1266 if exist bar echo bar should be renamed!
1267 if exist foo echo bar renamed to foo
1268 echo --- name collision
1269 echo foo>foo
1270 echo bar>bar
1271 ren foo bar 2> nul
1272 type foo
1273 type bar
1274 rem no-op
1275 ren foo foo
1276 mkdir baz
1277 ren foo baz\abc
1278 echo --- rename read-only files
1279 echo > file1
1280 attrib +r file1
1281 ren file1 file2
1282 if not exist file1 (
1283     if exist file2 (
1284         echo read-only file renamed
1285     )
1286 ) else (
1287     echo read-only file not renamed!
1288 )
1289 echo --- rename directories
1290 mkdir rep1
1291 ren rep1 rep2
1292 if not exist rep1 (
1293     if exist rep2 (
1294         echo dir renamed
1295     )
1296 )
1297 attrib +r rep2
1298 ren rep2 rep1
1299 if not exist rep2 (
1300     if exist rep1 (
1301         echo read-only dir renamed
1302     )
1303 )
1304 echo --- rename in other directory
1305 if not exist baz\abc (
1306     echo rename impossible in other directory
1307     if exist foo echo original file still present
1308 ) else (
1309     echo shouldn't rename in other directory!
1310     if not exist foo echo original file not present anymore
1311 )
1312 cd .. & rd /s/q foobar
1313
1314 echo ------------ Testing move ------------
1315 mkdir foobar & cd foobar
1316 echo --- file move
1317 echo >foo
1318 move foo bar > nul 2>&1
1319 if not exist foo (
1320     if exist bar (
1321         echo file move succeeded
1322     )
1323 )
1324 echo bar>bar
1325 echo baz> baz
1326 move /Y bar baz > nul 2>&1
1327 if not exist bar (
1328     if exist baz (
1329         echo file move with overwrite succeeded
1330     )
1331 ) else (
1332     echo file overwrite impossible!
1333     del bar
1334 )
1335 type baz
1336
1337 attrib +r baz
1338 move baz bazro > nul 2>&1
1339 if not exist baz (
1340     if exist bazro (
1341         echo read-only files are moveable
1342         move bazro baz > nul 2>&1
1343     )
1344 ) else (
1345     echo read-only file not moved!
1346 )
1347 attrib -r baz
1348 mkdir rep
1349 move baz rep > nul 2>&1
1350 if not exist baz (
1351     if exist rep\baz (
1352         echo file moved in subdirectory
1353     )
1354 )
1355 call :setError 0
1356 move rep\baz . > nul 2>&1
1357 move /Y baz baz > nul 2>&1
1358 if errorlevel 1 (
1359     echo moving a file to itself should be a no-op!
1360 ) else (
1361     echo moving a file to itself is a no-op
1362 )
1363 echo ErrorLevel: %ErrorLevel%
1364 call :setError 0
1365 del baz
1366 echo --- directory move
1367 mkdir foo\bar
1368 mkdir baz
1369 echo baz2>baz\baz2
1370 move baz foo\bar > nul 2>&1
1371 if not exist baz (
1372     if exist foo\bar\baz\baz2 (
1373         echo simple directory move succeeded
1374     )
1375 )
1376 call :setError 0
1377 mkdir baz
1378 move baz baz > nul 2>&1
1379 echo moving a directory to itself gives error; errlevel %ErrorLevel%
1380 echo ------ dir in dir move
1381 rd /s/q foo
1382 mkdir foo bar
1383 echo foo2>foo\foo2
1384 echo bar2>bar\bar2
1385 move foo bar > nul 2>&1
1386 if not exist foo (
1387     if exist bar (
1388         dir /b /ad bar
1389         dir /b /a-d bar
1390         dir /b bar\foo
1391     )
1392 )
1393 cd .. & rd /s/q foobar
1394
1395 echo ------------ Testing mkdir ------------
1396 call :setError 0
1397 echo --- md and mkdir are synonymous
1398 mkdir foobar
1399 echo %ErrorLevel%
1400 rmdir foobar
1401 md foobar
1402 echo %ErrorLevel%
1403 rmdir foobar
1404 echo --- creating an already existing directory/file must fail
1405 mkdir foobar
1406 md foobar
1407 echo %ErrorLevel%
1408 rmdir foobar
1409 echo > foobar
1410 mkdir foobar
1411 echo %ErrorLevel%
1412 del foobar
1413 echo --- multilevel path creation
1414 mkdir foo
1415 echo %ErrorLevel%
1416 mkdir foo\bar\baz
1417 echo %ErrorLevel%
1418 cd foo
1419 echo %ErrorLevel%
1420 cd bar
1421 echo %ErrorLevel%
1422 cd baz
1423 echo %ErrorLevel%
1424 echo > ..\..\bar2
1425 mkdir ..\..\..\foo\bar2
1426 echo %ErrorLevel%
1427 del ..\..\bar2
1428 mkdir ..\..\..\foo\bar2
1429 echo %ErrorLevel%
1430 rmdir ..\..\..\foo\bar2
1431 cd ..
1432 rmdir baz
1433 cd ..
1434 rmdir bar
1435 cd ..
1436 rmdir foo
1437 echo %ErrorLevel%
1438 echo --- trailing backslashes
1439 mkdir foo\\\\
1440 echo %ErrorLevel%
1441 if exist foo (rmdir foo & echo dir created
1442 ) else ( echo dir not created )
1443 echo %ErrorLevel%
1444 echo --- invalid chars
1445 mkdir ?
1446 echo mkdir ? gives errorlevel %ErrorLevel%
1447 call :setError 0
1448 mkdir ?\foo
1449 echo mkdir ?\foo gives errorlevel %ErrorLevel%
1450 call :setError 0
1451 mkdir foo\?
1452 echo mkdir foo\? gives errorlevel %ErrorLevel%
1453 if exist foo (rmdir foo & echo ok, foo created
1454 ) else ( echo foo not created )
1455 call :setError 0
1456 mkdir foo\bar\?
1457 echo mkdir foo\bar\? gives errorlevel %ErrorLevel%
1458 call :setError 0
1459 if not exist foo (
1460     echo bad, foo not created
1461 ) else (
1462     cd foo
1463     if exist bar (
1464         echo ok, foo\bar created
1465         rmdir bar
1466     )
1467     cd ..
1468     rmdir foo
1469 )
1470 echo --- multiple directories at once
1471 mkdir foobaz & cd foobaz
1472 mkdir foo bar\baz foobar "bazbaz" .\"zabzab"
1473 if exist foo (echo foo created) else echo foo not created!
1474 if exist bar (echo bar created) else echo bar not created!
1475 if exist foobar (echo foobar created) else echo foobar not created!
1476 if exist bar\baz (echo bar\baz created) else echo bar\baz not created!
1477 if exist bazbaz (echo bazbaz created) else echo bazbaz not created!
1478 if exist zabzab (echo zabzab created) else echo zabzab not created!
1479 cd .. & rd /s/q foobaz
1480 call :setError 0
1481 mkdir foo\*
1482 echo mkdir foo\* errorlevel %ErrorLevel%
1483 if exist foo (rmdir foo & echo ok, foo created
1484 ) else ( echo bad, foo not created )
1485
1486 echo ------------ Testing rmdir ------------
1487 call :setError 0
1488 rem rd and rmdir are synonymous
1489 mkdir foobar
1490 rmdir foobar
1491 echo %ErrorLevel%
1492 if not exist foobar echo dir removed
1493 mkdir foobar
1494 rd foobar
1495 echo %ErrorLevel%
1496 if not exist foobar echo dir removed
1497 rem Removing nonexistent directory
1498 rmdir foobar
1499 echo %ErrorLevel%
1500 rem Removing single-level directories
1501 echo > foo
1502 rmdir foo
1503 echo %ErrorLevel%
1504 if exist foo echo file not removed
1505 del foo
1506 mkdir foo
1507 echo > foo\bar
1508 rmdir foo
1509 echo %ErrorLevel%
1510 if exist foo echo non-empty dir not removed
1511 del foo\bar
1512 mkdir foo\bar
1513 rmdir foo
1514 echo %ErrorLevel%
1515 if exist foo echo non-empty dir not removed
1516 rmdir foo\bar
1517 rmdir foo
1518 rem Recursive rmdir
1519 mkdir foo\bar\baz
1520 rmdir /s /Q foo
1521 if not exist foo (
1522     echo recursive rmdir succeeded
1523 ) else (
1524     rd foo\bar\baz
1525     rd foo\bar
1526     rd foo
1527 )
1528 mkdir foo\bar\baz
1529 echo foo > foo\bar\brol
1530 rmdir /s /Q foo 2>&1
1531 if not exist foo (
1532     echo recursive rmdir succeeded
1533 ) else (
1534     rd foo\bar\baz
1535     del foo\bar\brol
1536     rd foo\bar
1537     rd foo
1538 )
1539 rem multiples directories at once
1540 mkdir foobaz & cd foobaz
1541 mkdir foo
1542 mkdir bar\baz
1543 mkdir foobar
1544 rd /s/q foo bar foobar
1545 if not exist foo (echo foo removed) else echo foo not removed!
1546 if not exist bar (echo bar removed) else echo bar not removed!
1547 if not exist foobar (echo foobar removed) else echo foobar not removed!
1548 if not exist bar\baz (echo bar\baz removed) else echo bar\baz not removed!
1549 cd .. & rd /s/q foobaz
1550
1551 echo ------------ Testing pushd/popd ------------
1552 cd
1553 echo --- popd is no-op when dir stack is empty
1554 popd
1555 cd
1556 echo --- pushing non-existing dir
1557 pushd foobar
1558 cd
1559 echo --- basic behaviour
1560 mkdir foobar\baz
1561 pushd foobar
1562 cd
1563 popd
1564 cd
1565 pushd foobar
1566 pushd baz
1567 cd
1568 popd
1569 cd
1570 pushd baz
1571 popd
1572 cd
1573 popd
1574 cd
1575 pushd .
1576 cd foobar\baz
1577 pushd ..
1578 cd
1579 popd
1580 popd
1581 cd
1582 rd /s/q foobar
1583
1584 echo ------------ Testing attrib ------------
1585 rem FIXME Add tests for archive, hidden and system attributes + mixed attributes modifications
1586 mkdir foobar & cd foobar
1587 echo foo original contents> foo
1588 attrib foo
1589 echo > bar
1590 echo --- read-only attribute
1591 rem Read-only files cannot be altered or deleted, unless forced
1592 attrib +R foo
1593 attrib foo
1594 dir /Ar /B
1595 echo bar>> foo
1596 type foo
1597 del foo > NUL 2>&1
1598 if exist foo (
1599     echo Read-only file not deleted
1600 ) else (
1601     echo Should not delete read-only file!
1602 )
1603 del /F foo
1604 if not exist foo (
1605     echo Read-only file forcibly deleted
1606 ) else (
1607     echo Should delete read-only file with del /F!
1608     attrib -r foo
1609     del foo
1610 )
1611 cd .. & rd /s/q foobar
1612 echo --- recursive behaviour
1613 mkdir foobar\baz & cd foobar
1614 echo > level1
1615 echo > whatever
1616 echo > baz\level2
1617 attrib baz\level2
1618 cd ..
1619 attrib +R l*vel? /S > nul 2>&1
1620 cd foobar
1621 attrib level1
1622 attrib baz\level2
1623 echo > bar
1624 attrib bar
1625 cd .. & rd /s/q foobar
1626 echo --- folders processing
1627 mkdir foobar
1628 attrib foobar
1629 cd foobar
1630 mkdir baz
1631 echo toto> baz\toto
1632 attrib +r baz /s /d > nul 2>&1
1633 attrib baz
1634 attrib baz\toto
1635 echo lulu>>baz\toto
1636 type baz\toto
1637 echo > baz\lala
1638 rem Oddly windows allows file creation in a read-only directory...
1639 if exist baz\lala (echo file created in read-only dir) else echo file not created
1640 cd .. & rd /s/q foobar
1641
1642 echo ------------ Testing assoc ------------
1643 rem FIXME Can't test error messages in the current test system, so we have to use some kludges
1644 rem FIXME Revise once || conditional execution is fixed
1645 mkdir foobar & cd foobar
1646 echo --- setting association
1647 assoc .foo > baz
1648 type baz
1649 echo ---
1650
1651 assoc .foo=bar
1652 assoc .foo
1653
1654 rem association set system-wide
1655 echo @echo off> tmp.cmd
1656 echo echo +++>> tmp.cmd
1657 echo assoc .foo>> tmp.cmd
1658 cmd /c tmp.cmd
1659
1660 echo --- resetting association
1661 assoc .foo=
1662 assoc .foo > baz
1663 type baz
1664 echo ---
1665
1666 rem association removal set system-wide
1667 cmd /c tmp.cmd > baz
1668 type baz
1669 echo ---
1670 cd .. & rd /s/q foobar
1671
1672 echo ------------ Testing ftype ------------
1673 rem FIXME Can't test error messages in the current test system, so we have to use some kludges
1674 rem FIXME Revise once || conditional execution is fixed
1675 mkdir foobar & cd foobar
1676 echo --- setting association
1677 ftype footype> baz
1678 type baz
1679 echo ---
1680
1681 ftype footype=foo_opencmd
1682 assoc .foo=footype
1683 ftype footype
1684
1685 rem association set system-wide
1686 echo @echo off> tmp.cmd
1687 echo echo +++>> tmp.cmd
1688 echo ftype footype>> tmp.cmd
1689 cmd /c tmp.cmd
1690
1691 echo --- resetting association
1692 assoc .foo=
1693
1694 rem Removing a file type association doesn't work on XP due to a bug, so a workaround is needed
1695 setlocal EnableDelayedExpansion
1696 set FOO=original value
1697 ftype footype=
1698 ftype footype > baz
1699 for /F %%i in ('type baz') do (set FOO=buggyXP)
1700 rem Resetting actually works on wine/NT4, but is reported as failing due to the peculiar test (and non-support for EnabledDelayedExpansion)
1701 rem FIXME Revisit once a grep-like program like ftype is implemented
1702 rem (e.g. to check baz's size using dir /b instead)
1703 echo !FOO!
1704
1705 rem cleanup registry
1706 echo REGEDIT4> regCleanup.reg
1707 echo.>> regCleanup.reg
1708 echo [-HKEY_CLASSES_ROOT\footype]>> regCleanup.reg
1709 regedit /s regCleanup.reg
1710 set FOO=
1711 endlocal
1712 cd .. & rd /s/q foobar
1713
1714 echo ------------ Testing CALL ------------
1715 mkdir foobar & cd foobar
1716 echo --- external script
1717 echo echo foo %%1> foo.cmd
1718 call foo
1719 call foo.cmd 8
1720 echo echo %%1 %%2 > foo.cmd
1721 call foo.cmd foo
1722 call foo.cmd foo bar
1723 call foo.cmd foo ""
1724 call foo.cmd "" bar
1725 call foo.cmd foo ''
1726 call foo.cmd '' bar
1727 del foo.cmd
1728
1729 echo --- internal routines
1730 call :testRoutine :testRoutine
1731 goto :endTestRoutine
1732 :testRoutine
1733 echo bar %1
1734 goto :eof
1735 :endTestRoutine
1736
1737 call :testRoutineArgs foo
1738 call :testRoutineArgs foo bar
1739 call :testRoutineArgs foo ""
1740 call :testRoutineArgs ""  bar
1741 call :testRoutineArgs foo ''
1742 call :testRoutineArgs ''  bar
1743 goto :endTestRoutineArgs
1744 :testRoutineArgs
1745 echo %1 %2
1746 goto :eof
1747 :endTestRoutineArgs
1748
1749 echo --- with builtins
1750 call mkdir foo
1751 echo %ErrorLevel%
1752 if exist foo (echo foo created) else echo foo should exist!
1753 rmdir foo
1754 set FOOBAZ_VAR=foobaz
1755 call echo Should expand %FOOBAZ_VAR%
1756 set FOOBAZ_VAR=
1757 echo>batfile
1758 call dir /b
1759 echo>robinfile
1760 if 1==1 call del batfile
1761 dir /b
1762 if exist batfile echo batfile shouldn't exist
1763 rem ... but not for 'if' or 'for'
1764 call if 1==1 echo bar 2> nul
1765 echo %ErrorLevel%
1766 call :setError 0
1767 call for %%i in (foo bar baz) do echo %%i 2> nul
1768 echo %ErrorLevel%
1769 rem First look for programs in the path before trying a builtin
1770 echo echo non-builtin dir> dir.cmd
1771 call dir /b
1772 del dir.cmd
1773 rem The below line equates to call (, which does nothing, then the
1774 rem subsequent lines are executed.
1775 call (
1776   echo Line one
1777   echo Line two
1778 )
1779 rem The below line equates to call if, which always fails, then the
1780 rem subsequent lines are executed. Note cmd.exe swallows all lines
1781 rem starting with )
1782 call if 1==1 (
1783   echo Get if
1784 ) else (
1785   echo ... and else!
1786 )
1787 call call call echo passed
1788 cd .. & rd /s/q foobar
1789
1790 echo ------------ Testing SHIFT ------------
1791
1792 call :shiftFun p1 p2 p3 p4 p5
1793 goto :endShiftFun
1794
1795 :shiftFun
1796 echo '%1' '%2' '%3' '%4' '%5'
1797 shift
1798 echo '%1' '%2' '%3' '%4' '%5'
1799 shift@tab@ /1
1800 echo '%1' '%2' '%3' '%4' '%5'
1801 shift /2
1802 echo '%1' '%2' '%3' '%4' '%5'
1803 shift /-1
1804 echo '%1' '%2' '%3' '%4' '%5'
1805 shift /0
1806 echo '%1' '%2' '%3' '%4' '%5'
1807 goto :eof
1808 :endShiftFun
1809
1810 echo ------------ Testing cmd invocation ------------
1811 rem FIXME: only a stub ATM
1812 echo --- a batch file can delete itself
1813 echo del foo.cmd>foo.cmd
1814 cmd /q /c foo.cmd
1815 if not exist foo.cmd (
1816     echo file correctly deleted
1817 ) else (
1818     echo file should be deleted!
1819     del foo.cmd
1820 )
1821 echo --- a batch file can alter itself
1822 echo echo bar^>foo.cmd>foo.cmd
1823 cmd /q /c foo.cmd > NUL 2>&1
1824 if exist foo.cmd (
1825     type foo.cmd
1826     del foo.cmd
1827 ) else (
1828     echo file not created!
1829 )
1830
1831 echo ---------- Testing copy
1832 md foobar2
1833 cd foobar2
1834 rem Note echo adds 0x0d 0x0a on the end of the line in the file
1835 echo AAA> file1
1836 echo BBBBBB> file2
1837 echo CCCCCCCCC> file3
1838 md dir1
1839 goto :testcopy
1840
1841 :CheckExist
1842 if exist "%1" (
1843   echo Passed: Found expected %1
1844 ) else (
1845   echo Failed: Did not find expected %1
1846 )
1847 del /q "%1" >nul 2>&1
1848 shift
1849 if not "%1"=="" goto :CheckExist
1850 goto :eof
1851
1852 :CheckNotExist
1853 if not exist "%1" (
1854   echo Passed: Did not find %1
1855 ) else (
1856   echo Failed: Unexpectedly found %1
1857   del /q "%1" >nul 2>&1
1858 )
1859 shift
1860 if not "%1"=="" goto :CheckNotExist
1861 goto :eof
1862
1863 rem Note: No way to check file size on NT4 so skip the test
1864 :CheckFileSize
1865 if not exist "%1" (
1866   echo Failed: File missing when requested filesize check [%2]
1867   goto :ContinueFileSizeChecks
1868 )
1869 for %%i in (%1) do set filesize=%%~zi
1870 if "%filesize%"=="%2" (
1871     echo Passed: file size check on %1 [%filesize%]
1872 ) else (
1873   if "%filesize%"=="%%~zi" (
1874     echo Skipping file size check on NT4
1875   ) else (
1876     echo Failed: file size check on %1 [%filesize% != %2]
1877   )
1878 )
1879 :ContinueFileSizeChecks
1880 shift
1881 shift
1882 if not "%1"=="" goto :CheckFileSize
1883 goto :eof
1884
1885 :testcopy
1886
1887 rem -----------------------
1888 rem Simple single file copy
1889 rem -----------------------
1890 rem Simple single file copy, normally used syntax
1891 copy file1 dummy.file >nul 2>&1
1892 if errorlevel 1 echo Incorrect errorlevel
1893 call :CheckExist dummy.file
1894
1895 rem Simple single file copy, destination supplied as two forms of directory
1896 copy file1 dir1 >nul 2>&1
1897 if errorlevel 1 echo Incorrect errorlevel
1898 call :CheckExist dir1\file1
1899
1900 copy file1 dir1\ >nul 2>&1
1901 if errorlevel 1 echo Incorrect errorlevel
1902 call :CheckExist dir1\file1
1903
1904 rem Simple single file copy, destination supplied as fully qualified destination
1905 copy file1 dir1\file99 >nul 2>&1
1906 if errorlevel 1 echo Incorrect errorlevel
1907 call :CheckExist dir1\file99
1908
1909 rem Simple single file copy, destination not supplied
1910 cd dir1
1911 copy ..\file1 >nul 2>&1
1912 if errorlevel 1 echo Incorrect errorlevel
1913 call :CheckExist file1
1914 cd ..
1915
1916 rem Simple single file copy, destination supplied as nonexistent directory
1917 copy file1 dir2\ >nul 2>&1
1918 if not errorlevel 1 echo Incorrect errorlevel
1919 call :CheckNotExist dir2 dir2\file1
1920
1921 rem -----------------------
1922 rem Wildcarded copy
1923 rem -----------------------
1924 rem Simple single file copy, destination supplied as two forms of directory
1925 copy file? dir1 >nul 2>&1
1926 if errorlevel 1 echo Incorrect errorlevel
1927 call :CheckExist dir1\file1 dir1\file2 dir1\file3
1928
1929 copy file* dir1\ >nul 2>&1
1930 if errorlevel 1 echo Incorrect errorlevel
1931 call :CheckExist dir1\file1 dir1\file2 dir1\file3
1932
1933 rem Simple single file copy, destination not supplied
1934 cd dir1
1935 copy ..\file*.* >nul 2>&1
1936 if errorlevel 1 echo Incorrect errorlevel
1937 call :CheckExist file1 file2 file3
1938 cd ..
1939
1940 rem Simple wildcarded file copy, destination supplied as nonexistent directory
1941 copy file? dir2\ >nul 2>&1
1942 if not errorlevel 1 echo Incorrect errorlevel
1943 call :CheckNotExist dir2 dir2\file1 dir2\file2 dir2\file3
1944
1945 rem ------------------------------------------------
1946 rem Confirm overwrite works (cannot test prompting!)
1947 rem ------------------------------------------------
1948 copy file1 testfile >nul 2>&1
1949 copy /y file2 testfile >nul 2>&1
1950 call :CheckExist testfile
1951
1952 rem ------------------------------------------------
1953 rem Test concatenation
1954 rem ------------------------------------------------
1955 rem simple case, no wildcards
1956 copy file1+file2 testfile >nul 2>&1
1957 if errorlevel 1 echo Incorrect errorlevel
1958 call :CheckExist testfile
1959
1960 rem simple case, wildcards, no concatenation
1961 copy file* testfile >nul 2>&1
1962 if errorlevel 1 echo Incorrect errorlevel
1963 call :CheckExist testfile
1964
1965 rem simple case, wildcards, and concatenation
1966 echo ddddd > fred
1967 copy file*+fred testfile >nul 2>&1
1968 if errorlevel 1 echo Incorrect errorlevel
1969 call :CheckExist testfile
1970
1971 rem simple case, wildcards, and concatenation
1972 copy fred+file* testfile >nul 2>&1
1973 if errorlevel 1 echo Incorrect errorlevel
1974 call :CheckExist testfile
1975
1976 rem Calculate destination name
1977 copy fred+file* dir1 >nul 2>&1
1978 if errorlevel 1 echo Incorrect errorlevel
1979 call :CheckExist dir1\fred
1980
1981 rem Calculate destination name
1982 copy fred+file* dir1\ >nul 2>&1
1983 if errorlevel 1 echo Incorrect errorlevel
1984 call :CheckExist dir1\fred
1985
1986 rem Calculate destination name (none supplied)
1987 cd dir1
1988 copy ..\fred+..\file* >nul 2>&1
1989 if errorlevel 1 echo Incorrect errorlevel
1990 call :CheckExist fred
1991
1992 copy ..\fr*+..\file1  >nul 2>&1
1993 if errorlevel 1 echo Incorrect errorlevel
1994 call :CheckExist fred
1995 cd ..
1996
1997 rem ******************************************************************
1998 rem ASCII and BINARY tests
1999 rem Note: hard coded numbers deliberate because need to ensure whether
2000 rem an additional EOF has been added or not. There is no way to handle
2001 rem EOFs in batch, so assume if a single byte appears, its an EOF!
2002 rem ******************************************************************
2003
2004 rem Confirm original sizes of file1,2,3
2005 call :CheckFileSize file1 5 file2 8 file3 11
2006
2007 cd dir1
2008
2009 rem ----------------------------------------------
2010 rem Show concatenation defaults copy to ascii mode
2011 rem ----------------------------------------------
2012 rem Simple default copy source to destination (should not append EOF 5)
2013 copy ..\file1 file1_default >nul 2>&1
2014 call :CheckFileSize file1_default 5
2015
2016 rem Simple binary copy source to destination (should not append EOF 5)
2017 copy /b ..\file1 file1_default2 >nul 2>&1
2018 call :CheckFileSize file1_default2 5
2019
2020 rem Simple ascii copy source to destination (should append EOF 5+1, 8+1, 11+1)
2021 copy /a ..\file1 file1_plus_eof >nul 2>&1
2022 call :CheckFileSize file1_plus_eof 6
2023 copy /a ..\file2 file2_plus_eof >nul 2>&1
2024 call :CheckFileSize file2_plus_eof 9
2025 copy /a ..\file3 file3_plus_eof >nul 2>&1
2026 call :CheckFileSize file3_plus_eof 12
2027
2028 rem Concat 2 files, ascii mode - (only one EOF on the end 5+8+1)
2029 copy /a ..\file1+..\file2 file12_plus_eof >nul 2>&1
2030 call :CheckFileSize file12_plus_eof 14
2031
2032 rem Concat 2 files, binary mode - (no EOF on the end 5+8)
2033 copy /b ..\file1+..\file2 file12_no_eof >nul 2>&1
2034 call :CheckFileSize file12_no_eof 13
2035
2036 rem Concat 2 files, default mode - (one EOF on the end 5+8+1)
2037 copy ..\file1+..\file2 file12_eof2 >nul 2>&1
2038 call :CheckFileSize file12_eof2 14
2039
2040 rem --------------------------------------------------------------
2041 rem Show ascii source copy stops at first EOF, binary does the lot
2042 rem --------------------------------------------------------------
2043 copy file1_plus_eof /b file1_binary_srccopy /b >nul 2>&1
2044 call :CheckFileSize file1_binary_srccopy 6
2045
2046 copy file1_plus_eof /a file1_ascii_srccopy /b >nul 2>&1
2047 call :CheckFileSize file1_ascii_srccopy 5
2048
2049 rem --------------------------------------------------------------
2050 rem Show results of concatenating files (ending in EOFs) and /a /b
2051 rem --------------------------------------------------------------
2052
2053 rem Default and ascii copy reads as ascii, stripping EOFs, so 6-1 + 9-1 + 12-1 + 1
2054 copy file1_plus_eof+file2_plus_eof+file3_plus_eof file123_default_copy >nul 2>&1
2055 call :CheckFileSize file123_default_copy 25
2056 copy /a file1_plus_eof+file2_plus_eof+file3_plus_eof file123_ascii_copy >nul 2>&1
2057 call :CheckFileSize file123_ascii_copy 25
2058
2059 rem In binary mode, we get 3 eofs, so 6 + 9 + 12 = 27
2060 copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_binary_copy >nul 2>&1
2061 call :CheckFileSize file123_binary_copy 27
2062
2063 rem We can select which we want the eofs from by postfixing it with /a or /b
2064 rem so here have first and third with eof, second as ascii 6 + 9-1 + 12
2065 copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy1 >nul 2>&1
2066 call :CheckFileSize file123_mixed_copy1 26
2067
2068 rem By postfixing the destination with /a, we ask for an ascii destination which appends EOF
2069 rem so here have first and third with eof, second as ascii 6 + 9-1 + 12 + extra EOF
2070 rem Note the delta between this and the previous one also shows that the destination
2071 rem ascii/binary is inherited from the last /a or /b on the line
2072 copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy2 /a >nul 2>&1
2073 call :CheckFileSize file123_mixed_copy2 27
2074
2075 rem so here have second with eof, first and third as ascii 6-1 + 9 + 12-1
2076 rem Note the delta between the next two also shows that the destination ascii/binary is
2077 rem inherited from the last /a or /b on the line, so the first has an extra EOF
2078 copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy3 >nul 2>&1
2079 call :CheckFileSize file123_mixed_copy3 26
2080 copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy4 /b >nul 2>&1
2081 call :CheckFileSize file123_mixed_copy4 25
2082
2083 rem -------------------------------------------------------------------------------------------
2084 rem This shows when concatenating, an ascii destination always adds on an EOF but when we
2085 rem are not concatenating, its a direct copy regardless of destination if being read as binary
2086 rem -------------------------------------------------------------------------------------------
2087
2088 rem All 3 have eof's, plus an extra = 6 + 9 + 12 + eof
2089 copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_mixed_copy5 /a >nul 2>&1
2090 call :CheckFileSize file123_mixed_copy5 28
2091
2092 rem All 2 have eof's, plus an extra = 6 + 12 + eof
2093 copy /b file1_plus_eof + file3_plus_eof file123_mixed_copy6 /a >nul 2>&1
2094 call :CheckFileSize file123_mixed_copy6 19
2095
2096 rem One file has EOF, but doesn't get an extra one, i.e. 6
2097 copy /b file1_plus_eof file123_mixed_copy7 /a >nul 2>&1
2098 call :CheckFileSize file123_mixed_copy7 6
2099
2100 rem Syntax means concatenate so ascii destination kicks in
2101 copy /b file1_plus_eof* file123_mixed_copy8 /a >nul 2>&1
2102 call :CheckFileSize file123_mixed_copy8 7
2103
2104 del *.* /q
2105 cd ..
2106
2107 rem ---------------------------------------
2108 rem Error combinations
2109 rem ---------------------------------------
2110 rem Specify source directory but name is a file
2111 call :setError 0
2112 copy file1\ dir1\ >NUL 2>&1
2113 if errorlevel 1 echo Passed: errorlevel invalid check 1
2114 if not errorlevel 1 echo Failed: errorlevel invalid check 1
2115 call :CheckNotExist dir1\file1
2116
2117 rem Overwrite same file
2118 call :setError 0
2119 copy file1 file1 >NUL 2>&1
2120 if errorlevel 1 echo Passed: errorlevel invalid check 2
2121 if not errorlevel 1 echo Failed: errorlevel invalid check 2
2122
2123 rem Supply same file identified as a directory
2124 call :setError 0
2125 copy file1 file1\ >NUL 2>&1
2126 if errorlevel 1 echo Passed: errorlevel invalid check 3
2127 if not errorlevel 1 echo Failed: errorlevel invalid check 3
2128
2129 cd ..
2130 rd foobar2 /s /q
2131
2132 echo ------------ Testing setlocal/endlocal ------------
2133 call :setError 0
2134 rem Note: setlocal EnableDelayedExpansion already tested in the variable delayed expansion test section
2135 mkdir foobar & cd foobar
2136 echo --- enable/disable extensions
2137 setlocal DisableEXTensions
2138 echo ErrLev: %ErrorLevel%
2139 endlocal
2140 echo ErrLev: %ErrorLevel%
2141 echo @echo off> tmp.cmd
2142 echo echo ErrLev: %%ErrorLevel%%>> tmp.cmd
2143 rem Enabled by default
2144 cmd /C tmp.cmd
2145 cmd /E:OfF /C tmp.cmd
2146 cmd /e:oN /C tmp.cmd
2147
2148 rem FIXME: creating file before setting envvar value to prevent parsing-time evaluation (due to EnableDelayedExpansion not being implemented/available yet)
2149 echo --- setlocal with corresponding endlocal
2150 rem %CD% does not tork on NT4 so use the following workaround
2151 for /d %%i in (.) do set CURDIR=%%~dpnxi
2152 echo @echo off> test.cmd
2153 echo echo %%VAR%%>> test.cmd
2154 echo setlocal>> test.cmd
2155 echo set VAR=localval>> test.cmd
2156 echo md foobar2>> test.cmd
2157 echo cd foobar2>> test.cmd
2158 echo echo %%VAR%%>> test.cmd
2159 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2160 echo endlocal>> test.cmd
2161 echo echo %%VAR%%>> test.cmd
2162 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2163 set VAR=globalval
2164 call test.cmd
2165 echo %VAR%
2166 for /d %%i in (.) do echo %%~dpnxi
2167 cd /d %curdir%
2168 rd foobar2
2169 set VAR=
2170 echo --- setlocal with no corresponding endlocal
2171 echo @echo off> test.cmd
2172 echo echo %%VAR%%>> test.cmd
2173 echo setlocal>> test.cmd
2174 echo set VAR=localval>> test.cmd
2175 echo md foobar2>> test.cmd
2176 echo cd foobar2>> test.cmd
2177 echo echo %%VAR%%>> test.cmd
2178 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2179 set VAR=globalval
2180 rem %CD% does not tork on NT4 so use the following workaround
2181 for /d %%i in (.) do set CURDIR=%%~dpnxi
2182 call test.cmd
2183 echo %VAR%
2184 for /d %%i in (.) do echo %%~dpnxi
2185 cd /d %curdir%
2186 rd foobar2
2187 set VAR=
2188 echo --- setlocal within same batch program
2189 set var1=one
2190 set var2=
2191 set var3=
2192 rem %CD% does not tork on NT4 so use the following workaround
2193 for /d %%i in (.) do set CURDIR=%%~dpnxi
2194 setlocal
2195 set var2=two
2196 mkdir foobar2
2197 cd foobar2
2198 setlocal
2199 set var3=three
2200 if "%var1%"=="one" echo Var1 ok 1
2201 if "%var2%"=="two" echo Var2 ok 2
2202 if "%var3%"=="three" echo Var3 ok 3
2203 for /d %%i in (.) do set curdir2=%%~dpnxi
2204 if "%curdir2%"=="%curdir%\foobar2" echo Directory is ok 1
2205 endlocal
2206 if "%var1%"=="one" echo Var1 ok 1
2207 if "%var2%"=="two" echo Var2 ok 2
2208 if "%var3%"=="" echo Var3 ok 3
2209 for /d %%i in (.) do set curdir2=%%~dpnxi
2210 if "%curdir2%"=="%curdir%\foobar2" echo Directory is ok 2
2211 endlocal
2212 if "%var1%"=="one" echo Var1 ok 1
2213 if "%var2%"=="" echo Var2 ok 2
2214 if "%var3%"=="" echo Var3 ok 3
2215 for /d %%i in (.) do set curdir2=%%~dpnxi
2216 if "%curdir2%"=="%curdir%" echo Directory is ok 3
2217 rd foobar2 /s /q
2218 set var1=
2219
2220 echo --- Mismatched set and end locals
2221 mkdir foodir2 2>nul
2222 mkdir foodir3 2>nul
2223 mkdir foodir4 2>nul
2224 rem %CD% does not tork on NT4 so use the following workaround
2225 for /d %%i in (.) do set curdir=%%~dpnxi
2226
2227 echo @echo off> 2set1end.cmd
2228 echo echo %%VAR%%>> 2set1end.cmd
2229 echo setlocal>> 2set1end.cmd
2230 echo set VAR=2set1endvalue1>> 2set1end.cmd
2231 echo cd ..\foodir3>> 2set1end.cmd
2232 echo setlocal>> 2set1end.cmd
2233 echo set VAR=2set1endvalue2>> 2set1end.cmd
2234 echo cd ..\foodir4>> 2set1end.cmd
2235 echo endlocal>> 2set1end.cmd
2236 echo echo %%VAR%%>> 2set1end.cmd
2237 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 2set1end.cmd
2238
2239 echo @echo off> 1set2end.cmd
2240 echo echo %%VAR%%>> 1set2end.cmd
2241 echo setlocal>> 1set2end.cmd
2242 echo set VAR=1set2endvalue1>> 1set2end.cmd
2243 echo cd ..\foodir3>> 1set2end.cmd
2244 echo endlocal>> 1set2end.cmd
2245 echo echo %%VAR%%>> 1set2end.cmd
2246 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
2247 echo endlocal>> 1set2end.cmd
2248 echo echo %%VAR%%>> 1set2end.cmd
2249 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
2250
2251 echo --- Extra setlocal in called batch
2252 set VAR=value1
2253 rem -- setlocal1 == this batch, should never be used inside a called routine
2254 setlocal
2255 set var=value2
2256 cd foodir2
2257 call %curdir%\2set1end.cmd
2258 echo Finished:
2259 echo %VAR%
2260 for /d %%i in (.) do echo %%~dpnxi
2261 endlocal
2262 echo %VAR%
2263 for /d %%i in (.) do echo %%~dpnxi
2264 cd /d %curdir%
2265
2266 echo --- Extra endlocal in called batch
2267 set VAR=value1
2268 rem -- setlocal1 == this batch, should never be used inside a called routine
2269 setlocal
2270 set var=value2
2271 cd foodir2
2272 call %curdir%\1set2end.cmd
2273 echo Finished:
2274 echo %VAR%
2275 for /d %%i in (.) do echo %%~dpnxi
2276 endlocal
2277 echo %VAR%
2278 for /d %%i in (.) do echo %%~dpnxi
2279 cd /d %curdir%
2280
2281 echo --- endlocal in called function rather than batch pgm is ineffective
2282 @echo off
2283 set var=1
2284 set var2=1
2285 setlocal
2286 set var=2
2287 call :endlocalroutine
2288 echo %var%
2289 endlocal
2290 echo %var%
2291 goto :endlocalfinished
2292 :endlocalroutine
2293 echo %var%
2294 endlocal
2295 echo %var%
2296 setlocal
2297 set var2=2
2298 endlocal
2299 echo %var2%
2300 endlocal
2301 echo %var%
2302 echo %var2%
2303 goto :eof
2304 :endlocalfinished
2305 echo %var%
2306
2307 set var=
2308 set var2=
2309 cd .. & rd /q/s foobar
2310
2311 echo ------------ Testing Errorlevel ------------
2312 rem WARNING: Do *not* add tests using ErrorLevel after this section
2313 should_not_exist 2> nul > nul
2314 echo %ErrorLevel%
2315 rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak
2316 rem See http://www.robvanderwoude.com/exit.php
2317 call :setError 1
2318 echo %ErrorLevel%
2319 if errorlevel 2 echo errorlevel too high, bad
2320 if errorlevel 1 echo errorlevel just right, good
2321 if errorlevel 01 echo errorlevel with leading zero just right, good
2322 if errorlevel -1 echo errorlevel with negative number OK
2323 if errorlevel 0x1 echo hexa should not be recognized!
2324 if errorlevel 1a echo invalid error level recognized!
2325 call :setError 0
2326 echo abc%ErrorLevel%def
2327 if errorlevel 1 echo errorlevel nonzero, bad
2328 if not errorlevel 1 echo errorlevel zero, good
2329 if not errorlevel 0x1 echo hexa should not be recognized!
2330 if not errorlevel 1a echo invalid error level recognized!
2331 rem Now verify that setting a real variable hides its magic variable
2332 set errorlevel=7
2333 echo %ErrorLevel% should be 7
2334 if errorlevel 7 echo setting var worked too well, bad
2335 call :setError 3
2336 echo %ErrorLevel% should still be 7
2337
2338 echo ------------ Testing GOTO ------------
2339 if a==a goto dest1
2340 :dest1
2341 echo goto with no leading space worked
2342 if b==b goto dest2
2343  :dest2
2344 echo goto with a leading space worked
2345 if c==c goto dest3
2346         :dest3
2347 echo goto with a leading tab worked
2348 if d==d goto dest4
2349 :dest4@space@
2350 echo goto with a following space worked
2351
2352 echo ------------ Testing PATH ------------
2353 set backup_path=%path%
2354 set path=original
2355 path
2356 path try2
2357 path
2358 path=try3
2359 path
2360 set path=%backup_path%
2361 set backup_path=
2362
2363 echo ------------ Testing combined CALLs/GOTOs ------------
2364 echo @echo off>foo.cmd
2365 echo goto :eof>>foot.cmd
2366 echo :eof>>foot.cmd
2367 echo echo world>>foo.cmd
2368
2369 echo @echo off>foot.cmd
2370 echo echo cheball>>foot.cmd
2371 echo.>>foot.cmd
2372 echo call :bar>>foot.cmd
2373 echo if "%%1"=="deleteMe" (del foot.cmd)>>foot.cmd
2374 echo goto :eof>>foot.cmd
2375 echo.>>foot.cmd
2376 echo :bar>>foot.cmd
2377 echo echo barbare>>foot.cmd
2378 echo goto :eof>>foot.cmd
2379
2380 call foo.cmd
2381 call foot
2382 call :bar
2383 del foo.cmd
2384 rem Script execution stops after the following line
2385 foot deleteMe
2386 call :foo
2387 call :foot
2388 goto :endFuns
2389
2390 :foot
2391 echo foot
2392
2393 :foo
2394 echo foo
2395 goto :eof
2396
2397 :endFuns
2398
2399 :bar
2400 echo bar
2401 call :foo
2402
2403 :baz
2404 echo baz
2405 goto :eof
2406
2407 echo Final message is not output since earlier 'foot' processing stops script execution
2408 echo Do NOT add any tests below this line
2409
2410 echo ------------ Done, jumping to EOF -----------
2411 goto :eof
2412 rem Subroutine to set errorlevel and return
2413 rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported
2414 :setError
2415 exit /B %1
2416 rem This line runs under cmd in windows NT 4, but not in more modern versions.