HDropIterator.Tests.cpp
1 #include "pch.h" 2 #include "TestHelpers.h" 3 #include <HDropIterator.h> 4 #include <shlobj.h> 5 6 using namespace Microsoft::VisualStudio::CppUnitTestFramework; 7 8 namespace UnitTestsCommonUtils 9 { 10 TEST_CLASS(HDropIteratorTests) 11 { 12 public: 13 // Helper to create a test HDROP structure 14 static HGLOBAL CreateTestHDrop(const std::vector<std::wstring>& files) 15 { 16 // Calculate required size 17 size_t size = sizeof(DROPFILES); 18 for (const auto& file : files) 19 { 20 size += (file.length() + 1) * sizeof(wchar_t); 21 } 22 size += sizeof(wchar_t); // Double null terminator 23 24 HGLOBAL hGlobal = GlobalAlloc(GHND, size); 25 if (!hGlobal) return nullptr; 26 27 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 28 if (!pDropFiles) 29 { 30 GlobalFree(hGlobal); 31 return nullptr; 32 } 33 34 pDropFiles->pFiles = sizeof(DROPFILES); 35 pDropFiles->fWide = TRUE; 36 37 wchar_t* pData = reinterpret_cast<wchar_t*>(reinterpret_cast<BYTE*>(pDropFiles) + sizeof(DROPFILES)); 38 for (const auto& file : files) 39 { 40 wcscpy_s(pData, file.length() + 1, file.c_str()); 41 pData += file.length() + 1; 42 } 43 *pData = L'\0'; // Double null terminator 44 45 GlobalUnlock(hGlobal); 46 return hGlobal; 47 } 48 49 TEST_METHOD(HDropIterator_EmptyDrop_IsDoneImmediately) 50 { 51 HGLOBAL hGlobal = CreateTestHDrop({}); 52 if (!hGlobal) 53 { 54 Assert::IsTrue(true); // Skip if allocation failed 55 return; 56 } 57 58 STGMEDIUM medium = {}; 59 medium.tymed = TYMED_HGLOBAL; 60 medium.hGlobal = hGlobal; 61 62 // Without a proper IDataObject, we can't fully test 63 // Just verify the class can be instantiated conceptually 64 GlobalFree(hGlobal); 65 Assert::IsTrue(true); 66 } 67 68 TEST_METHOD(HDropIterator_Iteration_Conceptual) 69 { 70 // This test verifies the concept of iteration 71 // Full integration testing requires a proper IDataObject 72 73 std::vector<std::wstring> testFiles = { 74 L"C:\\test\\file1.txt", 75 L"C:\\test\\file2.txt", 76 L"C:\\test\\file3.txt" 77 }; 78 79 HGLOBAL hGlobal = CreateTestHDrop(testFiles); 80 if (!hGlobal) 81 { 82 Assert::IsTrue(true); 83 return; 84 } 85 86 // Verify we can create the HDROP structure 87 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 88 Assert::IsNotNull(pDropFiles); 89 Assert::IsTrue(pDropFiles->fWide); 90 91 GlobalUnlock(hGlobal); 92 GlobalFree(hGlobal); 93 Assert::IsTrue(true); 94 } 95 96 TEST_METHOD(HDropIterator_SingleFile_Works) 97 { 98 std::vector<std::wstring> testFiles = { L"C:\\test\\single.txt" }; 99 100 HGLOBAL hGlobal = CreateTestHDrop(testFiles); 101 if (!hGlobal) 102 { 103 Assert::IsTrue(true); 104 return; 105 } 106 107 // Verify structure 108 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 109 Assert::IsNotNull(pDropFiles); 110 111 // Read back the file name 112 wchar_t* pData = reinterpret_cast<wchar_t*>(reinterpret_cast<BYTE*>(pDropFiles) + pDropFiles->pFiles); 113 Assert::AreEqual(std::wstring(L"C:\\test\\single.txt"), std::wstring(pData)); 114 115 GlobalUnlock(hGlobal); 116 GlobalFree(hGlobal); 117 } 118 119 TEST_METHOD(HDropIterator_MultipleFiles_Structure) 120 { 121 std::vector<std::wstring> testFiles = { 122 L"C:\\file1.txt", 123 L"C:\\file2.txt", 124 L"C:\\file3.txt" 125 }; 126 127 HGLOBAL hGlobal = CreateTestHDrop(testFiles); 128 if (!hGlobal) 129 { 130 Assert::IsTrue(true); 131 return; 132 } 133 134 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 135 Assert::IsNotNull(pDropFiles); 136 137 // Count files by iterating through null-terminated strings 138 wchar_t* pData = reinterpret_cast<wchar_t*>(reinterpret_cast<BYTE*>(pDropFiles) + pDropFiles->pFiles); 139 int count = 0; 140 while (*pData) 141 { 142 count++; 143 pData += wcslen(pData) + 1; 144 } 145 146 Assert::AreEqual(3, count); 147 148 GlobalUnlock(hGlobal); 149 GlobalFree(hGlobal); 150 } 151 152 TEST_METHOD(HDropIterator_UnicodeFilenames_Work) 153 { 154 std::vector<std::wstring> testFiles = { 155 L"C:\\test\\file.txt" 156 }; 157 158 HGLOBAL hGlobal = CreateTestHDrop(testFiles); 159 if (!hGlobal) 160 { 161 Assert::IsTrue(true); 162 return; 163 } 164 165 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 166 Assert::IsTrue(pDropFiles->fWide == TRUE); 167 168 GlobalUnlock(hGlobal); 169 GlobalFree(hGlobal); 170 } 171 172 TEST_METHOD(HDropIterator_LongFilenames_Work) 173 { 174 std::wstring longPath = L"C:\\"; 175 for (int i = 0; i < 20; ++i) 176 { 177 longPath += L"LongFolderName\\"; 178 } 179 longPath += L"file.txt"; 180 181 std::vector<std::wstring> testFiles = { longPath }; 182 183 HGLOBAL hGlobal = CreateTestHDrop(testFiles); 184 if (!hGlobal) 185 { 186 Assert::IsTrue(true); 187 return; 188 } 189 190 DROPFILES* pDropFiles = static_cast<DROPFILES*>(GlobalLock(hGlobal)); 191 Assert::IsNotNull(pDropFiles); 192 193 wchar_t* pData = reinterpret_cast<wchar_t*>(reinterpret_cast<BYTE*>(pDropFiles) + pDropFiles->pFiles); 194 Assert::AreEqual(longPath, std::wstring(pData)); 195 196 GlobalUnlock(hGlobal); 197 GlobalFree(hGlobal); 198 } 199 }; 200 }