winget-cli

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

ConfigureCommand.cs (20076B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="ConfigureCommand.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     /// `Configure` command tests.
     16     /// </summary>
     17     public class ConfigureCommand
     18     {
     19         private const string CommandAndAgreementsAndVerbose = "configure --accept-configuration-agreements --verbose";
     20 
     21         /// <summary>
     22         /// Ensures that the test resources manifests are present.
     23         /// </summary>
     24         public static void EnsureTestResourcePresence()
     25         {
     26             DSCv3ResourceTestBase.EnsureTestResourcePresence();
     27         }
     28 
     29         /// <summary>
     30         /// Setup done once before all the tests here.
     31         /// </summary>
     32         [OneTimeSetUp]
     33         public void OneTimeSetup()
     34         {
     35             this.DeleteResourceArtifacts();
     36             EnsureTestResourcePresence();
     37             TestCommon.SetupTestSource(false);
     38         }
     39 
     40         /// <summary>
     41         /// Teardown done once after all the tests here.
     42         /// </summary>
     43         [OneTimeTearDown]
     44         public void OneTimeTeardown()
     45         {
     46             this.DeleteResourceArtifacts();
     47             TestCommon.TearDownTestSource();
     48         }
     49 
     50         /// <summary>
     51         /// Simple test to confirm that a resource without a module specified can be discovered in the PSGallery.
     52         /// Intentionally has no settings to force a failure, but only after acquiring the module.
     53         /// </summary>
     54         [Test]
     55         [Ignore("PS Gallery tests are unreliable.")]
     56         public void ConfigureFromGallery()
     57         {
     58             TestCommon.EnsureModuleState(Constants.GalleryTestModuleName, present: false);
     59 
     60             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\PSGallery_NoModule_NoSettings.yml"), timeOut: 120000);
     61             Assert.AreEqual(Constants.ErrorCode.CONFIG_ERROR_SET_APPLY_FAILED, result.ExitCode);
     62             Assert.True(result.StdOut.Contains("The configuration unit failed while attempting to test the current system state."));
     63         }
     64 
     65         /// <summary>
     66         /// Simple test to confirm that a resource with a module specified can be discovered in a local repository that doesn't support resource discovery.
     67         /// </summary>
     68         [Test]
     69         public void ConfigureFromTestRepo()
     70         {
     71             TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false);
     72 
     73             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo.yml"));
     74             Assert.AreEqual(0, result.ExitCode);
     75 
     76             // The configuration creates a file next to itself with the given contents
     77             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo.txt");
     78             FileAssert.Exists(targetFilePath);
     79             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
     80 
     81             Assert.True(Directory.Exists(
     82                 Path.Combine(
     83                     TestCommon.GetExpectedModulePath(TestCommon.TestModuleLocation.Default),
     84                     Constants.SimpleTestModuleName)));
     85         }
     86 
     87         /// <summary>
     88         /// Simple test to confirm that the module was installed to the location specified in the DefaultModuleRoot settings.
     89         /// </summary>
     90         [Test]
     91         public void ConfigureFromTestRepo_DefaultModuleRootSetting()
     92         {
     93             TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false);
     94             string moduleTestDir = TestCommon.GetRandomTestDir();
     95             WinGetSettingsHelper.ConfigureConfigureBehavior(Constants.DefaultModuleRoot, moduleTestDir);
     96 
     97             string args = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo_Location.yml");
     98             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, args);
     99 
    100             WinGetSettingsHelper.ConfigureConfigureBehavior(Constants.DefaultModuleRoot, string.Empty);
    101             bool moduleExists = Directory.Exists(Path.Combine(moduleTestDir, Constants.SimpleTestModuleName));
    102             if (moduleExists)
    103             {
    104                 // Clean test directory to avoid impacting other tests.
    105                 Directory.Delete(moduleTestDir, true);
    106             }
    107 
    108             Assert.AreEqual(0, result.ExitCode);
    109             Assert.True(moduleExists);
    110         }
    111 
    112         /// <summary>
    113         /// Simple test to confirm that the module was installed in the right location.
    114         /// </summary>
    115         /// <param name="location">Location to pass.</param>
    116         [TestCase(TestCommon.TestModuleLocation.CurrentUser)]
    117         [TestCase(TestCommon.TestModuleLocation.AllUsers)]
    118         [TestCase(TestCommon.TestModuleLocation.WinGetModulePath)]
    119         [TestCase(TestCommon.TestModuleLocation.Custom)]
    120         [TestCase(TestCommon.TestModuleLocation.Default)]
    121         public void ConfigureFromTestRepo_Location(TestCommon.TestModuleLocation location)
    122         {
    123             TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false);
    124 
    125             string args = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo_Location.yml");
    126             if (location == TestCommon.TestModuleLocation.CurrentUser)
    127             {
    128                 args += " --module-path currentuser";
    129             }
    130             else if (location == TestCommon.TestModuleLocation.AllUsers)
    131             {
    132                 args += " --module-path allusers";
    133             }
    134             else if (location == TestCommon.TestModuleLocation.Default)
    135             {
    136                 args += " --module-path default";
    137             }
    138             else if (location == TestCommon.TestModuleLocation.Custom)
    139             {
    140                 args += " --module-path " + TestCommon.GetExpectedModulePath(location);
    141             }
    142 
    143             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, args);
    144             Assert.AreEqual(0, result.ExitCode);
    145 
    146             Assert.True(Directory.Exists(Path.Combine(
    147                 TestCommon.GetExpectedModulePath(location),
    148                 Constants.SimpleTestModuleName)));
    149         }
    150 
    151         /// <summary>
    152         /// One resource fails, but the other is not dependent and should be executed.
    153         /// </summary>
    154         [Test]
    155         public void IndependentResourceWithSingleFailure()
    156         {
    157             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\IndependentResources_OneFailure.yml"));
    158             Assert.AreEqual(Constants.ErrorCode.CONFIG_ERROR_SET_APPLY_FAILED, result.ExitCode);
    159 
    160             // The configuration creates a file next to itself with the given contents
    161             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\IndependentResources_OneFailure.txt");
    162             FileAssert.Exists(targetFilePath);
    163             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
    164         }
    165 
    166         /// <summary>
    167         /// One resource fails, and the dependent resource should not be executed.
    168         /// </summary>
    169         [Test]
    170         public void DependentResourceWithFailure()
    171         {
    172             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\DependentResources_Failure.yml"));
    173             Assert.AreEqual(Constants.ErrorCode.CONFIG_ERROR_SET_APPLY_FAILED, result.ExitCode);
    174 
    175             // The configuration creates a file next to itself with the given contents
    176             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\DependentResources_Failure.txt");
    177             FileAssert.DoesNotExist(targetFilePath);
    178         }
    179 
    180         /// <summary>
    181         /// The configuration server unexpectedly exits. Winget should continue to operate properly.
    182         /// </summary>
    183         [Test]
    184         public void ConfigServerUnexpectedExit()
    185         {
    186             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\ConfigServerUnexpectedExit.yml"));
    187             Assert.AreEqual(Constants.ErrorCode.CONFIG_ERROR_SET_APPLY_FAILED, result.ExitCode);
    188 
    189             // The configuration creates a file next to itself with the given contents
    190             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\ConfigServerUnexpectedExit.txt");
    191             FileAssert.DoesNotExist(targetFilePath);
    192         }
    193 
    194         /// <summary>
    195         /// Resource name case-insensitive test.
    196         /// </summary>
    197         [Test]
    198         public void ResourceCaseInsensitive()
    199         {
    200             TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false);
    201 
    202             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\ResourceCaseInsensitive.yml"));
    203             Assert.AreEqual(0, result.ExitCode);
    204 
    205             // The configuration creates a file next to itself with the given contents
    206             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\ResourceCaseInsensitive.txt");
    207             FileAssert.Exists(targetFilePath);
    208             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
    209         }
    210 
    211         /// <summary>
    212         /// Simple test to configure from an https configuration file.
    213         /// </summary>
    214         [Test]
    215         public void ConfigureFromHttpsConfigurationFile()
    216         {
    217             string args = $"{Constants.TestSourceUrl}/TestData/Configuration/Configure_TestRepo_Location.yml";
    218 
    219             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, args);
    220             Assert.AreEqual(0, result.ExitCode);
    221         }
    222 
    223         /// <summary>
    224         /// Runs a configuration, then changes the state and runs it again from history.
    225         /// </summary>
    226         [Test]
    227         public void ConfigureFromHistory()
    228         {
    229             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo.yml"));
    230             Assert.AreEqual(0, result.ExitCode);
    231 
    232             // The configuration creates a file next to itself with the given contents
    233             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo.txt");
    234             FileAssert.Exists(targetFilePath);
    235             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
    236 
    237             File.WriteAllText(targetFilePath, "Changed contents!");
    238 
    239             string guid = TestCommon.GetConfigurationInstanceIdentifierFor("Configure_TestRepo.yml");
    240             result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, $"-h {guid}");
    241             Assert.AreEqual(0, result.ExitCode);
    242 
    243             FileAssert.Exists(targetFilePath);
    244             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
    245         }
    246 
    247         /// <summary>
    248         /// Specifies the module path to an "elevated" server.
    249         /// </summary>
    250         [Test]
    251         public void SpecifyModulePathToHighIntegrityServer()
    252         {
    253             string configFile = TestCommon.GetTestDataFile("Configuration\\GetPSModulePath.yml");
    254             string testDirectory = TestCommon.GetRandomTestDir();
    255 
    256             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, $"{configFile} --module-path \"{testDirectory}\"");
    257             Assert.AreEqual(0, result.ExitCode);
    258 
    259             string testFile = Path.Join(TestCommon.GetTestDataFile("Configuration"), "PSModulePath.txt");
    260             Assert.True(File.Exists(testFile));
    261             string testFileContents = File.ReadAllText(testFile);
    262             Assert.True(testFileContents.StartsWith(testDirectory));
    263         }
    264 
    265         /// <summary>
    266         /// Runs a DSCv3 configuration, then changes the state and runs it again from history.
    267         /// </summary>
    268         [Test]
    269         public void ConfigureThroughHistory_DSCv3()
    270         {
    271             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\ShowDetails_DSCv3.yml"));
    272             Assert.AreEqual(0, result.ExitCode);
    273 
    274             // The configuration creates a file next to itself with the given contents
    275             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\ShowDetails_DSCv3.txt");
    276             FileAssert.Exists(targetFilePath);
    277             Assert.AreEqual("DSCv3 Contents!", File.ReadAllText(targetFilePath));
    278 
    279             File.WriteAllText(targetFilePath, "Changed contents!");
    280 
    281             string guid = TestCommon.GetConfigurationInstanceIdentifierFor("ShowDetails_DSCv3.yml");
    282             result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, $"-h {guid}");
    283             Assert.AreEqual(0, result.ExitCode);
    284 
    285             FileAssert.Exists(targetFilePath);
    286             Assert.AreEqual("DSCv3 Contents!", File.ReadAllText(targetFilePath));
    287         }
    288 
    289         /// <summary>
    290         /// Ensures that the test file resource schema function works.
    291         /// </summary>
    292         [Test]
    293         public void TestFileResourceSchema()
    294         {
    295             var result = TestCommon.RunAICLICommand("dscv3 test-file", "--schema");
    296             Assert.AreEqual(0, result.ExitCode);
    297 
    298             var lines = result.StdOut.Split("\r\n", StringSplitOptions.RemoveEmptyEntries);
    299             Assert.AreEqual(1, lines.Length);
    300         }
    301 
    302         /// <summary>
    303         /// Export all with specific package id.
    304         /// </summary>
    305         [Test]
    306         public void DSCv3_Export()
    307         {
    308             // Reset state
    309             var result = TestCommon.RunAICLICommand("dscv3 test-json", "--delete");
    310             Assert.AreEqual(0, result.ExitCode);
    311 
    312             // Configure properties
    313             string propertyName1 = "prop1";
    314             string propertyName2 = "prop2";
    315             string propertyValue1 = "val1";
    316             string propertyValue2 = "val2";
    317 
    318             string propertySetFormatString = "{{ \"property\": \"{0}\", \"value\": \"{1}\" }}";
    319 
    320             result = TestCommon.RunAICLICommand("dscv3 test-json", "--set", string.Format(propertySetFormatString, propertyName1, propertyValue1));
    321             Assert.AreEqual(0, result.ExitCode);
    322 
    323             result = TestCommon.RunAICLICommand("dscv3 test-json", "--set", string.Format(propertySetFormatString, propertyName2, propertyValue2));
    324             Assert.AreEqual(0, result.ExitCode);
    325 
    326             // Export
    327             var exportDir = TestCommon.GetRandomTestDir();
    328             var exportFile = Path.Combine(exportDir, "exported.yml");
    329 
    330             result = TestCommon.RunAICLICommand("test config-export-units", $"-o {exportFile} --resource Microsoft.WinGet.Dev/TestJSON --verbose");
    331             Assert.AreEqual(0, result.ExitCode);
    332 
    333             Assert.True(File.Exists(exportFile));
    334             string exportText = File.ReadAllText(exportFile);
    335             Assert.True(exportText.Contains("Microsoft.WinGet.Dev/TestJSON"));
    336             Assert.True(exportText.Contains(propertyName1));
    337             Assert.True(exportText.Contains(propertyName2));
    338             Assert.True(exportText.Contains(propertyValue1));
    339             Assert.True(exportText.Contains(propertyValue2));
    340         }
    341 
    342         /// <summary>
    343         /// Simple test to confirm that a resource with a module specified can be discovered in a local repository that doesn't support resource discovery.
    344         /// </summary>
    345         [Test]
    346         public void ConfigureFromTestRepo_DSCv3()
    347         {
    348             TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: true, repository: Constants.TestRepoName);
    349             this.DeleteResourceArtifacts();
    350 
    351             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo_DSCv3.yml"), timeOut: 300000);
    352             Assert.AreEqual(0, result.ExitCode);
    353 
    354             // The configuration creates a file next to itself with the given contents
    355             string targetFilePath = TestCommon.GetTestDataFile("Configuration\\Configure_TestRepo.txt");
    356             FileAssert.Exists(targetFilePath);
    357             Assert.AreEqual("Contents!", File.ReadAllText(targetFilePath));
    358         }
    359 
    360         /// <summary>
    361         /// Find unit processors tests.
    362         /// </summary>
    363         [Test]
    364         public void ConfigureFindUnitProcessors()
    365         {
    366             // Find all unit processors.
    367             var result = TestCommon.RunAICLICommand("test config-find-unit-processors", string.Empty);
    368             Assert.AreEqual(0, result.ExitCode);
    369             Assert.True(result.StdOut.Contains("Microsoft/OSInfo"));
    370 
    371             // Setup TestExeInstaller with dsc resources.
    372             var installDir = TestCommon.GetRandomTestDir();
    373             result = TestCommon.RunAICLICommand("install", $"AppInstallerTest.TestExeInstaller --override \"/InstallDir {installDir} /GenerateDscResourceFiles\"");
    374             Assert.AreEqual(0, result.ExitCode);
    375 
    376             // Find unit processors filtering to install location.
    377             result = TestCommon.RunAICLICommand("test config-find-unit-processors", $"-l {installDir}");
    378             Assert.AreEqual(0, result.ExitCode);
    379             Assert.False(result.StdOut.Contains("Microsoft/OSInfo"));
    380             Assert.True(result.StdOut.Contains("AppInstallerTest/TestResource"));
    381 
    382             // Find unit processors filtering to unknown location.
    383             var unknownDir = TestCommon.GetRandomTestDir();
    384             result = TestCommon.RunAICLICommand("test config-find-unit-processors", $"-l {unknownDir}");
    385             Assert.AreEqual(0, result.ExitCode);
    386             Assert.True(result.StdOut.Contains("No unit processors found."));
    387 
    388             // Clean up
    389             result = TestCommon.RunAICLICommand("uninstall", "AppInstallerTest.TestExeInstaller");
    390             Assert.AreEqual(0, result.ExitCode);
    391         }
    392 
    393         /// <summary>
    394         /// RunCommandOnSet test.
    395         /// </summary>
    396         [Test]
    397         public void RunCommandOnSetResourceTest()
    398         {
    399             var testDir = TestCommon.GetRandomTestDir();
    400             var testConfigFile = Path.Combine(testDir, "RunCommandOnSet.yml");
    401             File.Copy(TestCommon.GetTestDataFile("Configuration\\RunCommandOnSet.yml"), testConfigFile);
    402 
    403             var content = File.ReadAllText(testConfigFile);
    404             content = content.Replace("<PathToBeReplaced>", testDir);
    405             File.WriteAllText(testConfigFile, content);
    406 
    407             var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, testConfigFile, timeOut: 300000);
    408             Assert.AreEqual(0, result.ExitCode);
    409 
    410             // Verify test file created.
    411             string targetFilePath = Path.Combine(testDir, "TestFile.txt");
    412             FileAssert.Exists(targetFilePath);
    413             string testContent = File.ReadAllText(targetFilePath);
    414             Assert.True(testContent.Contains("TestContent"));
    415         }
    416 
    417         private void DeleteResourceArtifacts()
    418         {
    419             // Delete all .txt files in the test directory; they are placed there by the tests
    420             foreach (string file in Directory.GetFiles(TestCommon.GetTestDataFile("Configuration"), "*.txt"))
    421             {
    422                 File.Delete(file);
    423             }
    424         }
    425     }
    426 }