Window.Tests.cpp
1 #include "pch.h" 2 #include "TestHelpers.h" 3 #include <window.h> 4 5 using namespace Microsoft::VisualStudio::CppUnitTestFramework; 6 7 namespace UnitTestsCommonUtils 8 { 9 TEST_CLASS(WindowTests) 10 { 11 public: 12 // is_system_window tests 13 TEST_METHOD(IsSystemWindow_DesktopWindow_ReturnsResult) 14 { 15 HWND desktop = GetDesktopWindow(); 16 Assert::IsNotNull(desktop); 17 18 // Get class name 19 char className[256] = {}; 20 GetClassNameA(desktop, className, sizeof(className)); 21 22 bool result = is_system_window(desktop, className); 23 // Just verify it doesn't crash and returns a boolean 24 Assert::IsTrue(result == true || result == false); 25 } 26 27 TEST_METHOD(IsSystemWindow_NullHwnd_ReturnsFalse) 28 { 29 auto shell = GetShellWindow(); 30 auto desktop = GetDesktopWindow(); 31 bool result = is_system_window(nullptr, "ClassName"); 32 bool expected = (shell == nullptr) || (desktop == nullptr); 33 Assert::AreEqual(expected, result); 34 } 35 36 TEST_METHOD(IsSystemWindow_InvalidHwnd_ReturnsFalse) 37 { 38 bool result = is_system_window(reinterpret_cast<HWND>(0x12345678), "ClassName"); 39 Assert::IsFalse(result); 40 } 41 42 TEST_METHOD(IsSystemWindow_EmptyClassName_DoesNotCrash) 43 { 44 HWND desktop = GetDesktopWindow(); 45 bool result = is_system_window(desktop, ""); 46 // Just verify it doesn't crash 47 Assert::IsTrue(result == true || result == false); 48 } 49 50 TEST_METHOD(IsSystemWindow_NullClassName_DoesNotCrash) 51 { 52 HWND desktop = GetDesktopWindow(); 53 bool result = is_system_window(desktop, nullptr); 54 // Should handle null className gracefully 55 Assert::IsTrue(result == true || result == false); 56 } 57 58 // GetWindowCreateParam tests 59 TEST_METHOD(GetWindowCreateParam_ValidLparam_ReturnsValue) 60 { 61 struct TestData 62 { 63 int value; 64 }; 65 66 TestData data{ 42 }; 67 CREATESTRUCT cs{}; 68 cs.lpCreateParams = &data; 69 70 auto result = GetWindowCreateParam<TestData*>(reinterpret_cast<LPARAM>(&cs)); 71 Assert::IsNotNull(result); 72 Assert::AreEqual(42, result->value); 73 } 74 75 // Window data storage tests 76 TEST_METHOD(WindowData_StoreAndRetrieve_Works) 77 { 78 // Create a simple message-only window for testing 79 WNDCLASSW wc = {}; 80 wc.lpfnWndProc = DefWindowProcW; 81 wc.hInstance = GetModuleHandleW(nullptr); 82 wc.lpszClassName = L"TestWindowClass_DataTest"; 83 RegisterClassW(&wc); 84 85 HWND hwnd = CreateWindowExW(0, L"TestWindowClass_DataTest", L"Test", 86 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, 87 GetModuleHandleW(nullptr), nullptr); 88 89 if (hwnd) 90 { 91 int value = 42; 92 int* testValue = &value; 93 StoreWindowParam(hwnd, testValue); 94 95 auto retrieved = GetWindowParam<int*>(hwnd); 96 Assert::AreEqual(testValue, retrieved); 97 98 DestroyWindow(hwnd); 99 } 100 101 UnregisterClassW(L"TestWindowClass_DataTest", GetModuleHandleW(nullptr)); 102 Assert::IsTrue(true); // Window creation might fail in test environment 103 } 104 105 // run_message_loop tests 106 TEST_METHOD(RunMessageLoop_UntilIdle_Completes) 107 { 108 // Run message loop until idle with a timeout 109 // This should complete quickly since there are no messages 110 auto start = std::chrono::steady_clock::now(); 111 112 run_message_loop(true, 100); 113 114 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( 115 std::chrono::steady_clock::now() - start); 116 117 // Should complete within reasonable time 118 Assert::IsTrue(elapsed.count() < 500); 119 } 120 121 TEST_METHOD(RunMessageLoop_WithTimeout_RespectsTimeout) 122 { 123 auto start = std::chrono::steady_clock::now(); 124 125 run_message_loop(false, 50); 126 127 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( 128 std::chrono::steady_clock::now() - start); 129 130 // Should take at least the timeout duration 131 // Allow some tolerance for timing 132 Assert::IsTrue(elapsed.count() >= 40 && elapsed.count() < 500); 133 } 134 135 TEST_METHOD(RunMessageLoop_ZeroTimeout_CompletesImmediately) 136 { 137 auto start = std::chrono::steady_clock::now(); 138 139 run_message_loop(false, 0); 140 141 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( 142 std::chrono::steady_clock::now() - start); 143 144 // Should complete very quickly 145 Assert::IsTrue(elapsed.count() < 100); 146 } 147 148 TEST_METHOD(RunMessageLoop_NoTimeout_ProcessesMessages) 149 { 150 // Post a quit message before starting the loop 151 PostQuitMessage(0); 152 153 // Should process the quit message and exit 154 run_message_loop(false, std::nullopt); 155 156 Assert::IsTrue(true); 157 } 158 }; 159 }