/ src / common / UnitTests-CommonUtils / Elevation.Tests.cpp
Elevation.Tests.cpp
  1  #include "pch.h"
  2  #include "TestHelpers.h"
  3  #include <elevation.h>
  4  
  5  using namespace Microsoft::VisualStudio::CppUnitTestFramework;
  6  
  7  namespace UnitTestsCommonUtils
  8  {
  9      TEST_CLASS(ElevationTests)
 10      {
 11      public:
 12          // is_process_elevated tests
 13          TEST_METHOD(IsProcessElevated_ReturnsBoolean)
 14          {
 15              bool result = is_process_elevated(false);
 16              Assert::IsTrue(result == true || result == false);
 17          }
 18  
 19          TEST_METHOD(IsProcessElevated_CachedValue_ReturnsSameResult)
 20          {
 21              bool result1 = is_process_elevated(true);
 22              bool result2 = is_process_elevated(true);
 23  
 24              // Cached value should be consistent
 25              Assert::AreEqual(result1, result2);
 26          }
 27  
 28          TEST_METHOD(IsProcessElevated_UncachedValue_ReturnsBoolean)
 29          {
 30              bool result = is_process_elevated(false);
 31              Assert::IsTrue(result == true || result == false);
 32          }
 33  
 34          TEST_METHOD(IsProcessElevated_CachedAndUncached_AreConsistent)
 35          {
 36              // Both should return the same value for the same process
 37              bool cached = is_process_elevated(true);
 38              bool uncached = is_process_elevated(false);
 39  
 40              Assert::AreEqual(cached, uncached);
 41          }
 42  
 43          // check_user_is_admin tests
 44          TEST_METHOD(CheckUserIsAdmin_ReturnsBoolean)
 45          {
 46              bool result = check_user_is_admin();
 47              Assert::IsTrue(result == true || result == false);
 48          }
 49  
 50          TEST_METHOD(CheckUserIsAdmin_ConsistentResults)
 51          {
 52              bool result1 = check_user_is_admin();
 53              bool result2 = check_user_is_admin();
 54              bool result3 = check_user_is_admin();
 55  
 56              Assert::AreEqual(result1, result2);
 57              Assert::AreEqual(result2, result3);
 58          }
 59  
 60          // Relationship between elevation and admin
 61          TEST_METHOD(ElevationAndAdmin_Relationship)
 62          {
 63              bool elevated = is_process_elevated(false);
 64              bool admin = check_user_is_admin();
 65              (void)admin;
 66  
 67              // If elevated, user should typically be admin
 68              // But user can be admin without process being elevated
 69              if (elevated)
 70              {
 71                  // Elevated process usually means admin user
 72                  // (though there are edge cases)
 73              }
 74              // Just verify both functions return without crashing
 75              Assert::IsTrue(true);
 76          }
 77  
 78          // IsProcessOfWindowElevated tests
 79          TEST_METHOD(IsProcessOfWindowElevated_DesktopWindow_ReturnsBoolean)
 80          {
 81              HWND desktop = GetDesktopWindow();
 82              if (desktop)
 83              {
 84                  bool result = IsProcessOfWindowElevated(desktop);
 85                  Assert::IsTrue(result == true || result == false);
 86              }
 87              Assert::IsTrue(true);
 88          }
 89  
 90          TEST_METHOD(IsProcessOfWindowElevated_InvalidHwnd_DoesNotCrash)
 91          {
 92              bool result = IsProcessOfWindowElevated(nullptr);
 93              // Should handle null HWND gracefully
 94              Assert::IsTrue(result == true || result == false);
 95          }
 96  
 97          // ProcessInfo struct tests
 98          TEST_METHOD(ProcessInfo_DefaultConstruction)
 99          {
100              ProcessInfo info{};
101              Assert::AreEqual(static_cast<DWORD>(0), info.processID);
102          }
103  
104          // Thread safety tests
105          TEST_METHOD(IsProcessElevated_ThreadSafe)
106          {
107              std::vector<std::thread> threads;
108              std::atomic<int> successCount{ 0 };
109  
110              for (int i = 0; i < 10; ++i)
111              {
112                  threads.emplace_back([&successCount]() {
113                      for (int j = 0; j < 10; ++j)
114                      {
115                          is_process_elevated(j % 2 == 0);
116                          successCount++;
117                      }
118                  });
119              }
120  
121              for (auto& t : threads)
122              {
123                  t.join();
124              }
125  
126              Assert::AreEqual(100, successCount.load());
127          }
128  
129          // Performance of cached value
130          TEST_METHOD(IsProcessElevated_CachedPerformance)
131          {
132              auto start = std::chrono::high_resolution_clock::now();
133  
134              for (int i = 0; i < 10000; ++i)
135              {
136                  is_process_elevated(true);
137              }
138  
139              auto end = std::chrono::high_resolution_clock::now();
140              auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
141  
142              // Cached calls should be very fast
143              Assert::IsTrue(duration.count() < 1000);
144          }
145      };
146  }