PowerRenameManagerTests.cpp
1 #include "pch.h" 2 #include <PowerRenameInterfaces.h> 3 #include <PowerRenameManager.h> 4 #include <PowerRenameItem.h> 5 #include "MockPowerRenameItem.h" 6 #include "MockPowerRenameManagerEvents.h" 7 #include "TestFileHelper.h" 8 #include "Helpers.h" 9 10 #define DEFAULT_FLAGS 0 11 12 using namespace Microsoft::VisualStudio::CppUnitTestFramework; 13 14 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 15 16 #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) 17 18 HINSTANCE g_hostHInst = HINST_THISCOMPONENT; 19 20 namespace PowerRenameManagerTests 21 { 22 TEST_CLASS (SimpleTests) 23 { 24 public: 25 struct rename_pairs 26 { 27 std::wstring originalName; 28 std::wstring newName; 29 bool isFile; 30 bool shouldRename; 31 int depth; 32 }; 33 34 void RenameHelper(_In_ rename_pairs * renamePairs, _In_ int numPairs, _In_ std::wstring searchTerm, _In_ std::wstring replaceTerm, SYSTEMTIME fileTime, _In_ DWORD flags) 35 { 36 // Create a single item (in a temp directory) and verify rename works as expected 37 CTestFileHelper testFileHelper; 38 for (int i = 0; i < numPairs; i++) 39 { 40 if (renamePairs[i].isFile) 41 { 42 Assert::IsTrue(testFileHelper.AddFile(renamePairs[i].originalName)); 43 } 44 else 45 { 46 Assert::IsTrue(testFileHelper.AddFolder(renamePairs[i].originalName)); 47 } 48 } 49 50 CComPtr<IPowerRenameManager> mgr; 51 Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); 52 CMockPowerRenameManagerEvents* mockMgrEvents = new CMockPowerRenameManagerEvents(); 53 CComPtr<IPowerRenameManagerEvents> mgrEvents; 54 Assert::IsTrue(mockMgrEvents->QueryInterface(IID_PPV_ARGS(&mgrEvents)) == S_OK); 55 DWORD cookie = 0; 56 Assert::IsTrue(mgr->Advise(mgrEvents, &cookie) == S_OK); 57 58 for (int i = 0; i < numPairs; i++) 59 { 60 CComPtr<IPowerRenameItem> item; 61 CMockPowerRenameItem::CreateInstance(testFileHelper.GetFullPath(renamePairs[i].originalName).c_str(), 62 renamePairs[i].originalName.c_str(), 63 renamePairs[i].depth, 64 !renamePairs[i].isFile, 65 fileTime, 66 &item); 67 68 int itemId = 0; 69 Assert::IsTrue(item->GetId(&itemId) == S_OK); 70 mgr->AddItem(item); 71 } 72 73 // TODO: Setup match and replace parameters 74 CComPtr<IPowerRenameRegEx> renRegEx; 75 Assert::IsTrue(mgr->GetRenameRegEx(&renRegEx) == S_OK); 76 renRegEx->PutFlags(flags); 77 renRegEx->PutSearchTerm(searchTerm.c_str()); 78 renRegEx->PutReplaceTerm(replaceTerm.c_str()); 79 80 // Perform the rename 81 bool replaceSuccess = false; 82 for (int step = 0; step < 20; step++) 83 { 84 replaceSuccess = mgr->Rename(0, true) == S_OK; 85 if (replaceSuccess) 86 { 87 break; 88 } 89 Sleep(10); 90 } 91 92 Assert::IsTrue(replaceSuccess); 93 94 std::vector<std::wstring> shouldRename = { L"not ", L"" }; 95 96 // Verify the rename occurred 97 for (int i = 0; i < numPairs; i++) 98 { 99 Assert::IsTrue(testFileHelper.PathExistsCaseSensitive(renamePairs[i].originalName) == !renamePairs[i].shouldRename, 100 (std::wstring(L"The path: [" + renamePairs[i].originalName + L"] should ") + shouldRename[!renamePairs[i].shouldRename] + L"exist.").c_str()); 101 Assert::IsTrue(testFileHelper.PathExistsCaseSensitive(renamePairs[i].newName) == renamePairs[i].shouldRename, 102 (std::wstring(L"The path: [" + renamePairs[i].newName + L"] should ") + shouldRename[renamePairs[i].shouldRename] + L"exist.").c_str()); 103 } 104 105 Assert::IsTrue(mgr->Shutdown() == S_OK); 106 107 mockMgrEvents->Release(); 108 } 109 TEST_METHOD (CreateTest) 110 { 111 CComPtr<IPowerRenameManager> mgr; 112 Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); 113 } 114 115 TEST_METHOD (CreateAndShutdownTest) 116 { 117 CComPtr<IPowerRenameManager> mgr; 118 Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); 119 Assert::IsTrue(mgr->Shutdown() == S_OK); 120 } 121 122 TEST_METHOD (AddItemTest) 123 { 124 CComPtr<IPowerRenameManager> mgr; 125 Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); 126 CComPtr<IPowerRenameItem> item; 127 CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, SYSTEMTIME{ 0 }, &item); 128 mgr->AddItem(item); 129 Assert::IsTrue(mgr->Shutdown() == S_OK); 130 } 131 132 TEST_METHOD (VerifyRenameManagerEvents) 133 { 134 CComPtr<IPowerRenameManager> mgr; 135 Assert::IsTrue(CPowerRenameManager::s_CreateInstance(&mgr) == S_OK); 136 CMockPowerRenameManagerEvents* mockMgrEvents = new CMockPowerRenameManagerEvents(); 137 CComPtr<IPowerRenameManagerEvents> mgrEvents; 138 Assert::IsTrue(mockMgrEvents->QueryInterface(IID_PPV_ARGS(&mgrEvents)) == S_OK); 139 DWORD cookie = 0; 140 Assert::IsTrue(mgr->Advise(mgrEvents, &cookie) == S_OK); 141 CComPtr<IPowerRenameItem> item; 142 CMockPowerRenameItem::CreateInstance(L"foo", L"foo", 0, false, SYSTEMTIME{ 0 }, &item); 143 int itemId = 0; 144 Assert::IsTrue(item->GetId(&itemId) == S_OK); 145 mgr->AddItem(item); 146 147 Assert::IsTrue(mgr->Shutdown() == S_OK); 148 149 mockMgrEvents->Release(); 150 } 151 152 TEST_METHOD (VerifySingleRename) 153 { 154 // Create a single item and verify rename works as expected 155 rename_pairs renamePairs[] = { 156 { L"foo.txt", L"bar.txt", true, true } 157 }; 158 159 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS); 160 } 161 162 TEST_METHOD (VerifyMultiRename) 163 { 164 // Create a single item and verify rename works as expected 165 rename_pairs renamePairs[] = { 166 { L"foo1.txt", L"bar1.txt", true, true, 0 }, 167 { L"foo2.txt", L"bar2.txt", true, true, 0 }, 168 { L"foo3.txt", L"bar3.txt", true, true, 0 }, 169 { L"foo4.txt", L"bar4.txt", true, true, 0 }, 170 { L"foo5.txt", L"bar5.txt", true, true, 0 }, 171 { L"baa.txt", L"baa_norename.txt", true, false, 0 } 172 }; 173 174 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS); 175 } 176 177 TEST_METHOD (VerifyFilesOnlyRename) 178 { 179 // Verify only files are renamed when folders match too 180 rename_pairs renamePairs[] = { 181 { L"foo.txt", L"bar.txt", true, true, 0 }, 182 { L"foo", L"foo_norename", false, false, 0 } 183 }; 184 185 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | ExcludeFolders); 186 } 187 188 TEST_METHOD (VerifyFoldersOnlyRename) 189 { 190 // Verify only folders are renamed when files match too 191 rename_pairs renamePairs[] = { 192 { L"foo.txt", L"foo_norename.txt", true, false, 0 }, 193 { L"foo", L"bar", false, true, 0 } 194 }; 195 196 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | ExcludeFiles); 197 } 198 199 TEST_METHOD (VerifyFileNameOnlyRename) 200 { 201 // Verify only file name is renamed, not extension 202 rename_pairs renamePairs[] = { 203 { L"foo.foo", L"bar.foo", true, true, 0 }, 204 { L"test.foo", L"test.foo_norename", true, false, 0 } 205 }; 206 207 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | NameOnly); 208 } 209 210 TEST_METHOD (VerifyFileExtensionOnlyRename) 211 { 212 // Verify only file extension is renamed, not name 213 rename_pairs renamePairs[] = { 214 { L"foo.foo", L"foo.bar", true, true, 0 }, 215 { L"test.foo", L"test.bar", true, true, 0 } 216 }; 217 218 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | ExtensionOnly); 219 } 220 221 TEST_METHOD (VerifySubFoldersRename) 222 { 223 // Verify subfolders do not get renamed 224 rename_pairs renamePairs[] = { 225 { L"foo1", L"bar1", false, true, 0 }, 226 { L"foo2", L"foo2_norename", false, false, 1 } 227 }; 228 229 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | ExcludeSubfolders); 230 } 231 232 TEST_METHOD (VerifyUppercaseTransform) 233 { 234 rename_pairs renamePairs[] = { 235 { L"foo", L"BAR", true, true, 0 }, 236 { L"foo.test", L"BAR.TEST", true, true, 0 }, 237 { L"TEST", L"TEST_norename", true, false, 0 } 238 }; 239 240 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Uppercase); 241 } 242 243 TEST_METHOD (VerifyLowercaseTransform) 244 { 245 rename_pairs renamePairs[] = { 246 { L"Foo", L"bar", false, true, 0 }, 247 { L"Foo.teST", L"bar.test", false, true, 0 }, 248 { L"test", L"test_norename", false, false, 0 } 249 }; 250 251 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Lowercase); 252 } 253 254 TEST_METHOD (VerifyTitlecaseTransform) 255 { 256 rename_pairs renamePairs[] = { 257 { L"foo And The To", L"Bar and the To", false, true, 0 }, 258 { L"foo And The To.txt", L"Bar and the To.txt", true, true, 0 }, 259 { L"Test", L"Test_norename", false, false, 0 } 260 }; 261 262 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Titlecase); 263 } 264 265 TEST_METHOD (VerifyTitlecaseWithApostropheTransform) 266 { 267 rename_pairs renamePairs[] = { 268 { L"the foo i'll and i've you're dogs' the i'd it's i'm don't to y'all", L"The Bar I'll and I've You're Dogs' the I'd It's I'm Don't to Y'all", false, true, 0 }, 269 { L"'the 'foo' 'i'll' and i've you're dogs' the 'i'd' it's i'm don't to y'all.txt", L"'The 'Bar' 'I'll' and I've You're Dogs' the 'I'd' It's I'm Don't to Y'all.txt", true, true, 0 }, 270 { L"Test", L"Test_norename", false, false, 0 } 271 }; 272 273 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Titlecase); 274 } 275 276 TEST_METHOD (VerifyCapitalizedTransform) 277 { 278 rename_pairs renamePairs[] = { 279 { L"foo and the to", L"Bar And The To", false, true, 0 }, 280 { L"Test", L"Test_norename", false, false, 0 } 281 }; 282 283 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Capitalized); 284 } 285 286 TEST_METHOD (VerifyCapitalizedWithApostropheTransform) 287 { 288 rename_pairs renamePairs[] = { 289 { L"foo i'll and i've you're dogs' the i'd it's i'm don't to y'all", L"Bar I'll And I've You're Dogs' The I'd It's I'm Don't To Y'all", false, true, 0 }, 290 { L"'foo i'll 'and' i've you're dogs' the i'd it's i'm don't to y'all.txt", L"'Bar I'll 'And' I've You're Dogs' The I'd It's I'm Don't To Y'all.txt", true, true, 0 }, 291 { L"Test", L"Test_norename", false, false, 0 } 292 }; 293 294 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Capitalized); 295 } 296 297 TEST_METHOD (VerifyNameOnlyTransform) 298 { 299 rename_pairs renamePairs[] = { 300 { L"foo.foo", L"BAR.foo", true, true, 0 }, 301 { L"foo.txt", L"BAR.TXT", false, true, 0 }, 302 { L"TEST", L"TEST_norename", false, false, 1 } 303 }; 304 305 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Uppercase | NameOnly); 306 } 307 308 TEST_METHOD (VerifyExtensionOnlyTransform) 309 { 310 rename_pairs renamePairs[] = { 311 { L"foo.FOO", L"foo.bar", true, true, 0 }, 312 { L"bar.FOO", L"bar.FOO_norename", false, false, 0 }, 313 { L"foo.bar", L"foo.bar_norename", true, false, 0 } 314 }; 315 316 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Lowercase | ExtensionOnly); 317 } 318 319 TEST_METHOD (VerifyFileAttributesNoPadding) 320 { 321 rename_pairs renamePairs[] = { 322 { L"foo", L"bar20-7-22-15-6-42-4", true, true, 0 }, 323 }; 324 325 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar$YY-$M-$D-$h-$m-$s-$f", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS); 326 } 327 328 TEST_METHOD (VerifyFileAttributesPadding) 329 { 330 rename_pairs renamePairs[] = { 331 { L"foo", L"bar2020-07-22-15-06-42-453", true, true, 0 }, 332 }; 333 334 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar$YYYY-$MM-$DD-$hh-$mm-$ss-$fff", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS); 335 } 336 337 TEST_METHOD (VerifyFileAttributesMonthAndDayNames) 338 { 339 std::locale::global(std::locale("")); 340 SYSTEMTIME fileTime = { 2020, 1, 3, 1, 15, 6, 42, 453 }; 341 wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; 342 wchar_t result[MAX_PATH] = L"bar"; 343 wchar_t formattedDate[MAX_PATH]; 344 if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) == 0) 345 StringCchCopy(localeName, LOCALE_NAME_MAX_LENGTH, L"en_US"); 346 347 GetDateFormatEx(localeName, NULL, &fileTime, L"MMM", formattedDate, MAX_PATH, NULL); 348 formattedDate[0] = towupper(formattedDate[0]); 349 StringCchPrintf(result, MAX_PATH, TEXT("%s%s"), result, formattedDate); 350 351 GetDateFormatEx(localeName, NULL, &fileTime, L"MMMM", formattedDate, MAX_PATH, NULL); 352 formattedDate[0] = towupper(formattedDate[0]); 353 StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate); 354 355 GetDateFormatEx(localeName, NULL, &fileTime, L"ddd", formattedDate, MAX_PATH, NULL); 356 formattedDate[0] = towupper(formattedDate[0]); 357 StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate); 358 359 GetDateFormatEx(localeName, NULL, &fileTime, L"dddd", formattedDate, MAX_PATH, NULL); 360 formattedDate[0] = towupper(formattedDate[0]); 361 StringCchPrintf(result, MAX_PATH, TEXT("%s-%s"), result, formattedDate); 362 363 rename_pairs renamePairs[] = { 364 { L"foo", result, true, true, 0 }, 365 }; 366 367 RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar$MMM-$MMMM-$DDD-$DDDD", SYSTEMTIME{ 2020, 1, 3, 1, 15, 6, 42, 453 }, DEFAULT_FLAGS); 368 } 369 }; 370 }