https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e753d5e1086e96a4978d061e0ca6ff1b9cf4d896

commit e753d5e1086e96a4978d061e0ca6ff1b9cf4d896
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Thu Nov 14 22:52:31 2019 +0900
Commit:     GitHub <[email protected]>
CommitDate: Thu Nov 14 22:52:31 2019 +0900

    [CMD_APITEST] Add cmd_apitest testcases (#2034)
    
    Add some testcases for cmd.exe. CORE-12150
---
 modules/rostests/apitests/CMakeLists.txt     |   1 +
 modules/rostests/apitests/cmd/CMakeLists.txt |  11 +
 modules/rostests/apitests/cmd/cmd.c          | 300 +++++++++++++++++++++++++++
 modules/rostests/apitests/cmd/precomp.h      |   6 +
 modules/rostests/apitests/cmd/testlist.c     |  16 ++
 5 files changed, 334 insertions(+)

diff --git a/modules/rostests/apitests/CMakeLists.txt 
b/modules/rostests/apitests/CMakeLists.txt
index 8910f89b56a..62ca4c742bc 100644
--- a/modules/rostests/apitests/CMakeLists.txt
+++ b/modules/rostests/apitests/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(apphelp)
 add_subdirectory(appshim)
 add_subdirectory(atl)
 add_subdirectory(browseui)
+add_subdirectory(cmd)
 add_subdirectory(com)
 add_subdirectory(comctl32)
 add_subdirectory(crt)
diff --git a/modules/rostests/apitests/cmd/CMakeLists.txt 
b/modules/rostests/apitests/cmd/CMakeLists.txt
new file mode 100644
index 00000000000..5eae6ccdee6
--- /dev/null
+++ b/modules/rostests/apitests/cmd/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+list(APPEND SOURCE
+    cmd.c
+    precomp.h)
+
+add_executable(cmd_apitest ${SOURCE} testlist.c)
+target_link_libraries(cmd_apitest wine ${PSEH_LIB})
+set_module_type(cmd_apitest win32cui)
+add_importlibs(cmd_apitest msvcrt kernel32)
+add_pch(cmd_apitest precomp.h SOURCE)
+add_rostests_file(TARGET cmd_apitest)
diff --git a/modules/rostests/apitests/cmd/cmd.c 
b/modules/rostests/apitests/cmd/cmd.c
new file mode 100644
index 00000000000..f4e79cc59bd
--- /dev/null
+++ b/modules/rostests/apitests/cmd/cmd.c
@@ -0,0 +1,300 @@
+/*
+ * PROJECT:     ReactOS API tests
+ * LICENSE:     LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
+ * PURPOSE:     Test for cmd.exe
+ * COPYRIGHT:   Copyright 2019 Katayama Hirofumi MZ 
<[email protected]>
+ */
+
+#include "precomp.h"
+
+#define TIMEOUT 3000
+
+typedef struct TEST_ENTRY
+{
+    INT line;
+    DWORD dwExitCode;
+    const char *cmdline;
+    BOOL bStdOutput;
+    BOOL bStdError;
+} TEST_ENTRY;
+
+static const TEST_ENTRY s_exit_entries[] =
+{
+    { __LINE__, 0,      "cmd /c exit" },
+    { __LINE__, 0,      "cmd /c exit 0" },
+    { __LINE__, 0,      "cmd /c exit \"\"" },
+    { __LINE__, 0,      "cmd /c exit ABC" },
+    { __LINE__, 0,      "cmd /c exit \"ABC" },
+    { __LINE__, 0,      "cmd /c exit \"ABC\"" },
+    { __LINE__, 1234,   "cmd /c exit 1234" },
+};
+
+static const TEST_ENTRY s_echo_entries[] =
+{
+    { __LINE__, 0,      "cmd /c echo", TRUE, FALSE },
+    { __LINE__, 0,      "cmd /c echo.", TRUE, FALSE },
+};
+
+static const TEST_ENTRY s_cd_entries[] =
+{
+    { __LINE__, 0,      "cmd /c cd \"C:\\ ", },
+    { __LINE__, 0,      "cmd /c cd C:/", },
+    { __LINE__, 0,      "cmd /c cd \"\"", TRUE, FALSE },
+    { __LINE__, 0,      "cmd /c cd", TRUE, FALSE },
+    { __LINE__, 1234,   "cmd /c cd C:\\Program Files && exit 1234" },
+    { __LINE__, 1234,   "cmd /c cd \"C:\\ \" && exit 1234", },
+    { __LINE__, 1234,   "cmd /c cd \"C:\\Program Files\" && exit 1234", },
+    { __LINE__, 1234,   "cmd /c cd \"\" && exit 1234", TRUE, FALSE },
+    { __LINE__, 1234,   "cmd /c cd \\ && exit 1234" },
+};
+
+static const TEST_ENTRY s_pushd_entries[] =
+{
+    { __LINE__, 0,      "cmd /c pushd C:\\ " },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\ \"\"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\" },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd C:\\\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd C:\\\"\"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \" " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\" " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\ \"\"\"\" " },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\\"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\\"\"\"\"" },
+    { __LINE__, 0,      "cmd /c pushd \"C:\\\"" },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ ", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ \"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ \"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ \"\"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ \"\"\"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\ ", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\ \"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\ \"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\ \"\"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\ \"\"\"\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"\" C:\\\"", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c popd ABC" },
+    { __LINE__, 1,      "cmd /c popd \" " },
+    { __LINE__, 1,      "cmd /c popd \"\"" },
+    { __LINE__, 1,      "cmd /c popd" },
+    { __LINE__, 1,      "cmd /c pushd ABC", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd C:/Program Files && popd && exit 1234", 
FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd C:\\ C:\\ && popd && exit 1234", FALSE, 
TRUE },
+    { __LINE__, 1,      "cmd /c pushd C:\\Invalid Directory && exit 1234", 
FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd C:\\Invalid Directory && popd && exit 
1234", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \" C:\\ ", FALSE, TRUE },
+    { __LINE__, 1,      "cmd /c pushd \"C:\\ C:\\\" && popd && exit 1234", 
FALSE, TRUE },
+    { __LINE__, 1234,   "cmd /c pushd && exit 1234 " },
+    { __LINE__, 1234,   "cmd /c pushd C:\\ && popd && exit 1234" },
+    { __LINE__, 1234,   "cmd /c pushd C:\\ \"\" && popd && exit 1234" },
+    { __LINE__, 1234,   "cmd /c pushd C:\\Program Files && popd && exit 1234" 
},
+    { __LINE__, 1234,   "cmd /c pushd \"C:/Program Files/\" && popd && exit 
1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:/Program Files\" && popd && exit 
1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\ \" && popd && exit 1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\ \"\"\" && popd && exit 1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\ \"\"\"\"\" && popd && exit 1234" 
},
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\Program Files\" && popd && exit 
1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\Program Files\\\" && popd && exit 
1234" },
+    { __LINE__, 1234,   "cmd /c pushd \"C:\\\" && popd && exit 1234" },
+};
+
+static BOOL MyDuplicateHandle(HANDLE hFile, PHANDLE phFile, BOOL bInherit)
+{
+    HANDLE hProcess = GetCurrentProcess();
+    return DuplicateHandle(hProcess, hFile, hProcess, phFile, 0,
+                           bInherit, DUPLICATE_SAME_ACCESS);
+}
+
+static BOOL PrepareForRedirect(STARTUPINFOA *psi, PHANDLE phInputWrite,
+                               PHANDLE phOutputRead, PHANDLE phErrorRead)
+{
+    HANDLE hInputRead = NULL, hInputWriteTmp = NULL;
+    HANDLE hOutputReadTmp = NULL, hOutputWrite = NULL;
+    HANDLE hErrorReadTmp = NULL, hErrorWrite = NULL;
+    SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
+
+    psi->hStdInput = NULL;
+    psi->hStdOutput = NULL;
+    psi->hStdError = NULL;
+
+    if (phInputWrite)
+    {
+        if (CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0))
+        {
+            if (!MyDuplicateHandle(hInputWriteTmp, phInputWrite, FALSE))
+                goto failed;
+
+            CloseHandle(hInputWriteTmp);
+        }
+        else
+            goto failed;
+    }
+
+    if (phOutputRead)
+    {
+        if (CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0))
+        {
+            if (!MyDuplicateHandle(hOutputReadTmp, phOutputRead, FALSE))
+                goto failed;
+
+            CloseHandle(hOutputReadTmp);
+        }
+        else
+            goto failed;
+    }
+
+    if (phOutputRead && phOutputRead == phErrorRead)
+    {
+        if (!MyDuplicateHandle(hOutputWrite, &hErrorWrite, TRUE))
+            goto failed;
+    }
+    else if (phErrorRead)
+    {
+        if (CreatePipe(&hErrorReadTmp, &hErrorWrite, &sa, 0))
+        {
+            if (!MyDuplicateHandle(hErrorReadTmp, phErrorRead, FALSE))
+                goto failed;
+            CloseHandle(hErrorReadTmp);
+        }
+        else
+            goto failed;
+    }
+
+    if (phInputWrite)
+        psi->hStdInput = hInputRead;
+    if (phOutputRead)
+        psi->hStdOutput = hOutputWrite;
+    if (phErrorRead)
+        psi->hStdError = hErrorWrite;
+
+    return TRUE;
+
+failed:
+    CloseHandle(hInputRead);
+    CloseHandle(hInputWriteTmp);
+    CloseHandle(hOutputReadTmp);
+    CloseHandle(hOutputWrite);
+    CloseHandle(hErrorReadTmp);
+    CloseHandle(hErrorWrite);
+    return FALSE;
+}
+
+static void DoTestEntry(const TEST_ENTRY *pEntry)
+{
+    STARTUPINFOA si;
+    PROCESS_INFORMATION pi;
+    DWORD dwExitCode, dwWait;
+    HANDLE hOutputRead = NULL;
+    HANDLE hErrorRead = NULL;
+    BYTE b;
+    DWORD dwRead;
+    BOOL bStdOutput, bStdError;
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    si.dwFlags = STARTF_USESTDHANDLES;
+
+    if (!PrepareForRedirect(&si, NULL, &hOutputRead, &hErrorRead))
+    {
+        skip("PrepareForRedirect failed\n");
+        return;
+    }
+
+    if (CreateProcessA(NULL, (char *)pEntry->cmdline, NULL, NULL, TRUE, 0, 
NULL, NULL, &si, &pi))
+    {
+        CloseHandle(si.hStdInput);
+        dwWait = WaitForSingleObject(pi.hProcess, TIMEOUT);
+        if (dwWait == WAIT_TIMEOUT)
+        {
+            TerminateProcess(pi.hProcess, 9999);
+        }
+        GetExitCodeProcess(pi.hProcess, &dwExitCode);
+        CloseHandle(pi.hThread);
+        CloseHandle(pi.hProcess);
+    }
+    else
+    {
+        dwExitCode = 8888;
+    }
+
+    PeekNamedPipe(hOutputRead, &b, 1, &dwRead, NULL, NULL);
+    bStdOutput = dwRead != 0;
+    PeekNamedPipe(hErrorRead, &b, 1, &dwRead, NULL, NULL);
+    bStdError = dwRead != 0;
+
+    if (si.hStdInput)
+        CloseHandle(si.hStdInput);
+    if (si.hStdOutput)
+        CloseHandle(si.hStdOutput);
+    if (si.hStdError)
+        CloseHandle(si.hStdError);
+
+    ok(pEntry->bStdOutput == bStdOutput,
+       "Line %u: bStdOutput %d vs %d\n",
+       pEntry->line, pEntry->bStdOutput, bStdOutput);
+
+    ok(pEntry->bStdError == bStdError,
+       "Line %u: bStdError %d vs %d\n",
+       pEntry->line, pEntry->bStdError, bStdError);
+
+    ok(pEntry->dwExitCode == dwExitCode,
+       "Line %u: dwExitCode %ld vs %ld\n",
+       pEntry->line, pEntry->dwExitCode, dwExitCode);
+}
+
+START_TEST(exit)
+{
+    SIZE_T i;
+    for (i = 0; i < ARRAYSIZE(s_exit_entries); ++i)
+    {
+        DoTestEntry(&s_exit_entries[i]);
+    }
+}
+
+START_TEST(echo)
+{
+    SIZE_T i;
+    for (i = 0; i < ARRAYSIZE(s_echo_entries); ++i)
+    {
+        DoTestEntry(&s_echo_entries[i]);
+    }
+}
+
+START_TEST(cd)
+{
+    SIZE_T i;
+    for (i = 0; i < ARRAYSIZE(s_cd_entries); ++i)
+    {
+        DoTestEntry(&s_cd_entries[i]);
+    }
+}
+
+START_TEST(pushd)
+{
+    SIZE_T i;
+    for (i = 0; i < ARRAYSIZE(s_pushd_entries); ++i)
+    {
+        DoTestEntry(&s_pushd_entries[i]);
+    }
+}
diff --git a/modules/rostests/apitests/cmd/precomp.h 
b/modules/rostests/apitests/cmd/precomp.h
new file mode 100644
index 00000000000..13f2ddb0772
--- /dev/null
+++ b/modules/rostests/apitests/cmd/precomp.h
@@ -0,0 +1,6 @@
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#include <apitest.h>
+#include <windows.h>
diff --git a/modules/rostests/apitests/cmd/testlist.c 
b/modules/rostests/apitests/cmd/testlist.c
new file mode 100644
index 00000000000..07ab34a2c97
--- /dev/null
+++ b/modules/rostests/apitests/cmd/testlist.c
@@ -0,0 +1,16 @@
+#define STANDALONE
+#include <apitest.h>
+
+extern void func_cd(void);
+extern void func_echo(void);
+extern void func_exit(void);
+extern void func_pushd(void);
+
+const struct test winetest_testlist[] =
+{
+    { "cd", func_cd },
+    { "echo", func_echo },
+    { "exit", func_exit },
+    { "pushd", func_pushd },
+    { 0, 0 }
+};

Reply via email to