echo Tests for cmd's builtin commands @echo on echo ------------ Testing 'echo' [ON] -------------- echo word echo 'singlequotedword' echo "doublequotedword" @echo at-echoed-word echo "/?" echo. echo . echo.word echo .word echo word@space@ echo word@space@@space@ @echo off echo ------------ Testing 'echo' [OFF] -------------- echo word echo 'singlequotedword' echo "doublequotedword" @echo at-echoed-word echo "/?" echo. echo . echo.word echo .word echo word@space@ echo word@space@@space@ echo ------------ Testing 'set' -------------- echo %ErrorLevel% set FOOBAR 2> nul > nul echo %ErrorLevel% set FOOBAR = baz echo %ErrorLevel% echo %FOOBAR%FOOBAR not defined echo %FOOBAR % set FOOBAR 2> nul set FOOBAR = baz2 echo %ErrorLevel% echo %fOObAr % set FOOBAR= bar echo %ErrorLevel% echo %FOOBAR% set FOO set FOOBAR= set FOOB echo %FOOBAR%FOOBAR not defined set FOOBAR = set FOOBA 2> nul > nul echo %ErrorLevel% set FOO=bar echo %FOO% set FOO=foo set BAR=bar echo %FOO%%BAR% set BAR= set FOO= set FOO=%FOO% echo %FOO%FOO not defined set BAZ%=bazbaz set BA echo %BAZ%% set BAZ%= echo set "FOO=bar" should not include the quotes in the variable value set "FOO=bar" echo %FOO% set FOO= echo ------------ Testing variable expansion -------------- call :setError 0 echo ~dp0 should be directory containing batch file echo %~dp0 mkdir dummydir cd dummydir echo %~dp0 cd .. rmdir dummydir echo CD value %CD% echo %% echo P% echo %P echo %UNKNOWN%S echo P%UNKNOWN% echo P%UNKNOWN%S echo %ERRORLEVEL echo %ERRORLEVEL% echo %ERRORLEVEL%%ERRORLEVEL% echo %ERRORLEVEL%ERRORLEVEL% echo %ERRORLEVEL%% echo %ERRORLEVEL%%% echo P%ERRORLEVEL% echo %ERRORLEVEL%S echo P%ERRORLEVEL%S echo ------------ Testing type ------------ echo bar> foobaz @echo on type foobaz echo *** @echo off type foobaz echo *** del foobaz echo ------------ Testing NUL ------------ md foobar && cd foobar rem NUL file (non) creation + case insensitivity rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround echo > bar echo foo > NUL dir /b /a-d echo foo > nul dir /b /a-d echo foo > NuL dir /b /a-d del bar rem NUL not special everywhere call :setError 123 echo NUL> foo if not exist foo (echo foo should have been created) else ( type foo del foo ) rem Empty file creation copy nul foo > nul if exist foo ( echo foo created del foo type foo ) else ( echo *** ) cd .. rd foobar echo ------------ Testing if/else -------------- echo if/else should work with blocks if 0 == 0 ( echo if seems to work ) else ( echo if seems to be broken ) if 1 == 0 ( echo else seems to be broken ) else ( echo else seems to work ) if /c==/c ( echo if seems not to detect /c as parameter ) else ( echo parameter detection seems to be broken ) echo Testing case sensitivity with and without /i option if bar==BAR echo if does not default to case sensitivity if not bar==BAR echo if seems to default to case sensitivity if /i foo==FOO echo if /i seems to work if /i not foo==FOO echo if /i seems to be broken if /I foo==FOO echo if /I seems to work if /I not foo==FOO echo if /I seems to be broken echo -----------Testing for ----------- for %%i in (A B C) do echo %%i for %%i in (A B C) do call :forTestFun1 %%i goto :endForTestFun1 :forTestFun1 echo %1 goto :eof :endForTestFun1 for %%i in (X) do ( for %%j in (Y) do ( echo %%i %%j )) for %%i in (A B) do ( for %%j in (C D) do ( echo %%i %%j )) for %%i in (A B) do ( for %%j in (C D) do ( call :forTestFun2 %%i %%j )) goto :endForTestFun2 :forTestFun2 echo %1 %2 goto :eof :endForTestFun2 echo -----------Testing del /a----------- del /f/q *.test > nul echo r > r.test attrib +r r.test echo not-r > not-r.test if not exist not-r.test echo not-r.test not found before delete, bad del /a:-r *.test if not exist not-r.test echo not-r.test not found after delete, good if not exist r.test echo r.test not found before delete, bad if exist r.test echo r.test found before delete, good del /a:r *.test if not exist r.test echo r.test not found after delete, good if exist r.test echo r.test found after delete, bad echo ------------ Testing del /q -------------- mkdir del_q_dir cd del_q_dir echo abc > file1 echo abc > file2.dat rem If /q doesn't work, cmd will prompt and the test case should hang del /q * > nul for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a cd .. rmdir del_q_dir echo ------------ Testing del /s -------------- mkdir "foo bar" cd "foo bar" echo hi > file1.dat echo there > file2.dat echo bub > file3.dat echo bye > "file with spaces.dat" cd .. del /s file1.dat > nul del file2.dat /s > nul del "file3.dat" /s > nul del "file with spaces.dat" /s > nul cd "foo bar" for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat" if exist "file with spaces.dat" del "file with spaces.dat" cd .. rmdir "foo bar" echo ----------- Testing mkdir ----------- call :setError 0 rem md and mkdir are synonymous mkdir foobar echo %ErrorLevel% rmdir foobar md foobar echo %ErrorLevel% rmdir foobar rem Creating an already existing directory/file must fail mkdir foobar md foobar echo %ErrorLevel% rmdir foobar echo > foobar mkdir foobar echo %ErrorLevel% del foobar rem Multi-level path creation mkdir foo echo %ErrorLevel% mkdir foo\bar\baz echo %ErrorLevel% cd foo echo %ErrorLevel% cd bar echo %ErrorLevel% cd baz echo %ErrorLevel% echo > ..\..\bar2 mkdir ..\..\..\foo\bar2 echo %ErrorLevel% del ..\..\bar2 mkdir ..\..\..\foo\bar2 echo %ErrorLevel% rmdir ..\..\..\foo\bar2 cd .. rmdir baz cd .. rmdir bar cd .. rmdir foo echo %ErrorLevel% rem Trailing backslashes mkdir foo\\\\ echo %ErrorLevel% if exist foo (rmdir foo && echo dir created ) else ( echo dir not created ) echo %ErrorLevel% rem Invalid chars mkdir ? echo %ErrorLevel% call :setError 0 mkdir ?\foo echo %ErrorLevel% call :setError 0 mkdir foo\? echo %ErrorLevel% if exist foo (rmdir foo && echo ok, foo created ) else ( echo foo not created ) call :setError 0 mkdir foo\bar\? echo %ErrorLevel% call :setError 0 if not exist foo ( echo bad, foo not created ) else ( cd foo if exist bar ( echo ok, foo\bar created rmdir bar ) cd .. rmdir foo ) echo ----------- Testing rmdir ----------- call :setError 0 rem rd and rmdir are synonymous mkdir foobar rmdir foobar echo %ErrorLevel% if not exist foobar echo dir removed mkdir foobar rd foobar echo %ErrorLevel% if not exist foobar echo dir removed rem Removing non-existent directory rmdir foobar echo %ErrorLevel% rem Removing single-level directories echo > foo rmdir foo echo %ErrorLevel% if exist foo echo file not removed del foo mkdir foo echo > foo\bar rmdir foo echo %ErrorLevel% if exist foo echo non-empty dir not removed del foo\bar mkdir foo\bar rmdir foo echo %ErrorLevel% if exist foo echo non-empty dir not removed rmdir foo\bar rmdir foo rem Recursive rmdir mkdir foo\bar\baz rmdir /s /Q foo if not exist foo ( echo recursive rmdir succeeded ) else ( rd foo\bar\baz rd foo\bar rd foo ) mkdir foo\bar\baz echo foo > foo\bar\brol rmdir /s /Q foo if not exist foo ( echo recursive rmdir succeeded ) else ( rd foo\bar\baz del foo\bar\brol rd foo\bar rd foo ) echo ------------ Testing CALL -------------- mkdir foobar & cd foobar rem External script echo echo foo %%1 > foo.cmd call foo call foo.cmd 8 del foo.cmd rem Internal routines call :testRoutine :testRoutine goto :endTestRoutine :testRoutine echo bar %1 goto :eof :endTestRoutine rem Should work for builtins... call mkdir foo echo %ErrorLevel% if exist foo (echo foo created) else echo foo should exist! rmdir foo set FOOBAZ_VAR=foobaz call echo Should expand %FOOBAZ_VAR% set FOOBAZ_VAR= echo>batfile call dir /b echo>robinfile if 1==1 call del batfile dir /b if exist batfile echo batfile shouldn't exist rem ... but not for 'if' or 'for' call if 1==1 echo bar 2> nul echo %ErrorLevel% call :setError 0 call for %%i in (foo bar baz) do echo %%i 2> nul echo %ErrorLevel% rem First look for programs in the path before trying a builtin echo echo non-builtin dir > dir.cmd call dir /b cd .. rd /s/q foobar echo -----------Testing Errorlevel----------- rem WARNING: Do *not* add tests using ErrorLevel after this section should_not_exist 2> nul > nul echo %ErrorLevel% rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak rem See http://www.robvanderwoude.com/exit.php call :setError 1 echo %ErrorLevel% if errorlevel 2 echo errorlevel too high, bad if errorlevel 1 echo errorlevel just right, good call :setError 0 echo abc%ErrorLevel%def if errorlevel 1 echo errorlevel nonzero, bad if not errorlevel 1 echo errorlevel zero, good rem Now verify that setting a real variable hides its magic variable set errorlevel=7 echo %ErrorLevel% should be 7 if errorlevel 7 echo setting var worked too well, bad call :setError 3 echo %ErrorLevel% should still be 7 echo -----------Testing GOTO----------- if a==a goto dest1 :dest1 echo goto with no leading space worked if b==b goto dest2 :dest2 echo goto with a leading space worked if c==c goto dest3 :dest3 echo goto with a leading tab worked if d==d goto dest4 :dest4@space@ echo goto with a following space worked echo -----------Done, jumping to EOF----------- goto :eof rem Subroutine to set errorlevel and return rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported :setError exit /B %1 rem This line runs under cmd in windows NT 4, but not in more modern versions.