winget-cli

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

InstallCommand.cs (40764B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="InstallCommand.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;
     10     using System.IO;
     11     using AppInstallerCLIE2ETests.Helpers;
     12     using NUnit.Framework;
     13 
     14     /// <summary>
     15     /// Test install command.
     16     /// </summary>
     17     public class InstallCommand : BaseCommand
     18     {
     19         /// <summary>
     20         /// Set up.
     21         /// </summary>
     22         [SetUp]
     23         public void Setup()
     24         {
     25             // Try clean up TestExeInstaller for failure cases where cleanup is not successful
     26             TestCommon.RunAICLICommand("uninstall", "AppInstallerTest.TestExeInstaller");
     27         }
     28 
     29         /// <summary>
     30         /// Test package doesn't exist.
     31         /// </summary>
     32         [Test]
     33         public void InstallAppDoesNotExist()
     34         {
     35             var result = TestCommon.RunAICLICommand("install", "DoesNotExist");
     36             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_APPLICATIONS_FOUND, result.ExitCode);
     37             Assert.True(result.StdOut.Contains("No package found matching input criteria."));
     38         }
     39 
     40         /// <summary>
     41         /// Test multiple matches found.
     42         /// </summary>
     43         [Test]
     44         public void InstallWithMultipleAppsMatchingQuery()
     45         {
     46             var result = TestCommon.RunAICLICommand("install", "TestExeInstaller");
     47             Assert.AreEqual(Constants.ErrorCode.ERROR_MULTIPLE_APPLICATIONS_FOUND, result.ExitCode);
     48             Assert.True(result.StdOut.Contains("Multiple packages found matching input criteria. Please refine the input."));
     49         }
     50 
     51         /// <summary>
     52         /// Test install exe.
     53         /// </summary>
     54         [Test]
     55         public void InstallExe()
     56         {
     57             var installDir = TestCommon.GetRandomTestDir();
     58             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller --silent -l {installDir}");
     59             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
     60             Assert.True(result.StdOut.Contains("Successfully installed"));
     61             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom"));
     62         }
     63 
     64         /// <summary>
     65         /// Test inapplicable os version.
     66         /// </summary>
     67         [Test]
     68         public void InstallExeWithInsufficientMinOsVersion()
     69         {
     70             var installDir = TestCommon.GetRandomTestDir();
     71             var result = TestCommon.RunAICLICommand("install", $"InapplicableOsVersion --silent -l {installDir}");
     72 
     73             // MinOSVersion is moved to installer level, the check is performed during installer selection
     74             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_APPLICABLE_INSTALLER, result.ExitCode);
     75             Assert.False(TestCommon.VerifyTestExeInstalledAndCleanup(installDir));
     76         }
     77 
     78         /// <summary>
     79         /// Test install exe hash mismatch.
     80         /// </summary>
     81         [Test]
     82         public void InstallExeWithHashMismatch()
     83         {
     84             var installDir = TestCommon.GetRandomTestDir();
     85             var result = TestCommon.RunAICLICommand("install", $"TestExeSha256Mismatch --silent -l {installDir}");
     86             Assert.AreEqual(Constants.ErrorCode.ERROR_INSTALLER_HASH_MISMATCH, result.ExitCode);
     87             Assert.True(result.StdOut.Contains("Installer hash does not match"));
     88             Assert.False(TestCommon.VerifyTestExeInstalledAndCleanup(installDir));
     89         }
     90 
     91         /// <summary>
     92         /// Test install inno.
     93         /// </summary>
     94         [Test]
     95         public void InstallWithInno()
     96         {
     97             // Install test inno, manifest does not provide silent switch, we should be populating the default
     98             var installDir = TestCommon.GetRandomTestDir();
     99             var result = TestCommon.RunAICLICommand("install", $"TestInnoInstaller --silent -l {installDir}");
    100             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    101             Assert.True(result.StdOut.Contains("Successfully installed"));
    102             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/VERYSILENT"));
    103         }
    104 
    105         /// <summary>
    106         /// Test install burn.
    107         /// </summary>
    108         [Test]
    109         public void InstallBurn()
    110         {
    111             // Install test burn, manifest does not provide silent switch, we should be populating the default
    112             var installDir = TestCommon.GetRandomTestDir();
    113             var result = TestCommon.RunAICLICommand("install", $"TestBurnInstaller --silent -l {installDir}");
    114             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    115             Assert.True(result.StdOut.Contains("Successfully installed"));
    116             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/quiet"));
    117         }
    118 
    119         /// <summary>
    120         /// Test install nullsoft.
    121         /// </summary>
    122         [Test]
    123         public void InstallNullSoft()
    124         {
    125             // Install test Nullsoft, manifest does not provide silent switch, we should be populating the default
    126             var installDir = TestCommon.GetRandomTestDir();
    127             var result = TestCommon.RunAICLICommand("install", $"TestNullsoftInstaller --silent -l {installDir}");
    128             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    129             Assert.True(result.StdOut.Contains("Successfully installed"));
    130             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/S"));
    131         }
    132 
    133         /// <summary>
    134         /// Test install msi.
    135         /// </summary>
    136         [Test]
    137         public void InstallMSI()
    138         {
    139             var installDir = TestCommon.GetRandomTestDir();
    140             var result = TestCommon.RunAICLICommand("install", $"TestMsiInstaller --silent -l {installDir}");
    141             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    142             Assert.True(result.StdOut.Contains("Successfully installed"));
    143             Assert.True(TestCommon.VerifyTestMsiInstalledAndCleanup(installDir));
    144         }
    145 
    146         /// <summary>
    147         /// Test install msix.
    148         /// </summary>
    149         [Test]
    150         public void InstallMSIX()
    151         {
    152             var result = TestCommon.RunAICLICommand("install", $"TestMsixInstaller");
    153             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    154             Assert.True(result.StdOut.Contains("Successfully installed"));
    155             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup());
    156         }
    157 
    158         /// <summary>
    159         /// Test install msix machine scope.
    160         /// </summary>
    161         [Test]
    162         public void InstallMSIXMachineScope()
    163         {
    164             // TODO: Provision and Deprovision api not supported in build server.
    165             Assert.Ignore();
    166 
    167             var result = TestCommon.RunAICLICommand("install", $"TestMsixInstaller --scope machine");
    168             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    169             Assert.True(result.StdOut.Contains("Successfully installed"));
    170             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup(true));
    171         }
    172 
    173         /// <summary>
    174         /// Test install msix with signature hash.
    175         /// </summary>
    176         [Test]
    177         public void InstallMSIXWithSignature()
    178         {
    179             var result = TestCommon.RunAICLICommand("install", $"TestMsixWithSignatureHash");
    180             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    181             Assert.True(result.StdOut.Contains("Successfully installed"));
    182             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup());
    183         }
    184 
    185         /// <summary>
    186         /// Test install msix with signature hash machine scope.
    187         /// </summary>
    188         [Test]
    189         public void InstallMSIXWithSignatureMachineScope()
    190         {
    191             // TODO: Provision and Deprovision api not supported in build server.
    192             Assert.Ignore();
    193 
    194             var result = TestCommon.RunAICLICommand("install", $"TestMsixWithSignatureHash --scope machine");
    195             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    196             Assert.True(result.StdOut.Contains("Successfully installed"));
    197             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup(true));
    198         }
    199 
    200         /// <summary>
    201         /// Test msix hash mismatch.
    202         /// </summary>
    203         [Test]
    204         public void InstallMSIXWithSignatureHashMismatch()
    205         {
    206             var result = TestCommon.RunAICLICommand("install", $"TestMsixSignatureHashMismatch");
    207             Assert.AreEqual(Constants.ErrorCode.ERROR_INSTALLER_HASH_MISMATCH, result.ExitCode);
    208             Assert.True(result.StdOut.Contains("Installer hash does not match"));
    209             Assert.False(TestCommon.VerifyTestMsixInstalledAndCleanup());
    210         }
    211 
    212         /// <summary>
    213         /// Test install with alternate source failure.
    214         /// </summary>
    215         [Test]
    216         public void InstallExeWithAlternateSourceFailure()
    217         {
    218             TestCommon.RunAICLICommand("source add", "failSearch \"{ \"\"SearchHR\"\": \"\"0x80070002\"\" }\" Microsoft.Test.Configurable --header \"{}\"");
    219 
    220             try
    221             {
    222                 var installDir = TestCommon.GetRandomTestDir();
    223                 var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller --silent -l {installDir}");
    224                 Assert.AreEqual(unchecked((int)0x80070002), result.ExitCode);
    225                 Assert.True(result.StdOut.Contains("Failed when searching source: failSearch"));
    226                 Assert.True(result.StdOut.Contains("AppInstallerTest.TestExeInstaller"));
    227                 Assert.False(result.StdOut.Contains("Successfully installed"));
    228                 Assert.False(TestCommon.VerifyTestExeInstalledAndCleanup(installDir));
    229             }
    230             finally
    231             {
    232                 this.ResetTestSource();
    233             }
    234         }
    235 
    236         /// <summary>
    237         /// Test install portable package.
    238         /// </summary>
    239         [Test]
    240         public void InstallPortableExe()
    241         {
    242             string installDir = TestCommon.GetPortablePackagesDirectory();
    243             string packageId, commandAlias, fileName, packageDirName, productCode;
    244             packageId = "AppInstallerTest.TestPortableExe";
    245             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    246             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    247 
    248             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    249             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    250             Assert.True(result.StdOut.Contains("Successfully installed"));
    251 
    252             // If no location specified, default behavior is to create a package directory with the name "{packageId}_{sourceId}"
    253             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    254         }
    255 
    256         /// <summary>
    257         /// Test install portable package with command.
    258         /// </summary>
    259         [Test]
    260         public void InstallPortableExeWithCommand()
    261         {
    262             var installDir = TestCommon.GetRandomTestDir();
    263             string packageId, commandAlias, fileName, productCode;
    264             packageId = "AppInstallerTest.TestPortableExeWithCommand";
    265             productCode = packageId + "_" + Constants.TestSourceIdentifier;
    266             fileName = "AppInstallerTestExeInstaller.exe";
    267             commandAlias = "testCommand.exe";
    268 
    269             var result = TestCommon.RunAICLICommand("install", $"{packageId} -l {installDir}");
    270             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    271             Assert.True(result.StdOut.Contains("Successfully installed"));
    272             TestCommon.VerifyPortablePackage(installDir, commandAlias, fileName, productCode, true);
    273         }
    274 
    275         /// <summary>
    276         /// Test install portable package with rename.
    277         /// </summary>
    278         [Test]
    279         public void InstallPortableExeWithRename()
    280         {
    281             var installDir = TestCommon.GetRandomTestDir();
    282             string packageId, productCode, renameArgValue;
    283             packageId = "AppInstallerTest.TestPortableExeWithCommand";
    284             productCode = packageId + "_" + Constants.TestSourceIdentifier;
    285             renameArgValue = "testRename.exe";
    286 
    287             var result = TestCommon.RunAICLICommand("install", $"{packageId} -l {installDir} --rename {renameArgValue}");
    288             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    289             Assert.True(result.StdOut.Contains("Successfully installed"));
    290             TestCommon.VerifyPortablePackage(installDir, renameArgValue, renameArgValue, productCode, true);
    291         }
    292 
    293         /// <summary>
    294         /// Test install portable package invalid rename.
    295         /// </summary>
    296         [Test]
    297         public void InstallPortableInvalidRename()
    298         {
    299             var installDir = TestCommon.GetRandomTestDir();
    300             string packageId, renameArgValue;
    301             packageId = "AppInstallerTest.TestPortableExeWithCommand";
    302             renameArgValue = "test?";
    303 
    304             var result = TestCommon.RunAICLICommand("install", $"{packageId} -l {installDir} --rename {renameArgValue}");
    305             Assert.AreNotEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    306             Assert.True(result.StdOut.Contains("The specified filename is not a valid filename"));
    307         }
    308 
    309         /// <summary>
    310         /// Test install portable package with reserve names.
    311         /// </summary>
    312         [Test]
    313         public void InstallPortableReservedNames()
    314         {
    315             var installDir = TestCommon.GetRandomTestDir();
    316             string packageId, renameArgValue;
    317             packageId = "AppInstallerTest.TestPortableExeWithCommand";
    318             renameArgValue = "CON";
    319 
    320             var result = TestCommon.RunAICLICommand("install", $"{packageId} -l {installDir} --rename {renameArgValue}");
    321             Assert.AreNotEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    322             Assert.True(result.StdOut.Contains("The specified filename is not a valid filename"));
    323         }
    324 
    325         /// <summary>
    326         /// Test install portable package to an existing directory.
    327         /// </summary>
    328         [Test]
    329         public void InstallPortableToExistingDirectory()
    330         {
    331             var installDir = TestCommon.GetRandomTestDir();
    332             var existingDir = Path.Combine(installDir, "testDirectory");
    333             Directory.CreateDirectory(existingDir);
    334 
    335             string packageId, commandAlias, fileName, productCode;
    336             packageId = "AppInstallerTest.TestPortableExe";
    337             productCode = packageId + "_" + Constants.TestSourceIdentifier;
    338             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    339 
    340             var result = TestCommon.RunAICLICommand("install", $"{packageId} -l {existingDir}");
    341             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    342             Assert.True(result.StdOut.Contains("Successfully installed"));
    343             TestCommon.VerifyPortablePackage(existingDir, commandAlias, fileName, productCode, true);
    344         }
    345 
    346         /// <summary>
    347         /// Test install portable package. Symlink is a directory.
    348         /// </summary>
    349         [Test]
    350         public void InstallPortableFailsWithCleanup()
    351         {
    352             string packageId, commandAlias;
    353             packageId = "AppInstallerTest.TestPortableExe";
    354             commandAlias = "AppInstallerTestExeInstaller.exe";
    355 
    356             // Create a directory with the same name as the symlink in order to cause install to fail.
    357             string symlinkDirectory = TestCommon.GetPortableSymlinkDirectory(TestCommon.Scope.User);
    358             string conflictDirectory = Path.Combine(symlinkDirectory, commandAlias);
    359 
    360             Directory.CreateDirectory(conflictDirectory);
    361 
    362             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    363 
    364             // Remove directory prior to assertions as this will impact other tests if assertions fail.
    365             Directory.Delete(conflictDirectory, true);
    366 
    367             Assert.AreNotEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    368             Assert.True(result.StdOut.Contains("Unable to create symlink"));
    369         }
    370 
    371         /// <summary>
    372         /// Test reinstalling portable package.
    373         /// </summary>
    374         [Test]
    375         public void ReinstallPortable()
    376         {
    377             string installDir = TestCommon.GetPortablePackagesDirectory();
    378             string packageId, commandAlias, fileName, packageDirName, productCode;
    379             packageId = "AppInstallerTest.TestPortableExe";
    380             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    381             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    382 
    383             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    384             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    385 
    386             string symlinkDirectory = TestCommon.GetPortableSymlinkDirectory(TestCommon.Scope.User);
    387             string symlinkPath = Path.Combine(symlinkDirectory, commandAlias);
    388 
    389             // Clean first install should not display file overwrite message.
    390             Assert.True(result.StdOut.Contains("Successfully installed"));
    391             Assert.False(result.StdOut.Contains($"Overwriting existing file: {symlinkPath}"));
    392 
    393             // Perform second install and verify that file overwrite message is displayed.
    394             var result2 = TestCommon.RunAICLICommand("install", $"{packageId} --force");
    395             Assert.AreEqual(Constants.ErrorCode.S_OK, result2.ExitCode);
    396             Assert.True(result2.StdOut.Contains("Successfully installed"));
    397 
    398             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    399         }
    400 
    401         /// <summary>
    402         /// Test installing portable package user scope.
    403         /// </summary>
    404         [Test]
    405         public void InstallPortable_UserScope()
    406         {
    407             string installDir = TestCommon.GetRandomTestDir();
    408             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageUserRoot, installDir);
    409 
    410             string packageId, commandAlias, fileName, packageDirName, productCode;
    411             packageId = "AppInstallerTest.TestPortableExe";
    412             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    413             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    414 
    415             var result = TestCommon.RunAICLICommand("install", $"{packageId} --scope user");
    416             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageUserRoot, string.Empty);
    417             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    418             Assert.True(result.StdOut.Contains("Successfully installed"));
    419             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    420         }
    421 
    422         /// <summary>
    423         /// Test install portable package machine scope.
    424         /// </summary>
    425         [Test]
    426         public void InstallPortable_MachineScope()
    427         {
    428             string installDir = TestCommon.GetRandomTestDir();
    429             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageMachineRoot, installDir);
    430 
    431             string packageId, commandAlias, fileName, packageDirName, productCode;
    432             packageId = "AppInstallerTest.TestPortableExe";
    433             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    434             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    435 
    436             var result = TestCommon.RunAICLICommand("install", $"{packageId} --scope machine");
    437             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageMachineRoot, string.Empty);
    438             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    439             Assert.True(result.StdOut.Contains("Successfully installed"));
    440             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true, TestCommon.Scope.Machine);
    441         }
    442 
    443         /// <summary>
    444         /// Test install portable package with settings set to user install scope.
    445         /// </summary>
    446         [Test]
    447         public void InstallPortable_InstallScopePreference_User()
    448         {
    449             string installDir = TestCommon.GetRandomTestDir();
    450             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageUserRoot, installDir);
    451             WinGetSettingsHelper.ConfigureInstallBehaviorPreferences(Constants.InstallBehaviorScope, "user");
    452 
    453             string packageId, commandAlias, fileName, packageDirName, productCode;
    454             packageId = "AppInstallerTest.TestPortableExe";
    455             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    456             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    457 
    458             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    459             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageUserRoot, string.Empty);
    460             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    461             Assert.True(result.StdOut.Contains("Successfully installed"));
    462             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    463         }
    464 
    465         /// <summary>
    466         /// Test install portable package with settings set to machine install scope.
    467         /// </summary>
    468         [Test]
    469         public void InstallPortable_InstallScopePreference_Machine()
    470         {
    471             string installDir = TestCommon.GetRandomTestDir();
    472             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageMachineRoot, installDir);
    473             WinGetSettingsHelper.ConfigureInstallBehaviorPreferences(Constants.InstallBehaviorScope, "machine");
    474 
    475             string packageId, commandAlias, fileName, packageDirName, productCode;
    476             packageId = "AppInstallerTest.TestPortableExe";
    477             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    478             commandAlias = fileName = "AppInstallerTestExeInstaller.exe";
    479 
    480             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    481             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.PortablePackageMachineRoot, string.Empty);
    482             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    483             Assert.True(result.StdOut.Contains("Successfully installed"));
    484             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true, TestCommon.Scope.Machine);
    485         }
    486 
    487         /// <summary>
    488         /// Test install zip exe.
    489         /// </summary>
    490         [Test]
    491         public void InstallZip_Exe()
    492         {
    493             var installDir = TestCommon.GetRandomTestDir();
    494             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInstallerWithExe --silent -l {installDir}");
    495             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    496             Assert.True(result.StdOut.Contains("Successfully installed"));
    497             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom"));
    498         }
    499 
    500         /// <summary>
    501         /// Test install zip portable.
    502         /// </summary>
    503         [Test]
    504         public void InstallZip_Portable()
    505         {
    506             string installDir = TestCommon.GetPortablePackagesDirectory();
    507             string packageId, commandAlias, fileName, packageDirName, productCode;
    508             packageId = "AppInstallerTest.TestZipInstallerWithPortable";
    509             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    510             commandAlias = "TestPortable.exe";
    511             fileName = "AppInstallerTestExeInstaller.exe";
    512 
    513             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    514             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    515             Assert.True(result.StdOut.Contains("Successfully installed"));
    516             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true, TestCommon.Scope.User);
    517         }
    518 
    519         /// <summary>
    520         /// Test install zip portable with binaries that depend on PATH variable.
    521         /// </summary>
    522         [Test]
    523         public void InstallZip_ArchivePortableWithBinariesDependentOnPath()
    524         {
    525             string installDir = TestCommon.GetPortablePackagesDirectory();
    526             string packageId, commandAlias, fileName, packageDirName, productCode;
    527             packageId = "AppInstallerTest.ArchivePortableWithBinariesDependentOnPath";
    528             packageDirName = productCode = packageId + "_" + Constants.TestSourceIdentifier;
    529             commandAlias = "TestPortable.exe";
    530             fileName = "AppInstallerTestExeInstaller.exe";
    531 
    532             var result = TestCommon.RunAICLICommand("install", $"{packageId}");
    533             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    534             Assert.True(result.StdOut.Contains("Successfully installed"));
    535             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true, TestCommon.Scope.User, true);
    536         }
    537 
    538         /// <summary>
    539         /// Test install zip with invalid relative file path.
    540         /// </summary>
    541         [Test]
    542         public void InstallZipWithInvalidRelativeFilePath()
    543         {
    544             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInvalidRelativePath");
    545             Assert.AreNotEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    546             Assert.True(result.StdOut.Contains("Invalid relative file path to the nested installer; path points to a location outside of the install directory"));
    547         }
    548 
    549         /// <summary>
    550         /// Test install zip msi.
    551         /// </summary>
    552         [Test]
    553         public void InstallZipWithMsi()
    554         {
    555             var installDir = TestCommon.GetRandomTestDir();
    556             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInstallerWithMsi --silent -l {installDir}");
    557             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    558             Assert.True(result.StdOut.Contains("Successfully installed"));
    559             Assert.True(TestCommon.VerifyTestMsiInstalledAndCleanup(installDir));
    560         }
    561 
    562         /// <summary>
    563         /// Test install zip msix.
    564         /// </summary>
    565         [Test]
    566         public void InstallZipWithMsix()
    567         {
    568             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInstallerWithMsix");
    569             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    570             Assert.True(result.StdOut.Contains("Successfully installed"));
    571             Assert.True(TestCommon.VerifyTestMsixInstalledAndCleanup());
    572         }
    573 
    574         /// <summary>
    575         /// Test install zip exe by extracting with tar.
    576         /// </summary>
    577         [Test]
    578         public void InstallZip_ExtractWithTar()
    579         {
    580             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.ArchiveExtractionMethod, "tar");
    581             var installDir = TestCommon.GetRandomTestDir();
    582             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestZipInstallerWithExe --silent -l {installDir}");
    583             WinGetSettingsHelper.ConfigureInstallBehavior(Constants.ArchiveExtractionMethod, string.Empty);
    584             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    585             Assert.True(result.StdOut.Contains("Successfully installed"));
    586             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom"));
    587         }
    588 
    589         /// <summary>
    590         /// Test install an installed package and convert to upgrade.
    591         /// </summary>
    592         [Test]
    593         public void InstallExeFoundExistingConvertToUpgrade()
    594         {
    595             var baseDir = TestCommon.GetRandomTestDir();
    596             var baseResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller -v 1.0.0.0 --silent -l {baseDir}");
    597             Assert.AreEqual(Constants.ErrorCode.S_OK, baseResult.ExitCode);
    598             Assert.True(baseResult.StdOut.Contains("Successfully installed"));
    599 
    600             // Install will convert to upgrade
    601             var upgradeDir = TestCommon.GetRandomTestDir();
    602             var upgradeResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller --silent -l {upgradeDir}");
    603             Assert.AreEqual(Constants.ErrorCode.S_OK, upgradeResult.ExitCode);
    604             Assert.True(upgradeResult.StdOut.Contains("Trying to upgrade the installed package..."));
    605             Assert.True(upgradeResult.StdOut.Contains("Successfully installed"));
    606 
    607             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(baseDir));
    608             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(upgradeDir, "/Version 2.0.0.0"));
    609         }
    610 
    611         /// <summary>
    612         /// Test install an installed package without an available upgrade.
    613         /// </summary>
    614         [Test]
    615         public void InstallExeFoundExistingConvertToUpgradeNoAvailableUpgrade()
    616         {
    617             var baseDir = TestCommon.GetRandomTestDir();
    618             var baseResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller -v 2.0.0.0 --silent -l {baseDir}");
    619             Assert.AreEqual(Constants.ErrorCode.S_OK, baseResult.ExitCode);
    620             Assert.True(baseResult.StdOut.Contains("Successfully installed"));
    621 
    622             // Install will convert to upgrade
    623             var upgradeDir = TestCommon.GetRandomTestDir();
    624             var upgradeResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller --silent -l {upgradeDir}");
    625             Assert.AreEqual(Constants.ErrorCode.ERROR_UPDATE_NOT_APPLICABLE, upgradeResult.ExitCode);
    626             Assert.True(upgradeResult.StdOut.Contains("Trying to upgrade the installed package..."));
    627             Assert.True(upgradeResult.StdOut.Contains("No available upgrade"));
    628 
    629             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(baseDir));
    630         }
    631 
    632         /// <summary>
    633         /// Test force installing a package.
    634         /// </summary>
    635         [Test]
    636         public void InstallExeWithLatestInstalledWithForce()
    637         {
    638             var baseDir = TestCommon.GetRandomTestDir();
    639             var baseResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller -v 2.0.0.0 --silent -l {baseDir}");
    640             Assert.AreEqual(Constants.ErrorCode.S_OK, baseResult.ExitCode);
    641             Assert.True(baseResult.StdOut.Contains("Successfully installed"));
    642 
    643             // Install will not convert to upgrade
    644             var installDir = TestCommon.GetRandomTestDir();
    645             var installResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller -v 1.0.0.0 --silent -l {installDir} --force");
    646             Assert.AreEqual(Constants.ErrorCode.S_OK, installResult.ExitCode);
    647             Assert.True(installResult.StdOut.Contains("Successfully installed"));
    648 
    649             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(baseDir));
    650             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom"));
    651         }
    652 
    653         /// <summary>
    654         /// Test install a package with an invalid Windows Feature dependency.
    655         /// </summary>
    656         [Test]
    657         public void InstallWithWindowsFeatureDependency_FeatureNotFound()
    658         {
    659             var testDir = TestCommon.GetRandomTestDir();
    660             var installResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.WindowsFeature -l {testDir}");
    661             Assert.AreEqual(Constants.ErrorCode.ERROR_INSTALL_DEPENDENCIES, installResult.ExitCode);
    662             Assert.True(installResult.StdOut.Contains("The feature [invalidFeature] was not found."));
    663             Assert.True(installResult.StdOut.Contains("Failed to enable Windows Feature dependencies. To proceed with installation, use '--force'."));
    664         }
    665 
    666         /// <summary>
    667         /// Test install a package with a Windows Feature dependency using the force argument.
    668         /// </summary>
    669         [Test]
    670         public void InstallWithWindowsFeatureDependency_Force()
    671         {
    672             var testDir = TestCommon.GetRandomTestDir();
    673             var installResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.WindowsFeature --silent --force -l {testDir}");
    674             Assert.AreEqual(Constants.ErrorCode.S_OK, installResult.ExitCode);
    675             Assert.True(installResult.StdOut.Contains("Failed to enable Windows Feature dependencies; proceeding due to --force"));
    676             Assert.True(installResult.StdOut.Contains("Successfully installed"));
    677             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(testDir));
    678         }
    679 
    680         /// <summary>
    681         /// Test install a package with a package dependency that requires the PATH environment variable to be refreshed between dependency installs.
    682         /// </summary>
    683         [Test]
    684         public void InstallWithPackageDependency_RefreshPathVariable()
    685         {
    686             var testDir = TestCommon.GetRandomTestDir();
    687             string installDir = TestCommon.GetPortablePackagesDirectory();
    688             var installResult = TestCommon.RunAICLICommand("install", $"AppInstallerTest.PackageDependencyRequiresPathRefresh -l {testDir}");
    689             Assert.AreEqual(Constants.ErrorCode.S_OK, installResult.ExitCode);
    690             Assert.True(installResult.StdOut.Contains("Successfully installed"));
    691 
    692             // Portable package is used as a dependency. Ensure that it is installed and cleaned up successfully.
    693             string portablePackageId, commandAlias, fileName, packageDirName, productCode;
    694             portablePackageId = "AppInstallerTest.TestPortableExeWithCommand";
    695             packageDirName = productCode = portablePackageId + "_" + Constants.TestSourceIdentifier;
    696             fileName = "AppInstallerTestExeInstaller.exe";
    697             commandAlias = "testCommand.exe";
    698 
    699             TestCommon.VerifyPortablePackage(Path.Combine(installDir, packageDirName), commandAlias, fileName, productCode, true);
    700             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(testDir));
    701         }
    702 
    703         /// <summary>
    704         /// Test install a package using a specific installer type.
    705         /// </summary>
    706         [Test]
    707         public void InstallWithInstallerTypeArgument()
    708         {
    709             var installDir = TestCommon.GetRandomTestDir();
    710             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMultipleInstallers --silent -l {installDir} --installer-type exe");
    711             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    712             Assert.True(result.StdOut.Contains("Successfully installed"));
    713             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir, "/execustom"));
    714         }
    715 
    716         /// <summary>
    717         /// Test install package with installer type preference settings.
    718         /// </summary>
    719         [Test]
    720         public void InstallWithInstallerTypePreference()
    721         {
    722             string[] installerTypePreference = { "nullsoft" };
    723             WinGetSettingsHelper.ConfigureInstallBehaviorPreferences(Constants.InstallerTypes, installerTypePreference);
    724 
    725             string installDir = TestCommon.GetRandomTestDir();
    726             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMultipleInstallers --silent -l {installDir}");
    727 
    728             // Reset installer type preferences.
    729             WinGetSettingsHelper.ConfigureInstallBehaviorPreferences(Constants.InstallerTypes, Array.Empty<string>());
    730 
    731             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    732             Assert.True(result.StdOut.Contains("Successfully installed"));
    733             Assert.True(TestCommon.VerifyTestExeInstalledAndCleanup(installDir), "/S");
    734         }
    735 
    736         /// <summary>
    737         /// Test install package with installer type requirement settings.
    738         /// </summary>
    739         [Test]
    740         public void InstallWithInstallerTypeRequirement()
    741         {
    742             string[] installerTypeRequirement = { "inno" };
    743             WinGetSettingsHelper.ConfigureInstallBehaviorRequirements(Constants.InstallerTypes, installerTypeRequirement);
    744 
    745             string installDir = TestCommon.GetRandomTestDir();
    746             var result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestMultipleInstallers --silent -l {installDir}");
    747 
    748             // Reset installer type requirements.
    749             WinGetSettingsHelper.ConfigureInstallBehaviorRequirements(Constants.InstallerTypes, Array.Empty<string>());
    750 
    751             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_APPLICABLE_INSTALLER, result.ExitCode);
    752             Assert.True(result.StdOut.Contains("No applicable installer found; see logs for more details."));
    753         }
    754 
    755         /// <summary>
    756         /// This test flow is intended to test an EXE that actually installs an MSIX internally, and whose name+publisher
    757         /// information resembles an existing installation. Given this, the goal is to get correlation to stick to the
    758         /// MSIX rather than the ARP entry that we would match with in the absence of the package family name being present.
    759         /// </summary>
    760         [Test]
    761         public void InstallExeThatInstallsMSIX()
    762         {
    763             string targetPackageIdentifier = "AppInstallerTest.TestExeInstallerInstallsMSIX";
    764             string fakeProductCode = "e35f5799-cce3-41fd-886c-c36fcb7104fe";
    765 
    766             // Insert fake ARP entry as if a non-MSIX version of the package is already installed.
    767             // The name here must not match the normalized name of the package, but be close enough to meet
    768             // the confidence requirements for correlation after an install operation (so we drop one word here).
    769             TestCommon.CreateARPEntry(fakeProductCode, new
    770             {
    771                 DisplayName = "EXE Installer that Installs MSIX",
    772                 Publisher = "AppInstallerTest",
    773                 DisplayVersion = "1.0.0",
    774             });
    775 
    776             // We should not find it before installing because the normalized name doesn't match
    777             var result = TestCommon.RunAICLICommand("list", targetPackageIdentifier);
    778             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_APPLICATIONS_FOUND, result.ExitCode);
    779 
    780             // Add the MSIX to simulate an installer doing it
    781             TestCommon.InstallMsix(TestIndex.MsixInstaller);
    782 
    783             // Install our exe that "installs" the MSIX
    784             result = TestCommon.RunAICLICommand("install", $"{targetPackageIdentifier} --force");
    785             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    786 
    787             // We should find the package now, and it should be correlated to the MSIX (although we don't actually know that from this probe)
    788             result = TestCommon.RunAICLICommand("list", targetPackageIdentifier);
    789             Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
    790 
    791             // Remove the MSIX outside of winget's knowledge to keep the tracking data.
    792             TestCommon.RemoveMsix(Constants.MsixInstallerName);
    793 
    794             // We should not find the package now that the MSIX is gone, confirming that it was correlated
    795             result = TestCommon.RunAICLICommand("list", targetPackageIdentifier);
    796             Assert.AreEqual(Constants.ErrorCode.ERROR_NO_APPLICATIONS_FOUND, result.ExitCode);
    797 
    798             TestCommon.RemoveARPEntry(fakeProductCode);
    799         }
    800     }
    801 }