From 7f642e51670bc38a4ef782a363936850bc2b0ba9 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 22 Apr 2021 06:38:23 -0700 Subject: Move dutil into libs/dutil --- src/test/DUtilUnitTest/MonUtilTest.cpp | 487 --------------------------------- 1 file changed, 487 deletions(-) delete mode 100644 src/test/DUtilUnitTest/MonUtilTest.cpp (limited to 'src/test/DUtilUnitTest/MonUtilTest.cpp') diff --git a/src/test/DUtilUnitTest/MonUtilTest.cpp b/src/test/DUtilUnitTest/MonUtilTest.cpp deleted file mode 100644 index 273f2eb6..00000000 --- a/src/test/DUtilUnitTest/MonUtilTest.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -#include "precomp.h" -#undef RemoveDirectory - -using namespace System; -using namespace System::Collections::Generic; -using namespace System::Runtime::InteropServices; -using namespace Xunit; -using namespace WixBuildTools::TestSupport; - -namespace DutilTests -{ - const int PREWAIT = 20; - const int POSTWAIT = 480; - const int FULLWAIT = 500; - const int SILENCEPERIOD = 100; - - struct RegKey - { - HRESULT hr; - HKEY hkRoot; - LPCWSTR wzSubKey; - REG_KEY_BITNESS kbKeyBitness; - BOOL fRecursive; - }; - struct Directory - { - HRESULT hr; - LPCWSTR wzPath; - BOOL fRecursive; - }; - struct Results - { - RegKey *rgRegKeys; - DWORD cRegKeys; - Directory *rgDirectories; - DWORD cDirectories; - }; - - public delegate void MonGeneralDelegate(HRESULT, LPVOID); - - public delegate void MonDriveStatusDelegate(WCHAR, BOOL, LPVOID); - - public delegate void MonDirectoryDelegate(HRESULT, LPCWSTR, BOOL, LPVOID, LPVOID); - - public delegate void MonRegKeyDelegate(HRESULT, HKEY, LPCWSTR, REG_KEY_BITNESS, BOOL, LPVOID, LPVOID); - - static void MonGeneral( - __in HRESULT /*hrResult*/, - __in_opt LPVOID /*pvContext*/ - ) - { - Assert::True(false); - } - - static void MonDriveStatus( - __in WCHAR /*chDrive*/, - __in BOOL /*fArriving*/, - __in_opt LPVOID /*pvContext*/ - ) - { - } - - static void MonDirectory( - __in HRESULT hrResult, - __in_z LPCWSTR wzPath, - __in_z BOOL fRecursive, - __in_opt LPVOID pvContext, - __in_opt LPVOID pvDirectoryContext - ) - { - Assert::Equal(S_OK, hrResult); - Assert::Equal(0, reinterpret_cast(pvDirectoryContext)); - - HRESULT hr = S_OK; - Results *pResults = reinterpret_cast(pvContext); - - hr = MemEnsureArraySize(reinterpret_cast(&pResults->rgDirectories), pResults->cDirectories + 1, sizeof(Directory), 5); - NativeAssert::ValidReturnCode(hr, S_OK); - ++pResults->cDirectories; - - pResults->rgDirectories[pResults->cDirectories - 1].hr = hrResult; - pResults->rgDirectories[pResults->cDirectories - 1].wzPath = wzPath; - pResults->rgDirectories[pResults->cDirectories - 1].fRecursive = fRecursive; - } - - static void MonRegKey( - __in HRESULT hrResult, - __in HKEY hkRoot, - __in_z LPCWSTR wzSubKey, - __in REG_KEY_BITNESS kbKeyBitness, - __in_z BOOL fRecursive, - __in_opt LPVOID pvContext, - __in_opt LPVOID pvRegKeyContext - ) - { - Assert::Equal(S_OK, hrResult); - Assert::Equal(0, reinterpret_cast(pvRegKeyContext)); - - HRESULT hr = S_OK; - Results *pResults = reinterpret_cast(pvContext); - - hr = MemEnsureArraySize(reinterpret_cast(&pResults->rgRegKeys), pResults->cRegKeys + 1, sizeof(RegKey), 5); - NativeAssert::ValidReturnCode(hr, S_OK); - ++pResults->cRegKeys; - - pResults->rgRegKeys[pResults->cRegKeys - 1].hr = hrResult; - pResults->rgRegKeys[pResults->cRegKeys - 1].hkRoot = hkRoot; - pResults->rgRegKeys[pResults->cRegKeys - 1].wzSubKey = wzSubKey; - pResults->rgRegKeys[pResults->cRegKeys - 1].kbKeyBitness = kbKeyBitness; - pResults->rgRegKeys[pResults->cRegKeys - 1].fRecursive = fRecursive; - } - - public ref class MonUtil - { - public: - void ClearResults(Results *pResults) - { - ReleaseNullMem(pResults->rgDirectories); - pResults->cDirectories = 0; - ReleaseNullMem(pResults->rgRegKeys); - pResults->cRegKeys = 0; - } - - void RemoveDirectory(LPCWSTR wzPath) - { - DWORD dwRetryCount = 0; - const DWORD c_dwMaxRetryCount = 100; - const DWORD c_dwRetryInterval = 50; - - HRESULT hr = DirEnsureDelete(wzPath, TRUE, TRUE); - - // Monitoring a directory opens a handle to that directory, which means delete requests for that directory will succeed - // (and deletion will be "pending" until our monitor handle is closed) - // but deletion of the directory containing that directory cannot complete until the handle is closed. This means DirEnsureDelete() - // can sometimes encounter HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) failures, which just means it needs to retry a bit later - // (after the waiter thread wakes up, it will release the handle) - while (HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) == hr && c_dwMaxRetryCount > dwRetryCount) - { - ::Sleep(c_dwRetryInterval); - ++dwRetryCount; - hr = DirEnsureDelete(wzPath, TRUE, TRUE); - } - - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE, E_PATHNOTFOUND); - } - - void TestDirectory(MON_HANDLE handle, Results *pResults) - { - HRESULT hr = S_OK; - LPWSTR sczShallowPath = NULL; - LPWSTR sczParentPath = NULL; - LPWSTR sczDeepPath = NULL; - LPWSTR sczChildPath = NULL; - LPWSTR sczChildFilePath = NULL; - - try - { - hr = PathExpand(&sczShallowPath, L"%TEMP%\\MonUtilTest\\", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = PathExpand(&sczParentPath, L"%TEMP%\\MonUtilTest\\sub\\folder\\that\\might\\not\\", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = PathExpand(&sczDeepPath, L"%TEMP%\\MonUtilTest\\sub\\folder\\that\\might\\not\\exist\\", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = PathExpand(&sczChildPath, L"%TEMP%\\MonUtilTest\\sub\\folder\\that\\might\\not\\exist\\some\\sub\\folder\\", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = PathExpand(&sczChildFilePath, L"%TEMP%\\MonUtilTest\\sub\\folder\\that\\might\\not\\exist\\some\\sub\\folder\\file.txt", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - RemoveDirectory(sczShallowPath); - - hr = MonAddDirectory(handle, sczDeepPath, TRUE, SILENCEPERIOD, NULL); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = DirEnsureExists(sczParentPath, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - // Make sure creating the parent directory does nothing, even after silence period - ::Sleep(FULLWAIT); - Assert::Equal(0, pResults->cDirectories); - - // Now create the target path, no notification until after the silence period - hr = DirEnsureExists(sczDeepPath, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ::Sleep(PREWAIT); - Assert::Equal(0, pResults->cDirectories); - - // Now after the full silence period, it should have triggered - ::Sleep(POSTWAIT); - Assert::Equal(1, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[0].hr, S_OK); - - // Now delete the directory, along with a ton of parents. This verifies MonUtil will keep watching the closest parent that still exists. - RemoveDirectory(sczShallowPath); - - ::Sleep(FULLWAIT); - Assert::Equal(2, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[1].hr, S_OK); - - // Create the parent directory again, still should be nothing even after full silence period - hr = DirEnsureExists(sczParentPath, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ::Sleep(FULLWAIT); - Assert::Equal(2, pResults->cDirectories); - - hr = DirEnsureExists(sczChildPath, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ::Sleep(PREWAIT); - Assert::Equal(2, pResults->cDirectories); - - ::Sleep(POSTWAIT); - Assert::Equal(3, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[2].hr, S_OK); - - // Write a file to a deep child subfolder, and make sure it's detected - hr = FileFromString(sczChildFilePath, 0, L"contents", FILE_ENCODING_UTF16_WITH_BOM); - NativeAssert::ValidReturnCode(hr, S_OK); - ::Sleep(PREWAIT); - Assert::Equal(3, pResults->cDirectories); - - ::Sleep(POSTWAIT); - Assert::Equal(4, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[2].hr, S_OK); - - RemoveDirectory(sczParentPath); - - ::Sleep(FULLWAIT); - Assert::Equal(5, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[3].hr, S_OK); - - // Now remove the directory from the list of things to monitor, and confirm changes are no longer tracked - hr = MonRemoveDirectory(handle, sczDeepPath, TRUE); - NativeAssert::ValidReturnCode(hr, S_OK); - ::Sleep(PREWAIT); - - hr = DirEnsureExists(sczDeepPath, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ::Sleep(FULLWAIT); - Assert::Equal(5, pResults->cDirectories); - NativeAssert::ValidReturnCode(pResults->rgDirectories[3].hr, S_OK); - - // Finally, add it back so we can test multiple things to monitor at once - hr = MonAddDirectory(handle, sczDeepPath, TRUE, SILENCEPERIOD, NULL); - NativeAssert::ValidReturnCode(hr, S_OK); - } - finally - { - ReleaseStr(sczShallowPath); - ReleaseStr(sczDeepPath); - ReleaseStr(sczParentPath); - } - } - - void TestRegKey(MON_HANDLE handle, Results *pResults) - { - HRESULT hr = S_OK; - LPCWSTR wzShallowRegKey = L"Software\\MonUtilTest\\"; - LPCWSTR wzParentRegKey = L"Software\\MonUtilTest\\sub\\folder\\that\\might\\not\\"; - LPCWSTR wzDeepRegKey = L"Software\\MonUtilTest\\sub\\folder\\that\\might\\not\\exist\\"; - LPCWSTR wzChildRegKey = L"Software\\MonUtilTest\\sub\\folder\\that\\might\\not\\exist\\some\\sub\\folder\\"; - HKEY hk = NULL; - - try - { - hr = RegDelete(HKEY_CURRENT_USER, wzShallowRegKey, REG_KEY_32BIT, TRUE); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE, E_PATHNOTFOUND); - - hr = MonAddRegKey(handle, HKEY_CURRENT_USER, wzDeepRegKey, REG_KEY_DEFAULT, TRUE, SILENCEPERIOD, NULL); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = RegCreate(HKEY_CURRENT_USER, wzParentRegKey, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk); - ReleaseRegKey(hk); - // Make sure creating the parent key does nothing, even after silence period - ::Sleep(FULLWAIT); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - Assert::Equal(0, pResults->cRegKeys); - - // Now create the target path, no notification until after the silence period - hr = RegCreate(HKEY_CURRENT_USER, wzDeepRegKey, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ReleaseRegKey(hk); - ::Sleep(PREWAIT); - Assert::Equal(0, pResults->cRegKeys); - - // Now after the full silence period, it should have triggered - ::Sleep(POSTWAIT); - Assert::Equal(1, pResults->cRegKeys); - NativeAssert::ValidReturnCode(pResults->rgRegKeys[0].hr, S_OK); - - // Now delete the directory, along with a ton of parents. This verifies MonUtil will keep watching the closest parent that still exists. - hr = RegDelete(HKEY_CURRENT_USER, wzShallowRegKey, REG_KEY_32BIT, TRUE); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE, E_PATHNOTFOUND); - ::Sleep(PREWAIT); - Assert::Equal(1, pResults->cRegKeys); - - ::Sleep(FULLWAIT); - Assert::Equal(2, pResults->cRegKeys); - NativeAssert::ValidReturnCode(pResults->rgRegKeys[1].hr, S_OK); - - // Create the parent directory again, still should be nothing even after full silence period - hr = RegCreate(HKEY_CURRENT_USER, wzParentRegKey, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ReleaseRegKey(hk); - ::Sleep(FULLWAIT); - Assert::Equal(2, pResults->cRegKeys); - - hr = RegCreate(HKEY_CURRENT_USER, wzChildRegKey, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ::Sleep(PREWAIT); - Assert::Equal(2, pResults->cRegKeys); - - ::Sleep(FULLWAIT); - Assert::Equal(3, pResults->cRegKeys); - NativeAssert::ValidReturnCode(pResults->rgRegKeys[2].hr, S_OK); - - // Write a registry value to some deep child subkey, and make sure it's detected - hr = RegWriteString(hk, L"valuename", L"testvalue"); - NativeAssert::ValidReturnCode(hr, S_OK); - ReleaseRegKey(hk); - ::Sleep(PREWAIT); - Assert::Equal(3, pResults->cRegKeys); - - ::Sleep(FULLWAIT); - Assert::Equal(4, pResults->cRegKeys); - NativeAssert::ValidReturnCode(pResults->rgRegKeys[2].hr, S_OK); - - hr = RegDelete(HKEY_CURRENT_USER, wzDeepRegKey, REG_KEY_32BIT, TRUE); - NativeAssert::ValidReturnCode(hr, S_OK); - - ::Sleep(FULLWAIT); - Assert::Equal(5, pResults->cRegKeys); - - // Now remove the regkey from the list of things to monitor, and confirm changes are no longer tracked - hr = MonRemoveRegKey(handle, HKEY_CURRENT_USER, wzDeepRegKey, REG_KEY_DEFAULT, TRUE); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = RegCreate(HKEY_CURRENT_USER, wzDeepRegKey, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - ReleaseRegKey(hk); - ::Sleep(FULLWAIT); - Assert::Equal(5, pResults->cRegKeys); - } - finally - { - ReleaseRegKey(hk); - } - } - - void TestMoreThan64(MON_HANDLE handle, Results *pResults) - { - HRESULT hr = S_OK; - LPWSTR sczBaseDir = NULL; - LPWSTR sczDir = NULL; - LPWSTR sczFile = NULL; - - try - { - hr = PathExpand(&sczBaseDir, L"%TEMP%\\ScalabilityTest\\", PATH_EXPAND_ENVIRONMENT); - NativeAssert::ValidReturnCode(hr, S_OK); - - for (DWORD i = 0; i < 200; ++i) - { - hr = StrAllocFormatted(&sczDir, L"%ls%u\\", sczBaseDir, i); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = DirEnsureExists(sczDir, NULL); - NativeAssert::ValidReturnCode(hr, S_OK, S_FALSE); - - hr = MonAddDirectory(handle, sczDir, FALSE, SILENCEPERIOD, NULL); - NativeAssert::ValidReturnCode(hr, S_OK); - } - - hr = PathConcat(sczDir, L"file.txt", &sczFile); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = FileFromString(sczFile, 0, L"contents", FILE_ENCODING_UTF16_WITH_BOM); - NativeAssert::ValidReturnCode(hr, S_OK); - - ::Sleep(FULLWAIT); - Assert::Equal(1, pResults->cDirectories); - - for (DWORD i = 0; i < 199; ++i) - { - hr = StrAllocFormatted(&sczDir, L"%ls%u\\", sczBaseDir, i); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = MonRemoveDirectory(handle, sczDir, FALSE); - NativeAssert::ValidReturnCode(hr, S_OK); - } - ::Sleep(FULLWAIT); - - hr = FileFromString(sczFile, 0, L"contents2", FILE_ENCODING_UTF16_WITH_BOM); - NativeAssert::ValidReturnCode(hr, S_OK); - - ::Sleep(FULLWAIT); - Assert::Equal(2, pResults->cDirectories); - - for (DWORD i = 0; i < 199; ++i) - { - hr = StrAllocFormatted(&sczDir, L"%ls%u\\", sczBaseDir, i); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = MonAddDirectory(handle, sczDir, FALSE, SILENCEPERIOD, NULL); - NativeAssert::ValidReturnCode(hr, S_OK); - } - ::Sleep(FULLWAIT); - - hr = FileFromString(sczFile, 0, L"contents3", FILE_ENCODING_UTF16_WITH_BOM); - NativeAssert::ValidReturnCode(hr, S_OK); - - ::Sleep(FULLWAIT); - Assert::Equal(3, pResults->cDirectories); - } - finally - { - ReleaseStr(sczBaseDir); - ReleaseStr(sczDir); - ReleaseStr(sczFile); - } - } - - [Fact(Skip = "Test demonstrates failure")] - void MonUtilTest() - { - HRESULT hr = S_OK; - MON_HANDLE handle = NULL; - List^ gcHandles = gcnew List(); - Results *pResults = (Results *)MemAlloc(sizeof(Results), TRUE); - Assert::True(NULL != pResults); - - try - { - // These ensure the function pointers we send point to this thread's appdomain, which helps with assembly binding when running tests within msbuild - MonGeneralDelegate^ fpMonGeneral = gcnew MonGeneralDelegate(MonGeneral); - GCHandle gchMonGeneral = GCHandle::Alloc(fpMonGeneral); - gcHandles->Add(gchMonGeneral); - IntPtr ipMonGeneral = Marshal::GetFunctionPointerForDelegate(fpMonGeneral); - - MonDriveStatusDelegate^ fpMonDriveStatus = gcnew MonDriveStatusDelegate(MonDriveStatus); - GCHandle gchMonDriveStatus = GCHandle::Alloc(fpMonDriveStatus); - gcHandles->Add(gchMonDriveStatus); - IntPtr ipMonDriveStatus = Marshal::GetFunctionPointerForDelegate(fpMonDriveStatus); - - MonDirectoryDelegate^ fpMonDirectory = gcnew MonDirectoryDelegate(MonDirectory); - GCHandle gchMonDirectory = GCHandle::Alloc(fpMonDirectory); - gcHandles->Add(gchMonDirectory); - IntPtr ipMonDirectory = Marshal::GetFunctionPointerForDelegate(fpMonDirectory); - - MonRegKeyDelegate^ fpMonRegKey = gcnew MonRegKeyDelegate(MonRegKey); - GCHandle gchMonRegKey = GCHandle::Alloc(fpMonRegKey); - gcHandles->Add(gchMonRegKey); - IntPtr ipMonRegKey = Marshal::GetFunctionPointerForDelegate(fpMonRegKey); - - // "Silence period" is 100 ms - hr = MonCreate(&handle, static_cast(ipMonGeneral.ToPointer()), static_cast(ipMonDriveStatus.ToPointer()), static_cast(ipMonDirectory.ToPointer()), static_cast(ipMonRegKey.ToPointer()), pResults); - NativeAssert::ValidReturnCode(hr, S_OK); - - hr = RegInitialize(); - NativeAssert::ValidReturnCode(hr, S_OK); - - TestDirectory(handle, pResults); - ClearResults(pResults); - TestRegKey(handle, pResults); - ClearResults(pResults); - TestMoreThan64(handle, pResults); - ClearResults(pResults); - } - finally - { - ReleaseMon(handle); - - for each (GCHandle gcHandle in gcHandles) - { - gcHandle.Free(); - } - - ReleaseMem(pResults->rgDirectories); - ReleaseMem(pResults->rgRegKeys); - ReleaseMem(pResults); - } - } - }; -} -- cgit v1.2.3-55-g6feb