[ROSTESTS] Add a new test for "gethostname" in ws2_32_apitest. (#1630) 1630/head
authorDoug-Lyons <douglyons@douglyons.com>
Sat, 8 Jun 2019 22:39:05 +0000 (17:39 -0500)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 15 Jun 2019 22:15:55 +0000 (00:15 +0200)
ROSTESTS-326

Make the test more robust; clean up on failures.

Co-authored-by: Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
modules/rostests/apitests/ws2_32/CMakeLists.txt
modules/rostests/apitests/ws2_32/gethostname.c [new file with mode: 0644]
modules/rostests/apitests/ws2_32/testlist.c

index cae491a..d9ad413 100644 (file)
@@ -3,6 +3,7 @@ list(APPEND SOURCE
     bind.c
     close.c
     getaddrinfo.c
     bind.c
     close.c
     getaddrinfo.c
+    gethostname.c
     getnameinfo.c
     getservbyname.c
     getservbyport.c
     getnameinfo.c
     getservbyname.c
     getservbyport.c
@@ -22,6 +23,6 @@ list(APPEND SOURCE
 add_executable(ws2_32_apitest ${SOURCE} testlist.c)
 target_link_libraries(ws2_32_apitest wine ${PSEH_LIB})
 set_module_type(ws2_32_apitest win32cui)
 add_executable(ws2_32_apitest ${SOURCE} testlist.c)
 target_link_libraries(ws2_32_apitest wine ${PSEH_LIB})
 set_module_type(ws2_32_apitest win32cui)
-add_importlibs(ws2_32_apitest ws2_32 msvcrt iphlpapi kernel32 ntdll)
+add_importlibs(ws2_32_apitest advapi32 iphlpapi ws2_32 msvcrt kernel32 ntdll)
 add_pch(ws2_32_apitest ws2_32.h SOURCE)
 add_rostests_file(TARGET ws2_32_apitest)
 add_pch(ws2_32_apitest ws2_32.h SOURCE)
 add_rostests_file(TARGET ws2_32_apitest)
diff --git a/modules/rostests/apitests/ws2_32/gethostname.c b/modules/rostests/apitests/ws2_32/gethostname.c
new file mode 100644 (file)
index 0000000..4bfb3c4
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * PROJECT:     ReactOS API tests
+ * LICENSE:     LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
+ * PURPOSE:     Tests for Hostname command and Winsock gethostname() function.
+ * COPYRIGHT:   Copyright 2019 Doug Lyons <douglyons@douglyons.com>
+ *              Copyright 2019 Hermes Belusca-Maito
+ */
+
+#include "ws2_32.h"
+
+#include <winreg.h>
+
+#define REG_HOSTNAME_KEY        L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+#define REG_COMPUTERNAME_KEY    L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
+
+HKEY
+OpenRegKey(
+    IN HKEY   hRootKey,
+    IN PCWSTR pszSubKey,
+    IN DWORD  ulOptions)
+{
+    HKEY hKey = NULL;
+    LONG Error = RegOpenKeyExW(hRootKey, pszSubKey, 0, ulOptions, &hKey);
+    if (Error == ERROR_SUCCESS)
+        return hKey;
+    return NULL;
+}
+
+BOOL
+GetHostnameFromCommand(
+    OUT PSTR pszHostnameBuffer,
+    IN ULONG ulBufferSize)
+{
+    PCSTR file_name = "HostName123.txt";
+    CHAR cmdline[MAX_PATH] = "hostname > ";
+    FILE *fp;
+    INT iResult;
+    INT len;
+    PCSTR ptr;
+
+    ZeroMemory(pszHostnameBuffer, ulBufferSize * sizeof(CHAR));
+
+    /* Run the 'hostname' command, piping out its result to the temporary file */
+    strcat(cmdline, file_name);
+    system(cmdline);
+
+    /* Open the temporary file in read mode */
+    fp = fopen(file_name, "r");
+    ok(fp != NULL, "An error occurred while opening the file.\n");
+    if (fp == NULL)
+        return FALSE;
+
+    /* Read its contents */
+    ptr = fgets(pszHostnameBuffer, ulBufferSize * sizeof(CHAR), fp);
+    ok(ptr != NULL, "An error occurred while reading the file.\n");
+    if (ptr == NULL)
+        goto Cleanup;
+
+    /* Delete the expected ending line feed character */
+    len = strlen(pszHostnameBuffer);
+    if (pszHostnameBuffer[len-1] == '\r' || pszHostnameBuffer[len-1] == '\n')
+        pszHostnameBuffer[len-1] = ANSI_NULL;
+
+Cleanup:
+    /* Close and remove the file */
+    iResult = fclose(fp);
+    ok(iResult == 0, "An error occurred while closing the file: %i.\n", iResult);
+    iResult = remove(file_name);
+    ok(iResult == 0, "An error occurred while deleting the file: %i.\n", iResult);
+
+    return (ptr ? TRUE : FALSE);
+}
+
+START_TEST(gethostname)
+{
+    INT pos;
+    HKEY hKeyHN;
+    DWORD cbData;
+    LONG Error;
+    INT hnError;
+    INT iResult;
+    WSADATA wsaData;
+    DWORD uApiHostNameSize;
+    CHAR szApiHostName[256] = "";
+    CHAR szHostNameOld[256] = "";
+    CHAR szHostNameNew[256] = "";
+    CHAR hostbuffer[256] = "";
+
+/*
+ * Notes about the retrieval of the computer name on Windows.
+ *
+ * - GetComputerName() (equivalently, GetComputerNameEx(ComputerNameNetBIOS))
+ *   retrieves the name cached in the registry value "ComputerName" under
+ *   "System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName" .
+ *
+ * - GetComputerNameEx(ComputerNameDnsHostname) as well as the 'hostname' command
+     return the registry value "Hostname" under "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" .
+ *
+ * - In case a new computer name is set, its value is cached in the registry value
+ *   "ComputerName" under "System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",
+ *   and also in the registry value "NV Hostname" under "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" .
+ */
+
+    /* Retrieve the current host name using API */
+    uApiHostNameSize = _countof(szApiHostName);
+    if (!GetComputerNameExA(ComputerNameDnsHostname, szApiHostName, &uApiHostNameSize))
+    {
+        /* Fail in case of error */
+        skip("GetComputerNameExA(ComputerNameDnsHostname) failed, error %lu\n", GetLastError());
+        return;
+    }
+    printf("The Hostname from API is '%s'.\n", szApiHostName);
+
+    /* Retrieve the current host name using the 'hostname' command */
+    if (!GetHostnameFromCommand(hostbuffer, _countof(hostbuffer)))
+    {
+        /* Fail in case of error */
+        skip("Error while retrieving the host name using the 'hostname' command!\n");
+        return;
+    }
+    printf("The Hostname from command is '%s'.\n", hostbuffer);
+
+    pos = strcmp(szApiHostName, hostbuffer);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "hostbuffer '%s' should have been szApiHostName '%s'.\n", hostbuffer, szApiHostName);
+
+    hKeyHN = OpenRegKey(HKEY_LOCAL_MACHINE, REG_HOSTNAME_KEY, KEY_ALL_ACCESS);
+    ok(hKeyHN != NULL, "Error while opening hostname registry key.\n");
+    if (hKeyHN == NULL)
+        return;
+
+    /* Get Old Hostname */
+    szHostNameOld[0] = ANSI_NULL;
+    cbData = sizeof(szHostNameOld);
+    Error = RegQueryValueExA(hKeyHN, "Hostname", NULL, NULL, (LPBYTE)szHostNameOld, &cbData);
+
+    printf("Hostname from Registry is '%s'.\n", szHostNameOld);
+
+    pos = strcmp(szHostNameOld, szApiHostName);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "szApiHostName '%s' should have been szHostNameOld '%s'.\n", szApiHostName, szHostNameOld);
+
+    /* Change Hostname in the Registry */
+    szHostNameNew[0] = ANSI_NULL;
+    strcat(szHostNameNew, "ROSHOSTNAME1");
+    cbData = strlen(szHostNameNew) + 1;
+
+    Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameNew, cbData);
+    ok(Error == ERROR_SUCCESS, "Error setting new registry value (%ld).\n", GetLastError());
+
+    /* Retrieve the current host name using API */
+    uApiHostNameSize = _countof(szApiHostName);
+    if (!GetComputerNameExA(ComputerNameDnsHostname, szApiHostName, &uApiHostNameSize))
+    {
+        /* Fail in case of error */
+        skip("GetComputerNameExA(ComputerNameDnsHostname) failed, error %lu\n", GetLastError());
+        goto Cleanup;
+    }
+    printf("The Hostname from API is '%s'.\n", szApiHostName);
+
+    /* Retrieve the current host name using the 'hostname' command */
+    if (!GetHostnameFromCommand(hostbuffer, _countof(hostbuffer)))
+    {
+        /* Fail in case of error */
+        skip("Error while retrieving the host name using the 'hostname' command!\n");
+        goto Cleanup;
+    }
+    printf("The Hostname from command is '%s'.\n", hostbuffer);
+
+    pos = strcmp(szHostNameNew, szApiHostName);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "szApiHostName '%s' should be szHostNameNew '%s'.\n", szApiHostName, szHostNameNew);
+
+    pos = strcmp(szHostNameNew, hostbuffer);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "hostbuffer '%s' should have been szHostNameNew '%s'.\n", hostbuffer, szHostNameNew);
+
+    /* Reset the original registry entry */
+    cbData = strlen(szHostNameOld) + 1;
+
+    Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameOld, cbData);
+    ok(Error == ERROR_SUCCESS, "Error resetting new registry value back (%ld).\n", GetLastError());
+
+/*============ Winsock Checks ===============*/
+
+    /* Start up Winsock to use gethostname() */
+    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+    ok(iResult == 0, "Error occurred starting Winsock");
+    if (iResult != 0)
+        goto Cleanup;
+
+    /* Retrieve gethostname() */
+    hnError = gethostname(hostbuffer, sizeof(hostbuffer));
+    ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
+
+    /* Display results */
+    if (!hnError)
+        printf("Winsock gethostname() is '%s'.\n", hostbuffer);
+
+    pos = strcmp(szHostNameOld, hostbuffer);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "szHostNameOld '%s' should be hostbuffer '%s'.\n", szHostNameOld, hostbuffer);
+
+    /* Change Hostname in the Registry */
+    szHostNameNew[0] = ANSI_NULL;
+    strcat(szHostNameNew, "ROSHOSTNAME1");
+    cbData = strlen(szHostNameNew) + 1;
+
+    Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameNew, cbData);
+    ok(Error == ERROR_SUCCESS, "Error setting new registry value (%ld).\n", GetLastError());
+
+    /* Retrieve gethostname() */
+    hnError = gethostname(hostbuffer, sizeof(hostbuffer));
+    ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
+
+    /* Display results */
+    if (!hnError)
+        printf("Winsock gethostname() is '%s'.\n", hostbuffer);
+
+    pos = strcmp(szHostNameNew, hostbuffer);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "szHostNameNew '%s' should be hostbuffer '%s'.\n", szHostNameNew, hostbuffer);
+
+    /* Reset the original registry entry */
+    cbData = strlen(szHostNameOld) + 1;
+
+    Error = RegSetValueExA(hKeyHN, "Hostname", 0, REG_SZ, (LPBYTE)szHostNameOld, cbData);
+    ok(Error == ERROR_SUCCESS, "Error resetting new registry value back (%ld).\n", GetLastError());
+
+    /* Retrieve gethostname() */
+    hnError = gethostname(hostbuffer, sizeof(hostbuffer));
+    ok(!hnError, "Winsock gethostname() Error is '%d'.\n", WSAGetLastError());
+
+    /* Display results */
+    if (!hnError)
+        printf("Winsock gethostname() is '%s'.\n", hostbuffer);
+
+    pos = strcmp(szHostNameOld, hostbuffer);
+    printf("The test results were '%s'.\n", pos==0 ? "good" : "bad");
+    ok(pos == 0, "szHostNameOld '%s' should be hostbuffer '%s'.\n", szHostNameOld, hostbuffer);
+
+Cleanup:
+    iResult = WSACleanup();
+    ok(iResult == 0, "WSACleanup error occurred ending Winsock");
+
+    Error = RegCloseKey(hKeyHN);
+    ok(Error == ERROR_SUCCESS, "Error closing registry key (%ld).\n", GetLastError());
+
+    return;
+}
index 8e33e8d..acf4fea 100644 (file)
@@ -6,6 +6,7 @@
 extern void func_bind(void);
 extern void func_close(void);
 extern void func_getaddrinfo(void);
 extern void func_bind(void);
 extern void func_close(void);
 extern void func_getaddrinfo(void);
+extern void func_gethostname(void);
 extern void func_getnameinfo(void);
 extern void func_getservbyname(void);
 extern void func_getservbyport(void);
 extern void func_getnameinfo(void);
 extern void func_getservbyname(void);
 extern void func_getservbyport(void);
@@ -25,6 +26,7 @@ const struct test winetest_testlist[] =
     { "bind", func_bind },
     { "close", func_close },
     { "getaddrinfo", func_getaddrinfo },
     { "bind", func_bind },
     { "close", func_close },
     { "getaddrinfo", func_getaddrinfo },
+    { "gethostname", func_gethostname },
     { "getnameinfo", func_getnameinfo },
     { "getservbyname", func_getservbyname },
     { "getservbyport", func_getservbyport },
     { "getnameinfo", func_getnameinfo },
     { "getservbyname", func_getservbyname },
     { "getservbyport", func_getservbyport },