WindowsFeature.cpp (8706B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include "WorkflowCommon.h" 6 #include <AppInstallerRuntime.h> 7 #include <Commands/InstallCommand.h> 8 #include "TestHooks.h" 9 10 using namespace AppInstaller::CLI; 11 using namespace AppInstaller::Settings; 12 using namespace AppInstaller::Utility; 13 using namespace TestCommon; 14 15 TEST_CASE("InstallFlow_WindowsFeatureDoesNotExist", "[windowsFeature]") 16 { 17 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 18 { 19 WARN("Test requires admin privilege. Skipped."); 20 return; 21 } 22 23 TestCommon::TempFile installResultPath("TestExeInstalled.txt"); 24 TestCommon::TestUserSettings testSettings; 25 26 std::ostringstream installOutput; 27 TestContext context{ installOutput, std::cin }; 28 auto previousThreadGlobals = context.SetForCurrentThread(); 29 OverrideOpenDependencySource(context); 30 31 context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_WindowsFeatures.yaml").GetPath().u8string()); 32 33 InstallCommand install({}); 34 install.Execute(context); 35 INFO(installOutput.str()); 36 37 REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES); 38 REQUIRE(!std::filesystem::exists(installResultPath.GetPath())); 39 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::WindowsFeatureNotFound(LocIndView{ "testFeature1" })).get()) != std::string::npos); 40 41 // "badFeature" should not be displayed as the flow should terminate after failing to find the first feature. 42 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::WindowsFeatureNotFound(LocIndView{ "testFeature2" })).get()) == std::string::npos); 43 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::FailedToEnableWindowsFeatureOverrideRequired).get()) != std::string::npos); 44 } 45 46 TEST_CASE("InstallFlow_FailedToEnableWindowsFeature", "[windowsFeature]") 47 { 48 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 49 { 50 WARN("Test requires admin privilege. Skipped."); 51 return; 52 } 53 54 TestCommon::TempFile installResultPath("TestExeInstalled.txt"); 55 TestCommon::TestUserSettings testSettings; 56 57 std::ostringstream installOutput; 58 TestContext context{ installOutput, std::cin }; 59 auto previousThreadGlobals = context.SetForCurrentThread(); 60 OverrideOpenDependencySource(context); 61 62 context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_WindowsFeatures.yaml").GetPath().u8string()); 63 64 auto setDoesFeatureExistOverride = TestHook::SetDoesWindowsFeatureExistResult_Override(ERROR_SUCCESS); 65 auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(0xc0040001); // DISMAPI_E_DISMAPI_NOT_INITIALIZED 66 67 InstallCommand install({}); 68 install.Execute(context); 69 INFO(installOutput.str()); 70 71 REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_INSTALL_DEPENDENCIES); 72 REQUIRE(!std::filesystem::exists(installResultPath.GetPath())); 73 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::FailedToEnableWindowsFeatureOverrideRequired).get()) != std::string::npos); 74 } 75 76 TEST_CASE("InstallFlow_FailedToEnableWindowsFeature_Force", "[windowsFeature]") 77 { 78 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 79 { 80 WARN("Test requires admin privilege. Skipped."); 81 return; 82 } 83 84 TestCommon::TempFile installResultPath("TestExeInstalled.txt"); 85 TestCommon::TestUserSettings testSettings; 86 87 auto doesFeatureExistOverride = TestHook::SetDoesWindowsFeatureExistResult_Override(ERROR_SUCCESS); 88 auto expectedErrorCode = 0xc0040001; // DISMAPI_E_DISMAPI_NOT_INITIALIZED 89 auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(expectedErrorCode); 90 91 std::ostringstream installOutput; 92 TestContext context{ installOutput, std::cin }; 93 auto previousThreadGlobals = context.SetForCurrentThread(); 94 OverrideForShellExecute(context); 95 OverrideOpenDependencySource(context); 96 97 context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_WindowsFeatures.yaml").GetPath().u8string()); 98 context.Args.AddArg(Execution::Args::Type::Force); 99 100 InstallCommand install({}); 101 install.Execute(context); 102 INFO(installOutput.str()); 103 104 // Verify Installer is called and parameters are passed in. 105 REQUIRE(context.GetTerminationHR() == ERROR_SUCCESS); 106 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::FailedToEnableWindowsFeature(LocIndView{ "testFeature1" }, expectedErrorCode)).get()) != std::string::npos); 107 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::FailedToEnableWindowsFeature(LocIndView{ "testFeature2" }, expectedErrorCode)).get()) != std::string::npos); 108 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::FailedToEnableWindowsFeatureOverridden).get()) != std::string::npos); 109 REQUIRE(std::filesystem::exists(installResultPath.GetPath())); 110 std::ifstream installResultFile(installResultPath.GetPath()); 111 REQUIRE(installResultFile.is_open()); 112 std::string installResultStr; 113 std::getline(installResultFile, installResultStr); 114 REQUIRE(installResultStr.find("/custom") != std::string::npos); 115 REQUIRE(installResultStr.find("/silentwithprogress") != std::string::npos); 116 } 117 118 TEST_CASE("InstallFlow_RebootRequired", "[windowsFeature]") 119 { 120 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 121 { 122 WARN("Test requires admin privilege. Skipped."); 123 return; 124 } 125 126 TestCommon::TempFile installResultPath("TestExeInstalled.txt"); 127 TestCommon::TestUserSettings testSettings; 128 129 // Override with reboot required HRESULT. 130 auto doesFeatureExistOverride = TestHook::SetDoesWindowsFeatureExistResult_Override(ERROR_SUCCESS); 131 auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(ERROR_SUCCESS_REBOOT_REQUIRED); 132 133 std::ostringstream installOutput; 134 TestContext context{ installOutput, std::cin }; 135 auto previousThreadGlobals = context.SetForCurrentThread(); 136 OverrideOpenDependencySource(context); 137 138 context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_WindowsFeatures.yaml").GetPath().u8string()); 139 140 InstallCommand install({}); 141 install.Execute(context); 142 INFO(installOutput.str()); 143 144 REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_FOR_INSTALL); 145 REQUIRE(!std::filesystem::exists(installResultPath.GetPath())); 146 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::RebootRequiredToEnableWindowsFeatureOverrideRequired).get()) != std::string::npos); 147 } 148 149 TEST_CASE("InstallFlow_RebootRequired_Force", "[windowsFeature]") 150 { 151 if (!AppInstaller::Runtime::IsRunningAsAdmin()) 152 { 153 WARN("Test requires admin privilege. Skipped."); 154 return; 155 } 156 157 TestCommon::TempFile installResultPath("TestExeInstalled.txt"); 158 TestCommon::TestUserSettings testSettings; 159 160 // Override with reboot required HRESULT. 161 auto doesFeatureExistOverride = TestHook::SetDoesWindowsFeatureExistResult_Override(ERROR_SUCCESS); 162 auto setEnableFeatureOverride = TestHook::SetEnableWindowsFeatureResult_Override(ERROR_SUCCESS_REBOOT_REQUIRED); 163 164 std::ostringstream installOutput; 165 TestContext context{ installOutput, std::cin }; 166 auto previousThreadGlobals = context.SetForCurrentThread(); 167 OverrideForShellExecute(context); 168 OverrideOpenDependencySource(context); 169 170 context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_WindowsFeatures.yaml").GetPath().u8string()); 171 context.Args.AddArg(Execution::Args::Type::Force); 172 173 InstallCommand install({}); 174 install.Execute(context); 175 INFO(installOutput.str()); 176 177 // Verify Installer is called and parameters are passed in. 178 REQUIRE(context.GetTerminationHR() == ERROR_SUCCESS); 179 REQUIRE(installOutput.str().find(Resource::LocString(Resource::String::RebootRequiredToEnableWindowsFeatureOverridden).get()) != std::string::npos); 180 REQUIRE(std::filesystem::exists(installResultPath.GetPath())); 181 std::ifstream installResultFile(installResultPath.GetPath()); 182 REQUIRE(installResultFile.is_open()); 183 std::string installResultStr; 184 std::getline(installResultFile, installResultStr); 185 REQUIRE(installResultStr.find("/custom") != std::string::npos); 186 REQUIRE(installResultStr.find("/silentwithprogress") != std::string::npos); 187 }