1 /* 2 * PROJECT: ReactOS API tests 3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) 4 * PURPOSE: Test for cmd.exe 5 * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "precomp.h" 9 10 #define TIMEOUT 3000 11 12 typedef struct TEST_ENTRY 13 { 14 INT line; 15 DWORD dwExitCode; 16 const char *cmdline; 17 BOOL bStdOutput; 18 BOOL bStdError; 19 const char *OutputContains; 20 const char *ErrorContains; 21 const char *OutputNotContains; 22 const char *ErrorNotContains; 23 } TEST_ENTRY; 24 25 static const TEST_ENTRY s_exit_entries[] = 26 { 27 { __LINE__, 0, "cmd /c exit" }, 28 { __LINE__, 0, "cmd /c exit 0" }, 29 { __LINE__, 0, "cmd /c exit \"\"" }, 30 { __LINE__, 0, "cmd /c exit ABC" }, 31 { __LINE__, 0, "cmd /c exit \"ABC" }, 32 { __LINE__, 0, "cmd /c exit \"ABC\"" }, 33 { __LINE__, 1234, "cmd /c exit 1234" }, 34 }; 35 36 static const TEST_ENTRY s_echo_entries[] = 37 { 38 // { __LINE__, 0, "cmd /c echo", TRUE, FALSE, NULL, "ECHO" }, 39 { __LINE__, 0, "cmd /c echo.", TRUE, FALSE, "\r\n" }, 40 { __LINE__, 0, "cmd /c echo ABC", TRUE, FALSE, "ABC\r\n" }, 41 }; 42 43 static const TEST_ENTRY s_cd_entries[] = 44 { 45 { __LINE__, 0, "cmd /c cd \"C:\\ " }, 46 { __LINE__, 0, "cmd /c cd C:/" }, 47 { __LINE__, 0, "cmd /c cd \"\"", TRUE, FALSE }, 48 { __LINE__, 0, "cmd /c cd", TRUE, FALSE }, 49 { __LINE__, 1234, "cmd /c cd C:\\Program Files && exit 1234" }, 50 { __LINE__, 1234, "cmd /c cd \"C:\\ \" && exit 1234" }, 51 { __LINE__, 1234, "cmd /c cd \"C:\\Program Files\" && exit 1234" }, 52 { __LINE__, 1234, "cmd /c cd \"\" && exit 1234", TRUE, FALSE }, 53 { __LINE__, 1234, "cmd /c cd \\ && exit 1234" }, 54 }; 55 56 static const TEST_ENTRY s_pushd_entries[] = 57 { 58 { __LINE__, 0, "cmd /c pushd C:\\ " }, 59 { __LINE__, 0, "cmd /c pushd C:\\ \"" }, 60 { __LINE__, 0, "cmd /c pushd C:\\ \"\"" }, 61 { __LINE__, 0, "cmd /c pushd C:\\ \"\"\"" }, 62 { __LINE__, 0, "cmd /c pushd C:\\ \"\"\"\"" }, 63 { __LINE__, 0, "cmd /c pushd C:\\ \" " }, 64 { __LINE__, 0, "cmd /c pushd C:\\ \"\" " }, 65 { __LINE__, 0, "cmd /c pushd C:\\ \"\"\" " }, 66 { __LINE__, 0, "cmd /c pushd C:\\ \"\"\"\" " }, 67 { __LINE__, 0, "cmd /c pushd C:\\" }, 68 { __LINE__, 0, "cmd /c pushd C:\\\"" }, 69 { __LINE__, 0, "cmd /c pushd C:\\\"\"" }, 70 { __LINE__, 0, "cmd /c pushd C:\\\"\"\"" }, 71 { __LINE__, 0, "cmd /c pushd C:\\\"\"\"\"" }, 72 { __LINE__, 0, "cmd /c pushd C:\\\" " }, 73 { __LINE__, 0, "cmd /c pushd C:\\\"\" " }, 74 { __LINE__, 0, "cmd /c pushd C:\\\"\"\" " }, 75 { __LINE__, 0, "cmd /c pushd C:\\\"\"\"\" " }, 76 { __LINE__, 0, "cmd /c pushd \"C:\\ " }, 77 { __LINE__, 0, "cmd /c pushd \"C:\\ \"" }, 78 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\"" }, 79 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\"\"" }, 80 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\"\"\"" }, 81 { __LINE__, 0, "cmd /c pushd \"C:\\ \" " }, 82 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\" " }, 83 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\"\" " }, 84 { __LINE__, 0, "cmd /c pushd \"C:\\ \"\"\"\" " }, 85 { __LINE__, 0, "cmd /c pushd \"C:\\" }, 86 { __LINE__, 0, "cmd /c pushd \"C:\\\"" }, 87 { __LINE__, 0, "cmd /c pushd \"C:\\\"\"" }, 88 { __LINE__, 0, "cmd /c pushd \"C:\\\"\"\"" }, 89 { __LINE__, 0, "cmd /c pushd \"C:\\\"\"\"\"" }, 90 { __LINE__, 0, "cmd /c pushd \"C:\\\"" }, 91 { __LINE__, 1, "cmd /c pushd \" C:\\ ", FALSE, TRUE }, 92 { __LINE__, 1, "cmd /c pushd \" C:\\ \"", FALSE, TRUE }, 93 { __LINE__, 1, "cmd /c pushd \" C:\\ \"\"", FALSE, TRUE }, 94 { __LINE__, 1, "cmd /c pushd \" C:\\ \"\"\"", FALSE, TRUE }, 95 { __LINE__, 1, "cmd /c pushd \" C:\\ \"\"\"\"", FALSE, TRUE }, 96 { __LINE__, 1, "cmd /c pushd \"\" C:\\ ", FALSE, TRUE }, 97 { __LINE__, 1, "cmd /c pushd \"\" C:\\ \"", FALSE, TRUE }, 98 { __LINE__, 1, "cmd /c pushd \"\" C:\\ \"\"", FALSE, TRUE }, 99 { __LINE__, 1, "cmd /c pushd \"\" C:\\ \"\"\"", FALSE, TRUE }, 100 { __LINE__, 1, "cmd /c pushd \"\" C:\\ \"\"\"\"", FALSE, TRUE }, 101 { __LINE__, 1, "cmd /c pushd \"\" C:\\\"", FALSE, TRUE }, 102 { __LINE__, 1, "cmd /c popd ABC" }, 103 { __LINE__, 1, "cmd /c popd \" " }, 104 { __LINE__, 1, "cmd /c popd \"\"" }, 105 { __LINE__, 1, "cmd /c popd" }, 106 { __LINE__, 1, "cmd /c pushd ABC", FALSE, TRUE }, 107 { __LINE__, 1, "cmd /c pushd C:/Program Files && popd && exit 1234", FALSE, TRUE }, 108 { __LINE__, 1, "cmd /c pushd C:\\ C:\\ && popd && exit 1234", FALSE, TRUE }, 109 { __LINE__, 1, "cmd /c pushd C:\\Invalid Directory && exit 1234", FALSE, TRUE }, 110 { __LINE__, 1, "cmd /c pushd C:\\Invalid Directory && popd && exit 1234", FALSE, TRUE }, 111 { __LINE__, 1, "cmd /c pushd \" C:\\ ", FALSE, TRUE }, 112 { __LINE__, 1, "cmd /c pushd \"C:\\ C:\\\" && popd && exit 1234", FALSE, TRUE }, 113 { __LINE__, 1234, "cmd /c pushd && exit 1234 " }, 114 { __LINE__, 1234, "cmd /c pushd C:\\ && popd && exit 1234" }, 115 { __LINE__, 1234, "cmd /c pushd C:\\ \"\" && popd && exit 1234" }, 116 { __LINE__, 1234, "cmd /c pushd C:\\Program Files && popd && exit 1234" }, 117 // { __LINE__, 1234, "cmd /c pushd \"C:/Program Files/\" && popd && exit 1234" }, 118 // { __LINE__, 1234, "cmd /c pushd \"C:/Program Files\" && popd && exit 1234" }, 119 { __LINE__, 1234, "cmd /c pushd \"C:\\ \" && popd && exit 1234" }, 120 { __LINE__, 1234, "cmd /c pushd \"C:\\ \"\"\" && popd && exit 1234" }, 121 { __LINE__, 1234, "cmd /c pushd \"C:\\ \"\"\"\"\" && popd && exit 1234" }, 122 { __LINE__, 1234, "cmd /c pushd \"C:\\Program Files\" && popd && exit 1234" }, 123 { __LINE__, 1234, "cmd /c pushd \"C:\\Program Files\\\" && popd && exit 1234" }, 124 { __LINE__, 1234, "cmd /c pushd \"C:\\\" && popd && exit 1234" }, 125 }; 126 127 static const TEST_ENTRY s_attrib_entries[] = 128 { 129 /* invalid-path.txt */ 130 { __LINE__, 0, "attrib invalid-path.txt", TRUE, FALSE }, 131 { __LINE__, 0, "attrib +H invalid-path.txt", TRUE, FALSE }, 132 { __LINE__, 0, "attrib -H invalid-path.txt", TRUE, FALSE }, 133 134 /* attr-test.txt */ 135 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 136 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 137 { __LINE__, 0, "cmd /c copy NUL attr-test.txt ", TRUE, FALSE }, 138 { __LINE__, 0, "attrib attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 139 { __LINE__, 0, "attrib +H attr-test.txt", FALSE, FALSE }, 140 { __LINE__, 0, "attrib attr-test.txt", TRUE, FALSE, " H " }, 141 { __LINE__, 0, "attrib -H attr-test.txt", FALSE, FALSE }, 142 { __LINE__, 0, "attrib attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 143 { __LINE__, 0, "attrib attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 144 { __LINE__, 0, "attrib +H attr-te*.txt", FALSE, FALSE }, 145 { __LINE__, 0, "attrib attr-te*.txt", TRUE, FALSE, " H " }, 146 { __LINE__, 0, "attrib -H attr-te*.txt", FALSE, FALSE }, 147 { __LINE__, 0, "attrib attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 148 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 149 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 150 151 /* /S attr-test.txt */ 152 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 153 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 154 { __LINE__, 0, "cmd /c copy NUL attr-test.txt ", TRUE, FALSE }, 155 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 156 { __LINE__, 0, "attrib /S +H attr-test.txt", FALSE, FALSE }, 157 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, " H " }, 158 { __LINE__, 0, "attrib /S -H attr-test.txt", FALSE, FALSE }, 159 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 160 { __LINE__, 0, "attrib /S attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 161 { __LINE__, 0, "attrib /S +H attr-te*.txt", FALSE, FALSE }, 162 { __LINE__, 0, "attrib /S attr-te*.txt", TRUE, FALSE, " H " }, 163 { __LINE__, 0, "attrib /S -H attr-te*.txt", FALSE, FALSE }, 164 { __LINE__, 0, "attrib /S attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 165 { __LINE__, 0, "attrib /S +H", FALSE, FALSE }, 166 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, " H " }, 167 { __LINE__, 0, "attrib /S -H", FALSE, FALSE }, 168 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 169 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 170 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 171 172 /* /S /D attr-test.txt */ 173 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 174 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 175 { __LINE__, 0, "cmd /c copy NUL attr-test.txt ", TRUE, FALSE }, 176 { __LINE__, 0, "attrib /S /D attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 177 { __LINE__, 0, "attrib /S /D +H attr-test.txt", FALSE, FALSE }, 178 { __LINE__, 0, "attrib /S /D attr-test.txt", TRUE, FALSE, " H " }, 179 { __LINE__, 0, "attrib /S /D -H attr-test.txt", FALSE, FALSE }, 180 { __LINE__, 0, "attrib /S /D attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 181 { __LINE__, 0, "attrib /S /D attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 182 { __LINE__, 0, "attrib /S /D +H attr-te*.txt", FALSE, FALSE }, 183 { __LINE__, 0, "attrib /S /D attr-te*.txt", TRUE, FALSE, " H " }, 184 { __LINE__, 0, "attrib /S /D -H attr-te*.txt", FALSE, FALSE }, 185 { __LINE__, 0, "attrib /S /D attr-te*.txt", TRUE, FALSE, NULL, NULL, " H " }, 186 { __LINE__, 0, "cmd /c if exist attr-test.txt attrib -H attr-test.txt" }, 187 { __LINE__, 0, "cmd /c if exist attr-test.txt del /Q attr-test.txt" }, 188 189 /* attr-dir, attr-dir/test.txt */ 190 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 191 { __LINE__, 0, "cmd /c mkdir attr-dir", FALSE, FALSE }, 192 { __LINE__, 0, "cmd /c if exist attr-dir/test.txt attrib -H attr-dir/test.txt" }, 193 { __LINE__, 0, "cmd /c if exist attr-dir/test.txt del /Q attr-dir/test.txt" }, 194 { __LINE__, 1, "cmd /c copy NUL attr-dir/test.txt ", TRUE, FALSE }, 195 { __LINE__, 0, "attrib attr-dir/test.txt", TRUE, FALSE, NULL, NULL, " H " }, 196 { __LINE__, 0, "attrib +H attr-dir/test.txt", TRUE, FALSE }, 197 { __LINE__, 0, "attrib attr-dir/test.txt", TRUE, FALSE, NULL, NULL, " H " }, 198 { __LINE__, 0, "attrib -H attr-dir/test.txt", TRUE, FALSE, "test.txt" }, 199 { __LINE__, 0, "attrib attr-dir/test.txt", TRUE, FALSE, NULL, NULL, " H " }, 200 { __LINE__, 0, "attrib +H attr-dir", FALSE, FALSE, NULL, NULL, " H " }, 201 { __LINE__, 0, "attrib attr-dir", TRUE, FALSE, " H " }, 202 { __LINE__, 0, "attrib attr-dir/test.txt", TRUE, FALSE, NULL, NULL, " H " }, 203 { __LINE__, 0, "attrib -H attr-dir", FALSE, FALSE, NULL, NULL, " H " }, 204 { __LINE__, 0, "attrib attr-dir", TRUE, FALSE, NULL, NULL, " H " }, 205 { __LINE__, 0, "cmd /c if exist attr-dir/test.txt attrib -H attr-dir/test.txt" }, 206 { __LINE__, 0, "cmd /c if exist attr-dir/test.txt del /Q attr-dir/test.txt" }, 207 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 208 209 /* attr-dir, attr-dir\\dir1 */ 210 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 211 { __LINE__, 0, "cmd /c mkdir attr-dir", FALSE, FALSE }, 212 { __LINE__, 0, "attrib attr-dir", TRUE, FALSE, NULL, NULL, " H " }, 213 { __LINE__, 0, "cmd /c if exist attr-dir echo OK", TRUE, FALSE, "OK" }, 214 { __LINE__, 0, "cmd /c mkdir attr-dir\\dir1", FALSE, FALSE }, 215 { __LINE__, 0, "cmd /c if exist attr-dir\\dir1 echo OK", TRUE, FALSE, "OK" }, 216 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 217 { __LINE__, 0, "attrib +H attr-dir\\dir1", FALSE, FALSE }, 218 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, " H " }, 219 { __LINE__, 0, "attrib -H attr-dir\\dir1", FALSE, FALSE }, 220 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 221 { __LINE__, 0, "attrib +H attr-dir", FALSE, FALSE }, 222 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 223 { __LINE__, 0, "attrib -H attr-dir", FALSE, FALSE }, 224 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 225 { __LINE__, 0, "attrib +H attr-d*", TRUE, FALSE, "attr-d*" }, 226 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 227 { __LINE__, 0, "attrib -H attr-d*", TRUE, FALSE, "attr-d*" }, 228 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 229 { __LINE__, 0, "attrib +H attr-dir\\d*", TRUE, FALSE, "attr-dir\\d*" }, 230 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 231 { __LINE__, 0, "attrib -H attr-dir\\d*", TRUE, FALSE, "attr-dir\\d*" }, 232 { __LINE__, 0, "attrib attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 233 { __LINE__, 0, "attrib -H attr-dir\\dir1", FALSE, FALSE }, 234 { __LINE__, 0, "attrib -H attr-dir", FALSE, FALSE }, 235 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 236 237 /* /S attr-dir, attr-dir\\dir1 */ 238 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 239 { __LINE__, 0, "cmd /c mkdir attr-dir", FALSE, FALSE }, 240 { __LINE__, 0, "attrib /S attr-dir", TRUE, FALSE, NULL, NULL, " H " }, 241 { __LINE__, 0, "cmd /c if exist attr-dir echo OK", TRUE, FALSE, "OK" }, 242 { __LINE__, 0, "cmd /c mkdir attr-dir\\dir1", FALSE, FALSE }, 243 { __LINE__, 0, "cmd /c if exist attr-dir\\dir1 echo OK", TRUE, FALSE, "OK" }, 244 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 245 { __LINE__, 0, "attrib /S +H attr-dir\\dir1", TRUE, FALSE, "attr-dir\\dir1", }, 246 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, "attr-dir\\dir1" }, 247 { __LINE__, 0, "attrib /S -H attr-dir\\dir1", TRUE, FALSE, "attr-dir\\dir1" }, 248 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 249 { __LINE__, 0, "attrib /S +H attr-dir", TRUE, FALSE, "attr-dir" }, 250 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 251 { __LINE__, 0, "attrib /S -H attr-dir", TRUE, FALSE, "attr-dir" }, 252 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 253 { __LINE__, 0, "attrib /S +H attr-d*", TRUE, FALSE, "attr-d*" }, 254 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 255 { __LINE__, 0, "attrib /S -H attr-d*", TRUE, FALSE, "attr-d*" }, 256 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 257 { __LINE__, 0, "attrib /S +H attr-dir\\d*", TRUE, FALSE, "attr-dir\\d*" }, 258 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 259 { __LINE__, 0, "attrib /S -H attr-dir\\d*", TRUE, FALSE, "attr-dir\\d*" }, 260 { __LINE__, 0, "attrib /S attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 261 { __LINE__, 0, "attrib /S -H attr-dir\\dir1", TRUE, FALSE, "attr-dir\\dir1" }, 262 { __LINE__, 0, "attrib /S -H attr-dir", TRUE, FALSE, "attr-dir" }, 263 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 264 265 /* /S /D attr-dir, attr-dir\\dir1 */ 266 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 267 { __LINE__, 0, "cmd /c mkdir attr-dir", FALSE, FALSE }, 268 { __LINE__, 0, "attrib /S /D attr-dir", TRUE, FALSE, NULL, NULL, " H " }, 269 { __LINE__, 0, "cmd /c if exist attr-dir echo OK", TRUE, FALSE, "OK" }, 270 { __LINE__, 0, "cmd /c mkdir attr-dir\\dir1", FALSE, FALSE }, 271 { __LINE__, 0, "cmd /c if exist attr-dir\\dir1 echo OK", TRUE, FALSE, "OK" }, 272 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 273 { __LINE__, 0, "attrib /S /D +H attr-dir\\dir1", FALSE, FALSE }, 274 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, " H " }, 275 { __LINE__, 0, "attrib /S /D -H attr-dir\\dir1", FALSE, FALSE }, 276 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 277 { __LINE__, 0, "attrib /S /D +H attr-dir", FALSE, FALSE }, 278 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 279 { __LINE__, 0, "attrib /S /D -H attr-dir", FALSE, FALSE }, 280 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 281 { __LINE__, 0, "attrib /S /D +H attr-d*", FALSE, FALSE }, 282 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 283 { __LINE__, 0, "attrib /S /D -H attr-d*", FALSE, FALSE }, 284 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 285 { __LINE__, 0, "attrib /S /D +H attr-dir\\d*", FALSE, FALSE }, 286 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, " H " }, 287 { __LINE__, 0, "attrib /S /D -H attr-dir\\d*", FALSE, FALSE }, 288 { __LINE__, 0, "attrib /S /D attr-dir\\dir1", TRUE, FALSE, NULL, NULL, " H " }, 289 { __LINE__, 0, "attrib /S /D -H attr-dir\\dir1", FALSE, FALSE }, 290 { __LINE__, 0, "attrib /S /D -H attr-dir", FALSE, FALSE }, 291 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 292 293 /* /S attr-dir, attr-dir\\dir1\\file.txt */ 294 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 295 { __LINE__, 0, "cmd /c mkdir attr-dir", FALSE, FALSE }, 296 { __LINE__, 0, "attrib /S /D attr-dir", TRUE, FALSE, NULL, NULL, " H " }, 297 { __LINE__, 0, "cmd /c if exist attr-dir echo OK", TRUE, FALSE, "OK" }, 298 { __LINE__, 0, "cmd /c mkdir attr-dir\\dir1", FALSE, FALSE }, 299 { __LINE__, 0, "cmd /c if exist attr-dir\\dir1 echo OK", TRUE, FALSE, "OK" }, 300 { __LINE__, 0, "cmd /c copy NUL attr-dir\\dir1\\attr-test.txt ", TRUE, FALSE }, 301 { __LINE__, 0, "attrib attr-dir\\dir1\\attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 302 { __LINE__, 0, "attrib /S +H attr-dir\\dir1\\attr-test.txt", FALSE, FALSE }, 303 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, " H " }, 304 { __LINE__, 0, "attrib /S -H attr-dir\\dir1\\attr-test.txt", FALSE, FALSE }, 305 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 306 { __LINE__, 0, "attrib /S +H attr-test.txt", FALSE, FALSE }, 307 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, " H " }, 308 { __LINE__, 0, "attrib /S -H attr-test.txt", FALSE, FALSE }, 309 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 310 { __LINE__, 0, "attrib /S +H", FALSE, FALSE }, 311 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, " H " }, 312 { __LINE__, 0, "attrib /S attr-tes*.*", TRUE, FALSE, " H " }, 313 { __LINE__, 0, "attrib /S -H", FALSE, FALSE }, 314 { __LINE__, 0, "attrib /S attr-test.txt", TRUE, FALSE, NULL, NULL, " H " }, 315 { __LINE__, 0, "attrib /S attr-tes*.*", TRUE, FALSE, NULL, NULL, " H " }, 316 { __LINE__, 0, "cmd /c if exist attr-dir/dir1/test.txt attrib -H attr-dir/dir1/test.txt" }, 317 { __LINE__, 0, "cmd /c if exist attr-dir/dir1/test.txt del /Q attr-dir/dir1/test.txt" }, 318 { __LINE__, 0, "cmd /c if exist attr-dir rmdir /s /q attr-dir" }, 319 320 }; 321 322 static BOOL MyDuplicateHandle(HANDLE hFile, PHANDLE phFile, BOOL bInherit) 323 { 324 HANDLE hProcess = GetCurrentProcess(); 325 return DuplicateHandle(hProcess, hFile, hProcess, phFile, 0, 326 bInherit, DUPLICATE_SAME_ACCESS); 327 } 328 329 static BOOL PrepareForRedirect(STARTUPINFOA *psi, PHANDLE phInputWrite, 330 PHANDLE phOutputRead, PHANDLE phErrorRead) 331 { 332 HANDLE hInputRead = NULL, hInputWriteTmp = NULL; 333 HANDLE hOutputReadTmp = NULL, hOutputWrite = NULL; 334 HANDLE hErrorReadTmp = NULL, hErrorWrite = NULL; 335 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE }; 336 337 psi->hStdInput = NULL; 338 psi->hStdOutput = NULL; 339 psi->hStdError = NULL; 340 341 if (phInputWrite) 342 { 343 if (CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0)) 344 { 345 if (!MyDuplicateHandle(hInputWriteTmp, phInputWrite, FALSE)) 346 goto failed; 347 348 CloseHandle(hInputWriteTmp); 349 } 350 else 351 goto failed; 352 } 353 354 if (phOutputRead) 355 { 356 if (CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0)) 357 { 358 if (!MyDuplicateHandle(hOutputReadTmp, phOutputRead, FALSE)) 359 goto failed; 360 361 CloseHandle(hOutputReadTmp); 362 } 363 else 364 goto failed; 365 } 366 367 if (phOutputRead && phOutputRead == phErrorRead) 368 { 369 if (!MyDuplicateHandle(hOutputWrite, &hErrorWrite, TRUE)) 370 goto failed; 371 } 372 else if (phErrorRead) 373 { 374 if (CreatePipe(&hErrorReadTmp, &hErrorWrite, &sa, 0)) 375 { 376 if (!MyDuplicateHandle(hErrorReadTmp, phErrorRead, FALSE)) 377 goto failed; 378 CloseHandle(hErrorReadTmp); 379 } 380 else 381 goto failed; 382 } 383 384 if (phInputWrite) 385 psi->hStdInput = hInputRead; 386 if (phOutputRead) 387 psi->hStdOutput = hOutputWrite; 388 if (phErrorRead) 389 psi->hStdError = hErrorWrite; 390 391 return TRUE; 392 393 failed: 394 CloseHandle(hInputRead); 395 CloseHandle(hInputWriteTmp); 396 CloseHandle(hOutputReadTmp); 397 CloseHandle(hOutputWrite); 398 CloseHandle(hErrorReadTmp); 399 CloseHandle(hErrorWrite); 400 return FALSE; 401 } 402 403 static void DoTestEntry(const TEST_ENTRY *pEntry) 404 { 405 STARTUPINFOA si; 406 PROCESS_INFORMATION pi; 407 DWORD dwExitCode, dwWait; 408 HANDLE hOutputRead = NULL; 409 HANDLE hErrorRead = NULL; 410 DWORD dwRead; 411 BOOL bStdOutput, bStdError; 412 CHAR szOut[512], szErr[512]; 413 414 memset(&si, 0, sizeof(si)); 415 si.cb = sizeof(si); 416 si.dwFlags = STARTF_USESTDHANDLES; 417 418 if (!PrepareForRedirect(&si, NULL, &hOutputRead, &hErrorRead)) 419 { 420 skip("PrepareForRedirect failed\n"); 421 return; 422 } 423 424 if (CreateProcessA(NULL, (char *)pEntry->cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) 425 { 426 CloseHandle(si.hStdInput); 427 dwWait = WaitForSingleObject(pi.hProcess, TIMEOUT); 428 if (dwWait == WAIT_TIMEOUT) 429 { 430 TerminateProcess(pi.hProcess, 9999); 431 } 432 GetExitCodeProcess(pi.hProcess, &dwExitCode); 433 CloseHandle(pi.hThread); 434 CloseHandle(pi.hProcess); 435 } 436 else 437 { 438 dwExitCode = 8888; 439 } 440 441 ZeroMemory(szOut, sizeof(szOut)); 442 PeekNamedPipe(hOutputRead, szOut, ARRAYSIZE(szOut), &dwRead, NULL, NULL); 443 szOut[ARRAYSIZE(szOut) - 1] = 0; 444 bStdOutput = dwRead != 0; 445 446 ZeroMemory(szErr, sizeof(szErr)); 447 PeekNamedPipe(hErrorRead, szErr, ARRAYSIZE(szErr), &dwRead, NULL, NULL); 448 szErr[ARRAYSIZE(szErr) - 1] = 0; 449 bStdError = dwRead != 0; 450 451 if (si.hStdInput) 452 CloseHandle(si.hStdInput); 453 if (si.hStdOutput) 454 CloseHandle(si.hStdOutput); 455 if (si.hStdError) 456 CloseHandle(si.hStdError); 457 458 ok(pEntry->bStdOutput == bStdOutput, 459 "Line %u: bStdOutput %d vs %d\n", 460 pEntry->line, pEntry->bStdOutput, bStdOutput); 461 462 ok(pEntry->bStdError == bStdError, 463 "Line %u: bStdError %d vs %d\n", 464 pEntry->line, pEntry->bStdError, bStdError); 465 466 ok(pEntry->dwExitCode == dwExitCode, 467 "Line %u: dwExitCode %ld vs %ld\n", 468 pEntry->line, pEntry->dwExitCode, dwExitCode); 469 470 if (pEntry->OutputContains) 471 { 472 ok(strstr(szOut, pEntry->OutputContains) != NULL, 473 "Line %u: szOut was '%s'\n", 474 pEntry->line, szOut); 475 } 476 477 if (pEntry->ErrorContains) 478 { 479 ok(strstr(szErr, pEntry->ErrorContains) != NULL, 480 "Line %u: szErr was '%s'\n", 481 pEntry->line, szErr); 482 } 483 484 if (pEntry->OutputNotContains) 485 { 486 ok(strstr(szOut, pEntry->OutputNotContains) == NULL, 487 "Line %u: szOut was '%s'\n", 488 pEntry->line, szOut); 489 } 490 491 if (pEntry->ErrorNotContains) 492 { 493 ok(strstr(szErr, pEntry->ErrorNotContains) == NULL, 494 "Line %u: szErr was '%s'\n", 495 pEntry->line, szErr); 496 } 497 } 498 499 START_TEST(exit) 500 { 501 SIZE_T i; 502 for (i = 0; i < ARRAYSIZE(s_exit_entries); ++i) 503 { 504 DoTestEntry(&s_exit_entries[i]); 505 } 506 } 507 508 START_TEST(echo) 509 { 510 SIZE_T i; 511 for (i = 0; i < ARRAYSIZE(s_echo_entries); ++i) 512 { 513 DoTestEntry(&s_echo_entries[i]); 514 } 515 } 516 517 START_TEST(cd) 518 { 519 SIZE_T i; 520 for (i = 0; i < ARRAYSIZE(s_cd_entries); ++i) 521 { 522 DoTestEntry(&s_cd_entries[i]); 523 } 524 } 525 526 START_TEST(pushd) 527 { 528 SIZE_T i; 529 for (i = 0; i < ARRAYSIZE(s_pushd_entries); ++i) 530 { 531 DoTestEntry(&s_pushd_entries[i]); 532 } 533 } 534 535 START_TEST(attrib) 536 { 537 SIZE_T i; 538 for (i = 0; i < ARRAYSIZE(s_attrib_entries); ++i) 539 { 540 DoTestEntry(&s_attrib_entries[i]); 541 } 542 } 543