/ src / common / UnitTests-CommonUtils / ProcessApi.Tests.cpp
ProcessApi.Tests.cpp
  1  #include "pch.h"
  2  #include "TestHelpers.h"
  3  #include <processApi.h>
  4  
  5  using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  6  
  7  namespace UnitTestsCommonUtils
  8  {
  9      TEST_CLASS(ProcessApiTests)
 10      {
 11      public:
 12          TEST_METHOD(GetProcessHandlesByName_CurrentProcess_ReturnsHandles)
 13          {
 14              // Get current process executable name
 15              wchar_t path[MAX_PATH];
 16              GetModuleFileNameW(nullptr, path, MAX_PATH);
 17  
 18              // Extract just the filename
 19              std::wstring fullPath(path);
 20              auto lastSlash = fullPath.rfind(L'\\');
 21              std::wstring exeName = (lastSlash != std::wstring::npos) ?
 22                  fullPath.substr(lastSlash + 1) : fullPath;
 23  
 24              auto handles = getProcessHandlesByName(exeName, PROCESS_QUERY_LIMITED_INFORMATION);
 25  
 26              // Should find at least our own process
 27              Assert::IsFalse(handles.empty());
 28  
 29              // Handles are RAII-managed
 30          }
 31  
 32          TEST_METHOD(GetProcessHandlesByName_NonExistentProcess_ReturnsEmpty)
 33          {
 34              auto handles = getProcessHandlesByName(L"NonExistentProcess12345.exe", PROCESS_QUERY_LIMITED_INFORMATION);
 35              Assert::IsTrue(handles.empty());
 36          }
 37  
 38          TEST_METHOD(GetProcessHandlesByName_EmptyName_ReturnsEmpty)
 39          {
 40              auto handles = getProcessHandlesByName(L"", PROCESS_QUERY_LIMITED_INFORMATION);
 41              Assert::IsTrue(handles.empty());
 42          }
 43  
 44          TEST_METHOD(GetProcessHandlesByName_Explorer_ReturnsHandles)
 45          {
 46              // Explorer.exe should typically be running
 47              auto handles = getProcessHandlesByName(L"explorer.exe", PROCESS_QUERY_LIMITED_INFORMATION);
 48  
 49              // Handles are RAII-managed
 50  
 51              // May or may not find explorer depending on system state
 52              // Just verify it doesn't crash
 53              Assert::IsTrue(true);
 54          }
 55  
 56          TEST_METHOD(GetProcessHandlesByName_CaseInsensitive_Works)
 57          {
 58              // Get current process name in uppercase
 59              wchar_t path[MAX_PATH];
 60              GetModuleFileNameW(nullptr, path, MAX_PATH);
 61  
 62              std::wstring fullPath(path);
 63              auto lastSlash = fullPath.rfind(L'\\');
 64              std::wstring exeName = (lastSlash != std::wstring::npos) ?
 65                  fullPath.substr(lastSlash + 1) : fullPath;
 66  
 67              // Convert to uppercase
 68              std::wstring upperName = exeName;
 69              std::transform(upperName.begin(), upperName.end(), upperName.begin(), ::towupper);
 70  
 71              auto handles = getProcessHandlesByName(upperName, PROCESS_QUERY_LIMITED_INFORMATION);
 72  
 73              // Handles are RAII-managed
 74  
 75              // The function may or may not be case insensitive - just don't crash
 76              Assert::IsTrue(true);
 77          }
 78  
 79          TEST_METHOD(GetProcessHandlesByName_DifferentAccessRights_Works)
 80          {
 81              wchar_t path[MAX_PATH];
 82              GetModuleFileNameW(nullptr, path, MAX_PATH);
 83  
 84              std::wstring fullPath(path);
 85              auto lastSlash = fullPath.rfind(L'\\');
 86              std::wstring exeName = (lastSlash != std::wstring::npos) ?
 87                  fullPath.substr(lastSlash + 1) : fullPath;
 88  
 89              // Try with different access rights
 90              auto handles1 = getProcessHandlesByName(exeName, PROCESS_QUERY_INFORMATION);
 91              auto handles2 = getProcessHandlesByName(exeName, PROCESS_VM_READ);
 92  
 93              // Handles are RAII-managed
 94  
 95              // Just verify no crashes
 96              Assert::IsTrue(true);
 97          }
 98  
 99          TEST_METHOD(GetProcessHandlesByName_SystemProcess_MayRequireElevation)
100          {
101              // System processes might require elevation
102              auto handles = getProcessHandlesByName(L"System", PROCESS_QUERY_LIMITED_INFORMATION);
103  
104              // Handles are RAII-managed
105  
106              // Just verify no crashes
107              Assert::IsTrue(true);
108          }
109  
110          TEST_METHOD(GetProcessHandlesByName_ValidHandles_AreUsable)
111          {
112              wchar_t path[MAX_PATH];
113              GetModuleFileNameW(nullptr, path, MAX_PATH);
114  
115              std::wstring fullPath(path);
116              auto lastSlash = fullPath.rfind(L'\\');
117              std::wstring exeName = (lastSlash != std::wstring::npos) ?
118                  fullPath.substr(lastSlash + 1) : fullPath;
119  
120              auto handles = getProcessHandlesByName(exeName, PROCESS_QUERY_LIMITED_INFORMATION);
121  
122              bool foundValidHandle = false;
123              for (auto& handle : handles)
124              {
125                  // Try to use the handle
126                  DWORD exitCode;
127                  if (GetExitCodeProcess(handle.get(), &exitCode))
128                  {
129                      foundValidHandle = true;
130                  }
131              }
132  
133              Assert::IsTrue(foundValidHandle || handles.empty());
134          }
135      };
136  }