winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

RepairCommand.cs (15513B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="RepairCommand.cs" company="Microsoft Corporation">
      3 //     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
      4 // </copyright>
      5 // -----------------------------------------------------------------------------
      6 
      7 namespace AppInstallerCLIE2ETests
      8 {
      9     using System.IO;
     10     using AppInstallerCLIE2ETests.Helpers;
     11     using NUnit.Framework;
     12 
     13     /// <summary>
     14     /// Test Repair command.
     15     /// </summary>
     16     public class RepairCommand : BaseCommand
     17     {
     18         /// <summary>
     19         /// One time setup.
     20         /// </summary>
     21         [OneTimeSetUp]
     22         public void OneTimeSetup()
     23         {
     24             // Try clean up AppInstallerTest.TestMsiInstaller for failure cases where cleanup is not successful
     25             TestCommon.RunAICLICommand("uninstall", "AppInstallerTest.TestMsiInstaller");
     26         }
     27 
     28         /// <summary>
     29         /// Test  MSI installer repair.
     30         /// </summary>
     31         [Test]
     32         public void RepairMSIInstaller()
     33         {
     34             if (string.IsNullOrEmpty(TestIndex.MsiInstallerV2))
     35             {
     36                 Assert.Ignore("MSI installer not available");
     37             }
     38 
     39             var installDir = TestCommon.GetRandomTestDir();
     40             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMsiRepair --silent -l {installDir}");
     41 
     42             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
     43             Assert.True(result.StdOut.Contains("Successfully installed"));
     44 
     45             // Note: The 'msiexec repair' command requires the original installer file to be present at the location registered in the ARP (Add/Remove Programs).
     46             // In our test scenario, the MSI installer file is initially placed in a temporary location and then deleted, which can cause the repair operation to fail.
     47             // To work around this, we copy the installer file to the ARP source directory before running the repair command.
     48             // A more permanent solution would be to modify the MSI installer to cache the installer file in a known location and register that location as the installer source.
     49             // This would allow the 'msiexec repair' command to function as expected.
     50             string installerSourceDir = TestCommon.CopyInstallerFileToARPInstallSourceDirectory(TestCommon.GetTestDataFile("AppInstallerTestMsiInstallerV2.msi"), Constants.MsiInstallerProductCode, true);
     51 
     52             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMsiRepair");
     53             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
     54             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
     55             Assert.True(TestCommon.VerifyTestMsiInstalledAndCleanup(installDir));
     56 
     57             if (installerSourceDir != null && Directory.Exists(installerSourceDir))
     58             {
     59                 Directory.Delete(installerSourceDir, true);
     60             }
     61         }
     62 
     63         /// <summary>
     64         /// Test  MSIX non-store package repair.
     65         /// </summary>
     66         [Test]
     67         public void RepairNonStoreMSIXPackage()
     68         {
     69             // install a test msix package from TestSource and then repair it.
     70             var installDir = TestCommon.GetRandomTestDir();
     71             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMsixInstaller --silent -l {installDir}");
     72 
     73             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
     74             Assert.True(result.StdOut.Contains("Successfully installed"));
     75 
     76             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMsixInstaller");
     77             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
     78             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
     79             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup());
     80         }
     81 
     82         /// <summary>
     83         /// Test MSIX non-store package repair with machine scope.
     84         /// </summary>
     85         [Test]
     86         public void RepairNonStoreMsixPackageWithMachineScope()
     87         {
     88             // Selecting Microsoft.Paint_8wekyb3d8bbwe because it's a system package suitable for this scenario.
     89             // First, we need to ensure this package is installed, otherwise, we skip the test.
     90             var result = TestCommon.RunAICLICommand("list", "Microsoft.Paint_8wekyb3d8bbwe");
     91 
     92             if (result.ExitCode != Constants.ErrorCode.S_OK)
     93             {
     94                 Assert.Ignore("Test skipped as Microsoft.Paint_8wekyb3d8bbwe is not installed.");
     95             }
     96 
     97             Assert.True(result.StdOut.Contains("Microsoft.Paint"));
     98 
     99             result = TestCommon.RunAICLICommand("repair", "Microsoft.Paint_8wekyb3d8bbwe --scope machine");
    100             Assert.AreEqual(Constants.ErrorCode.ERROR_INSTALL_SYSTEM_NOT_SUPPORTED, result.ExitCode);
    101             Assert.True(result.StdOut.Contains("The current system configuration does not support the repair of this package."));
    102         }
    103 
    104         /// <summary>
    105         /// Test repair of a Burn installer that has a "modify" repair behavior specified in the manifest.
    106         /// </summary>
    107         [Test]
    108         public void RepairBurnInstallerWithModifyBehavior()
    109         {
    110             // install a test burn package from TestSource and then repair it.
    111             var installDir = TestCommon.GetRandomTestDir();
    112             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestModifyRepair -v 2.0.0.0 --silent -l {installDir}");
    113 
    114             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    115             Assert.True(result.StdOut.Contains("Successfully installed"));
    116 
    117             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestModifyRepair");
    118             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    119             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
    120             Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Modify Repair operation"));
    121         }
    122 
    123         /// <summary>
    124         /// Tests the repair operation of a Burn installer that was installed in user scope but is being repaired in an admin context.
    125         /// </summary>
    126         [Test]
    127         public void RepairBurnInstallerInAdminContextWithUserScopeInstall()
    128         {
    129             // install a test burn package from TestSource and then repair it.
    130             var installDir = TestCommon.GetRandomTestDir();
    131             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestUserScopeInstallRepairInAdminContext -v 2.0.0.0 --silent -l {installDir}");
    132 
    133             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    134             Assert.True(result.StdOut.Contains("Successfully installed"));
    135 
    136             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestUserScopeInstallRepairInAdminContext");
    137             Assert.AreEqual(Constants.ErrorCode.ERROR_ADMIN_CONTEXT_REPAIR_PROHIBITED, result.ExitCode);
    138             Assert.True(result.StdOut.Contains("The package installed for user scope cannot be repaired when running with administrator privileges."));
    139             TestCommon.CleanupTestExeAndDirectory(installDir);
    140         }
    141 
    142         /// <summary>
    143         /// Tests the repair operation of a Burn installer that lacks a repair behavior.
    144         /// </summary>
    145         [Test]
    146         public void RepairBurnInstallerMissingRepairBehavior()
    147         {
    148             // install a test burn package from TestSource and then repair it.
    149             var installDir = TestCommon.GetRandomTestDir();
    150             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMissingRepairBehavior -v 2.0.0.0 --silent -l {installDir}");
    151 
    152             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    153             Assert.True(result.StdOut.Contains("Successfully installed"));
    154 
    155             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestMissingRepairBehavior");
    156             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_REPAIR_INFO_FOUND, result.ExitCode);
    157             Assert.True(result.StdOut.Contains("The repair command for this package cannot be found. Please reach out to the package publisher for support."));
    158             TestCommon.CleanupTestExeAndDirectory(installDir);
    159         }
    160 
    161         /// <summary>
    162         /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest and NoModify ARP flag set.
    163         /// </summary>
    164         [Test]
    165         public void RepairBurnInstallerWithWithModifyBehaviorAndNoModifyFlag()
    166         {
    167             // install a test Exe package from TestSource and then repair it.
    168             var installDir = TestCommon.GetRandomTestDir();
    169             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestModifyRepairWithNoModify -v 2.0.0.0 --silent -l {installDir}");
    170 
    171             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    172             Assert.True(result.StdOut.Contains("Successfully installed"));
    173 
    174             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestModifyRepairWithNoModify");
    175             Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode);
    176             Assert.True(result.StdOut.Contains("The installer technology in use does not support repair."));
    177             TestCommon.CleanupTestExeAndDirectory(installDir);
    178         }
    179 
    180         /// <summary>
    181         /// Tests the scenario where the repair operation is not supported for Portable Installer type.
    182         /// </summary>
    183         [Test]
    184         public void RepairOperationNotSupportedForPortableInstaller()
    185         {
    186             string installDir = TestCommon.GetPortablePackagesDirectory();
    187             string packageId, commandAlias, fileName, packageDirName, productCode;
    188             packageId = "AppInstallerTest.TestPortableExe";
    189             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    190             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    191 
    192             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    193             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    194             Assert.True(result.StdOut.Contains("Successfully installed"));
    195 
    196             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestPortableExe");
    197             Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode);
    198             Assert.True(result.StdOut.Contains("The installer technology in use does not support repair."));
    199 
    200             // If no location specified, default behavior is to create a package directory with the name "{packageId}_{sourceId}"
    201             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    202         }
    203 
    204         /// <summary>
    205         /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest.
    206         /// </summary>
    207         [Test]
    208         public void RepairExeInstallerWithUninstallerBehavior()
    209         {
    210             // install a test Exe package from TestSource and then repair it.
    211             var installDir = TestCommon.GetRandomTestDir();
    212             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepair -v 2.0.0.0 --silent -l {installDir}");
    213 
    214             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    215             Assert.True(result.StdOut.Contains("Successfully installed"));
    216 
    217             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepair");
    218             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    219             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
    220             Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Uninstaller Repair operation"));
    221         }
    222 
    223         /// <summary>
    224         /// Test repair of a Exe installer that has a "uninstaller" repair behavior specified in the manifest and NoRepair ARP flag set.
    225         /// </summary>
    226         [Test]
    227         public void RepairExeInstallerWithUninstallerBehaviorAndNoRepairFlag()
    228         {
    229             // install a test Exe package from TestSource and then repair it.
    230             var installDir = TestCommon.GetRandomTestDir();
    231             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepairWithNoRepair -v 2.0.0.0 --silent -l {installDir}");
    232 
    233             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    234             Assert.True(result.StdOut.Contains("Successfully installed"));
    235 
    236             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepairWithNoRepair");
    237             Assert.AreEqual(Constants.ErrorCode.ERROR_REPAIR_NOT_SUPPORTED, result.ExitCode);
    238             Assert.True(result.StdOut.Contains("The installer technology in use does not support repair."));
    239             TestCommon.CleanupTestExeAndDirectory(installDir);
    240         }
    241 
    242         /// <summary>
    243         /// Test repair of a Nullsoft installer that has a "uninstaller" repair behavior specified in the manifest.
    244         /// </summary>
    245         [Test]
    246         public void RepairNullsoftInstallerWithUninstallerBehavior()
    247         {
    248             // install a test Nullsoft package from TestSource and then repair it.
    249             var installDir = TestCommon.GetRandomTestDir();
    250             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.UninstallerRepair -v 2.0.0.0 --silent -l {installDir}");
    251 
    252             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    253             Assert.True(result.StdOut.Contains("Successfully installed"));
    254 
    255             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.UninstallerRepair");
    256             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    257             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
    258             Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Uninstaller Repair operation"));
    259         }
    260 
    261         /// <summary>
    262         /// Test repair of a Inno installer that has a "installer" repair behavior specified in the manifest.
    263         /// </summary>
    264         [Test]
    265         public void RepairInnoInstallerWithInstallerBehavior()
    266         {
    267             // install a test Inno package from TestSource and then repair it.
    268             var installDir = TestCommon.GetRandomTestDir();
    269             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestInstallerRepair -v 2.0.0.0 --silent -l {installDir}");
    270 
    271             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    272             Assert.True(result.StdOut.Contains("Successfully installed"));
    273 
    274             result = TestCommon.RunAICLICommand("repair", "AppInstallerTest.TestInstallerRepair");
    275             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    276             Assert.True(result.StdOut.Contains("Repair operation completed successfully"));
    277             Assert.True(TestCommon.VerifyTestExeRepairCompletedAndCleanup(installDir, "Installer Repair operation"));
    278         }
    279     }
    280 }