PathVariable.cpp (5326B)
1 #include "pch.h" 2 #include "TestCommon.h" 3 #include <AppInstallerRuntime.h> 4 #include <Resources.h> 5 #include <winget/PathVariable.h> 6 #include <winget/Filesystem.h> 7 8 using namespace AppInstaller::Manifest; 9 using namespace AppInstaller::Registry::Environment; 10 11 TEST_CASE("PathVariable_EnforceReadOnly", "[pathVariable]") 12 { 13 auto pathVariable = PathVariable(ScopeEnum::User, true); 14 REQUIRE_THROWS_HR(pathVariable.Append("testString"), E_ACCESSDENIED); 15 REQUIRE_THROWS_HR(pathVariable.Remove("testString"), E_ACCESSDENIED); 16 } 17 18 TEST_CASE("PathVariable_Append_NoSemiColon", "[pathVariable]") 19 { 20 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 21 { 22 WARN("Test requires admin privilege. Skipped."); 23 return; 24 } 25 26 auto pathVariable = PathVariable(ScopeEnum::User); 27 std::filesystem::path testPath{ "testString" }; 28 REQUIRE_FALSE(pathVariable.Contains(testPath)); 29 REQUIRE(pathVariable.Append(testPath)); 30 REQUIRE(pathVariable.Contains(testPath)); 31 32 // Verify that the path value ends with a ';' and not include ";;" 33 std::string pathValue = pathVariable.GetPathValue(); 34 REQUIRE(pathValue.back() == ';'); 35 REQUIRE(pathValue.find(";;") == std::string::npos); 36 37 REQUIRE(pathVariable.Remove(testPath)); 38 REQUIRE_FALSE(pathVariable.Contains(testPath)); 39 } 40 41 TEST_CASE("PathVariable_Append_WithSemicolon", "[pathVariable]") 42 { 43 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 44 { 45 WARN("Test requires admin privilege. Skipped."); 46 return; 47 } 48 49 auto pathVariable = PathVariable(ScopeEnum::User); 50 std::filesystem::path testPath{ "testString;" }; 51 REQUIRE_FALSE(pathVariable.Contains(testPath)); 52 REQUIRE(pathVariable.Append(testPath)); 53 REQUIRE(pathVariable.Contains(testPath)); 54 55 // Verify that the path value ends with a ';' and does not include ";;" 56 std::string pathValue = pathVariable.GetPathValue(); 57 REQUIRE(pathValue.back() == ';'); 58 REQUIRE(pathValue.find(";;") == std::string::npos); 59 60 REQUIRE(pathVariable.Remove(testPath)); 61 REQUIRE_FALSE(pathVariable.Contains(testPath)); 62 } 63 64 std::wstring GetCurrentProcessPathVariable() 65 { 66 size_t requiredSize; 67 _wgetenv_s(&requiredSize, nullptr, 0, L"PATH"); 68 69 if (requiredSize > 0) 70 { 71 auto buffer = std::make_unique<wchar_t[]>(requiredSize); 72 errno_t errorResult = _wgetenv_s(&requiredSize, buffer.get(), requiredSize, L"PATH"); 73 if (errorResult == 0) 74 { 75 return std::wstring(buffer.get()); 76 } 77 } 78 return {}; 79 } 80 81 TEST_CASE("RefreshEnvironmentVariable_User", "[pathVariable]") 82 { 83 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 84 { 85 WARN("Test requires admin privilege. Skipped."); 86 return; 87 } 88 89 std::wstring testPathEntry = L"testUserPathEntry"; 90 auto pathVariable = AppInstaller::Registry::Environment::PathVariable(ScopeEnum::User); 91 pathVariable.Append(testPathEntry); 92 93 std::wstring initialPathValue = GetCurrentProcessPathVariable(); 94 bool firstCheck = initialPathValue.find(testPathEntry) != std::string::npos; 95 96 AppInstaller::Registry::Environment::RefreshPathVariableForCurrentProcess(); 97 98 std::wstring updatedPathValue = GetCurrentProcessPathVariable(); 99 bool secondCheck = updatedPathValue.find(testPathEntry) != std::string::npos; 100 101 pathVariable.Remove(testPathEntry); 102 103 REQUIRE_FALSE(firstCheck); 104 REQUIRE(secondCheck); 105 } 106 107 TEST_CASE("RefreshEnvironmentVariable_System", "[pathVariable]") 108 { 109 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 110 { 111 WARN("Test requires admin privilege. Skipped."); 112 return; 113 } 114 115 std::wstring testPathEntry = L"testSystemPathEntry"; 116 auto pathVariable = AppInstaller::Registry::Environment::PathVariable(ScopeEnum::Machine); 117 pathVariable.Append(testPathEntry); 118 119 std::wstring initialPathValue = GetCurrentProcessPathVariable(); 120 bool firstCheck = initialPathValue.find(testPathEntry) != std::string::npos; 121 122 AppInstaller::Registry::Environment::RefreshPathVariableForCurrentProcess(); 123 124 std::wstring updatedPathValue = GetCurrentProcessPathVariable(); 125 bool secondCheck = updatedPathValue.find(testPathEntry) != std::string::npos; 126 127 pathVariable.Remove(testPathEntry); 128 129 REQUIRE_FALSE(firstCheck); 130 REQUIRE(secondCheck); 131 } 132 133 TEST_CASE("VerifyPathRefreshExpandsValues", "[pathVariable]") 134 { 135 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 136 { 137 WARN("Test requires admin privilege. Skipped."); 138 return; 139 } 140 141 std::filesystem::path testEntry{ "%USERPROFILE%\\testPath" }; 142 auto pathVariable = AppInstaller::Registry::Environment::PathVariable(ScopeEnum::User); 143 pathVariable.Append(testEntry); 144 145 std::wstring initialPathValue = GetCurrentProcessPathVariable(); 146 bool firstCheck = initialPathValue.find(testEntry) != std::string::npos; 147 148 AppInstaller::Registry::Environment::RefreshPathVariableForCurrentProcess(); 149 150 // %USERPROFILE% should be replaced with the actual path. 151 std::wstring updatedPathValue = GetCurrentProcessPathVariable(); 152 std::wstring expandedTestPath = AppInstaller::Filesystem::GetExpandedPath(testEntry.u8string()); 153 bool secondCheck = updatedPathValue.find(expandedTestPath) != std::string::npos; 154 155 pathVariable.Remove(testEntry); 156 157 REQUIRE_FALSE(firstCheck); 158 REQUIRE(secondCheck); 159 }