winget-cli

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

ConfigurationProcessorApplyTests.cs (37642B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="ConfigurationProcessorApplyTests.cs" company="Microsoft Corporation">
      3 //     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
      4 // </copyright>
      5 // -----------------------------------------------------------------------------
      6 
      7 namespace Microsoft.Management.Configuration.UnitTests.Tests
      8 {
      9     using System;
     10     using System.Collections.Generic;
     11     using System.IO;
     12     using System.Linq;
     13     using System.Threading;
     14     using Microsoft.Management.Configuration.UnitTests.Fixtures;
     15     using Microsoft.Management.Configuration.UnitTests.Helpers;
     16     using Microsoft.VisualBasic;
     17     using Xunit;
     18     using Xunit.Abstractions;
     19 
     20     /// <summary>
     21     /// Unit tests for running apply on the processor.
     22     /// </summary>
     23     [Collection("UnitTestCollection")]
     24     [InProc]
     25     [OutOfProc]
     26     public class ConfigurationProcessorApplyTests : ConfigurationProcessorTestBase
     27     {
     28         /// <summary>
     29         /// Initializes a new instance of the <see cref="ConfigurationProcessorApplyTests"/> class.
     30         /// </summary>
     31         /// <param name="fixture">Unit test fixture.</param>
     32         /// <param name="log">Log helper.</param>
     33         public ConfigurationProcessorApplyTests(UnitTestFixture fixture, ITestOutputHelper log)
     34             : base(fixture, log)
     35         {
     36         }
     37 
     38         /// <summary>
     39         /// An error creating the set processor results in an error for the function.
     40         /// </summary>
     41         [Fact]
     42         public void ApplySet_SetProcessorError()
     43         {
     44             ConfigurationSet configurationSet = this.ConfigurationSet();
     45 
     46             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
     47             factory.Exceptions.Add(configurationSet, new FileNotFoundException());
     48 
     49             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
     50 
     51             Assert.Throws<FileNotFoundException>(() => processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None));
     52 
     53             Assert.Empty(this.EventSink.Events);
     54         }
     55 
     56         /// <summary>
     57         /// Multiple configuration units with the same identifier.
     58         /// </summary>
     59         [Fact]
     60         public void ApplySet_DuplicateIdentifiers()
     61         {
     62             ConfigurationSet configurationSet = this.ConfigurationSet();
     63             ConfigurationUnit configurationUnit1 = this.ConfigurationUnit();
     64             ConfigurationUnit configurationUnit2 = this.ConfigurationUnit();
     65             ConfigurationUnit configurationUnitDifferentIdentifier = this.ConfigurationUnit();
     66             string sharedIdentifier = "SameIdentifier";
     67             configurationUnit1.Identifier = sharedIdentifier;
     68             configurationUnit2.Identifier = sharedIdentifier;
     69             configurationSet.Units = new ConfigurationUnit[] { configurationUnit1, configurationUnit2, configurationUnitDifferentIdentifier };
     70 
     71             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
     72 
     73             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
     74 
     75             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
     76             Assert.NotNull(result);
     77             Assert.NotNull(result.ResultCode);
     78             Assert.Equal(Errors.WINGET_CONFIG_ERROR_DUPLICATE_IDENTIFIER, result.ResultCode.HResult);
     79             Assert.Equal(3, result.UnitResults.Count);
     80 
     81             foreach (var configurationUnit in new ConfigurationUnit[] { configurationUnit1, configurationUnit2 })
     82             {
     83                 ApplyConfigurationUnitResult? unitResult = result.UnitResults.First(x => x.Unit == configurationUnit);
     84                 Assert.NotNull(unitResult);
     85                 Assert.False(unitResult.PreviouslyInDesiredState);
     86                 Assert.False(unitResult.RebootRequired);
     87                 Assert.NotNull(unitResult.ResultInformation);
     88                 Assert.NotNull(unitResult.ResultInformation.ResultCode);
     89                 Assert.Equal(Errors.WINGET_CONFIG_ERROR_DUPLICATE_IDENTIFIER, unitResult.ResultInformation.ResultCode.HResult);
     90                 Assert.Equal(ConfigurationUnitResultSource.ConfigurationSet, unitResult.ResultInformation.ResultSource);
     91             }
     92 
     93             ApplyConfigurationUnitResult unitResultDifferentIdentifier = result.UnitResults.First(x => x.Unit == configurationUnitDifferentIdentifier);
     94             Assert.NotNull(unitResultDifferentIdentifier);
     95             Assert.False(unitResultDifferentIdentifier.PreviouslyInDesiredState);
     96             Assert.False(unitResultDifferentIdentifier.RebootRequired);
     97             Assert.NotNull(unitResultDifferentIdentifier.ResultInformation);
     98             Assert.Null(unitResultDifferentIdentifier.ResultInformation.ResultCode);
     99             Assert.Equal(ConfigurationUnitResultSource.None, unitResultDifferentIdentifier.ResultInformation.ResultSource);
    100 
    101             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.ConfigurationSet);
    102         }
    103 
    104         /// <summary>
    105         /// A configuration unit has a dependency that is not in the set.
    106         /// </summary>
    107         [Fact]
    108         public void ApplySet_MissingDependency()
    109         {
    110             ConfigurationSet configurationSet = this.ConfigurationSet();
    111             ConfigurationUnit configurationUnit = this.ConfigurationUnit();
    112             ConfigurationUnit configurationUnitMissingDependency = this.ConfigurationUnit();
    113             configurationUnit.Identifier = "Identifier";
    114             configurationUnitMissingDependency.Dependencies = new string[] { "Dependency" };
    115             configurationSet.Units = new ConfigurationUnit[] { configurationUnit, configurationUnitMissingDependency };
    116 
    117             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    118 
    119             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    120 
    121             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    122             Assert.NotNull(result);
    123             Assert.NotNull(result.ResultCode);
    124             Assert.Equal(Errors.WINGET_CONFIG_ERROR_MISSING_DEPENDENCY, result.ResultCode.HResult);
    125             Assert.Equal(2, result.UnitResults.Count);
    126 
    127             ApplyConfigurationUnitResult unitResult = result.UnitResults.First(x => x.Unit == configurationUnit);
    128             Assert.NotNull(unitResult);
    129             Assert.False(unitResult.PreviouslyInDesiredState);
    130             Assert.False(unitResult.RebootRequired);
    131             Assert.NotNull(unitResult.ResultInformation);
    132             Assert.Null(unitResult.ResultInformation.ResultCode);
    133             Assert.Equal(ConfigurationUnitResultSource.None, unitResult.ResultInformation.ResultSource);
    134 
    135             unitResult = result.UnitResults.First(x => x.Unit == configurationUnitMissingDependency);
    136             Assert.NotNull(unitResult);
    137             Assert.False(unitResult.PreviouslyInDesiredState);
    138             Assert.False(unitResult.RebootRequired);
    139             Assert.NotNull(unitResult.ResultInformation);
    140             Assert.NotNull(unitResult.ResultInformation.ResultCode);
    141             Assert.Equal(Errors.WINGET_CONFIG_ERROR_MISSING_DEPENDENCY, unitResult.ResultInformation.ResultCode.HResult);
    142             Assert.Equal(ConfigurationUnitResultSource.ConfigurationSet, unitResult.ResultInformation.ResultSource);
    143 
    144             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.ConfigurationSet);
    145         }
    146 
    147         /// <summary>
    148         /// The configuration set has a dependency cycle.
    149         /// </summary>
    150         [Fact]
    151         public void ApplySet_DependencyCycle()
    152         {
    153             ConfigurationSet configurationSet = this.ConfigurationSet();
    154             ConfigurationUnit configurationUnit1 = this.ConfigurationUnit();
    155             ConfigurationUnit configurationUnit2 = this.ConfigurationUnit();
    156             ConfigurationUnit configurationUnit3 = this.ConfigurationUnit();
    157             configurationUnit1.Identifier = "Identifier1";
    158             configurationUnit2.Identifier = "Identifier2";
    159             configurationUnit3.Identifier = "Identifier3";
    160             configurationUnit1.Dependencies = new string[] { "Identifier3" };
    161             configurationUnit2.Dependencies = new string[] { "Identifier1" };
    162             configurationUnit3.Dependencies = new string[] { "Identifier2" };
    163             configurationSet.Units = new ConfigurationUnit[] { configurationUnit1, configurationUnit2, configurationUnit3 };
    164 
    165             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    166 
    167             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    168 
    169             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    170             Assert.NotNull(result);
    171             Assert.NotNull(result.ResultCode);
    172             Assert.Equal(Errors.WINGET_CONFIG_ERROR_SET_DEPENDENCY_CYCLE, result.ResultCode.HResult);
    173             Assert.Equal(3, result.UnitResults.Count);
    174 
    175             foreach (var unitResult in result.UnitResults)
    176             {
    177                 Assert.NotNull(unitResult);
    178                 Assert.False(unitResult.PreviouslyInDesiredState);
    179                 Assert.False(unitResult.RebootRequired);
    180                 Assert.NotNull(unitResult.ResultInformation);
    181                 Assert.NotNull(unitResult.ResultInformation.ResultCode);
    182                 Assert.Equal(Errors.WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED, unitResult.ResultInformation.ResultCode.HResult);
    183                 Assert.Equal(ConfigurationUnitResultSource.Precondition, unitResult.ResultInformation.ResultSource);
    184             }
    185 
    186             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.Precondition);
    187         }
    188 
    189         /// <summary>
    190         /// Checks that the intent for configuration units is handled properly.
    191         /// </summary>
    192         [Fact]
    193         public void ApplySet_IntentRespected()
    194         {
    195             ConfigurationSet configurationSet = this.ConfigurationSet();
    196             ConfigurationUnit configurationUnitAssert = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Assert });
    197             ConfigurationUnit configurationUnitInform = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Inform });
    198             ConfigurationUnit configurationUnitApply = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    199             configurationSet.Units = new ConfigurationUnit[] { configurationUnitInform, configurationUnitApply, configurationUnitAssert };
    200 
    201             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    202             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    203             TestConfigurationUnitProcessor unitProcessorAssert = setProcessor.CreateTestProcessor(configurationUnitAssert);
    204             TestConfigurationUnitProcessor unitProcessorInform = setProcessor.CreateTestProcessor(configurationUnitInform);
    205             TestConfigurationUnitProcessor unitProcessorApply = setProcessor.CreateTestProcessor(configurationUnitApply);
    206             unitProcessorApply.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    207 
    208             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    209 
    210             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    211             Assert.NotNull(result);
    212             Assert.Null(result.ResultCode);
    213             Assert.Equal(3, result.UnitResults.Count);
    214 
    215             foreach (var unitResult in result.UnitResults)
    216             {
    217                 Assert.NotNull(unitResult);
    218                 Assert.False(unitResult.PreviouslyInDesiredState);
    219                 Assert.False(unitResult.RebootRequired);
    220                 Assert.NotNull(unitResult.ResultInformation);
    221                 Assert.Null(unitResult.ResultInformation.ResultCode);
    222                 Assert.Equal(ConfigurationUnitResultSource.None, unitResult.ResultInformation.ResultSource);
    223             }
    224 
    225             Assert.Equal(1, unitProcessorAssert.TestSettingsCalls);
    226             Assert.Equal(0, unitProcessorAssert.GetSettingsCalls);
    227             Assert.Equal(0, unitProcessorAssert.ApplySettingsCalls);
    228 
    229             Assert.Equal(0, unitProcessorInform.TestSettingsCalls);
    230             Assert.Equal(1, unitProcessorInform.GetSettingsCalls);
    231             Assert.Equal(0, unitProcessorInform.ApplySettingsCalls);
    232 
    233             Assert.Equal(1, unitProcessorApply.TestSettingsCalls);
    234             Assert.Equal(0, unitProcessorApply.GetSettingsCalls);
    235             Assert.Equal(1, unitProcessorApply.ApplySettingsCalls);
    236 
    237             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.None);
    238         }
    239 
    240         /// <summary>
    241         /// An assertion fails to run.
    242         /// </summary>
    243         [Fact]
    244         public void ApplySet_AssertionFailure()
    245         {
    246             ConfigurationSet configurationSet = this.ConfigurationSet();
    247             ConfigurationUnit configurationUnitAssert = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Assert });
    248             ConfigurationUnit configurationUnitApply = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    249             configurationSet.Units = new ConfigurationUnit[] { configurationUnitApply, configurationUnitAssert };
    250 
    251             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    252             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    253             TestConfigurationUnitProcessor unitProcessorAssert = setProcessor.CreateTestProcessor(configurationUnitAssert);
    254             unitProcessorAssert.TestSettingsDelegate = () => throw new NullReferenceException();
    255             TestConfigurationUnitProcessor unitProcessorApply = setProcessor.CreateTestProcessor(configurationUnitApply);
    256             unitProcessorApply.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    257 
    258             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    259 
    260             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    261             Assert.NotNull(result);
    262             Assert.NotNull(result.ResultCode);
    263             Assert.Equal(Errors.WINGET_CONFIG_ERROR_ASSERTION_FAILED, result.ResultCode.HResult);
    264             Assert.Equal(2, result.UnitResults.Count);
    265 
    266             ApplyConfigurationUnitResult unitResult = result.UnitResults.First(x => x.Unit == configurationUnitAssert);
    267             Assert.NotNull(unitResult);
    268             Assert.False(unitResult.PreviouslyInDesiredState);
    269             Assert.False(unitResult.RebootRequired);
    270             Assert.NotNull(unitResult.ResultInformation);
    271             Assert.NotNull(unitResult.ResultInformation.ResultCode);
    272             Assert.IsType<NullReferenceException>(unitResult.ResultInformation.ResultCode);
    273             Assert.Equal(ConfigurationUnitResultSource.Internal, unitResult.ResultInformation.ResultSource);
    274 
    275             unitResult = result.UnitResults.First(x => x.Unit == configurationUnitApply);
    276             Assert.NotNull(unitResult);
    277             Assert.False(unitResult.PreviouslyInDesiredState);
    278             Assert.False(unitResult.RebootRequired);
    279             Assert.NotNull(unitResult.ResultInformation);
    280             Assert.NotNull(unitResult.ResultInformation.ResultCode);
    281             Assert.Equal(Errors.WINGET_CONFIG_ERROR_ASSERTION_FAILED, unitResult.ResultInformation.ResultCode.HResult);
    282             Assert.Equal(ConfigurationUnitResultSource.Precondition, unitResult.ResultInformation.ResultSource);
    283 
    284             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.Internal);
    285         }
    286 
    287         /// <summary>
    288         /// An assertion is found to be false.
    289         /// </summary>
    290         [Fact]
    291         public void ApplySet_AssertionNegative()
    292         {
    293             ConfigurationSet configurationSet = this.ConfigurationSet();
    294             ConfigurationUnit configurationUnitAssert = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Assert });
    295             ConfigurationUnit configurationUnitApply = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    296             configurationSet.Units = new ConfigurationUnit[] { configurationUnitApply, configurationUnitAssert };
    297 
    298             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    299             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    300             TestConfigurationUnitProcessor unitProcessorAssert = setProcessor.CreateTestProcessor(configurationUnitAssert);
    301             unitProcessorAssert.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitAssert) { TestResult = ConfigurationTestResult.Negative };
    302             TestConfigurationUnitProcessor unitProcessorApply = setProcessor.CreateTestProcessor(configurationUnitApply);
    303             unitProcessorApply.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    304 
    305             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    306 
    307             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    308             Assert.NotNull(result);
    309             Assert.NotNull(result.ResultCode);
    310             Assert.Equal(Errors.WINGET_CONFIG_ERROR_ASSERTION_FAILED, result.ResultCode.HResult);
    311             Assert.Equal(2, result.UnitResults.Count);
    312 
    313             foreach (var unitResult in result.UnitResults)
    314             {
    315                 Assert.NotNull(unitResult);
    316                 Assert.False(unitResult.PreviouslyInDesiredState);
    317                 Assert.False(unitResult.RebootRequired);
    318                 Assert.NotNull(unitResult.ResultInformation);
    319                 Assert.NotNull(unitResult.ResultInformation.ResultCode);
    320                 Assert.Equal(Errors.WINGET_CONFIG_ERROR_ASSERTION_FAILED, unitResult.ResultInformation.ResultCode.HResult);
    321                 Assert.Equal(ConfigurationUnitResultSource.Precondition, unitResult.ResultInformation.ResultSource);
    322             }
    323 
    324             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.Precondition);
    325         }
    326 
    327         /// <summary>
    328         /// A unit in the correct state is not applied again.
    329         /// </summary>
    330         [Fact]
    331         public void ApplySet_UnitAlreadyInCorrectState()
    332         {
    333             ConfigurationSet configurationSet = this.ConfigurationSet();
    334             ConfigurationUnit configurationUnit = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    335             configurationSet.Units = new ConfigurationUnit[] { configurationUnit };
    336 
    337             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    338             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    339             TestConfigurationUnitProcessor unitProcessor = setProcessor.CreateTestProcessor(configurationUnit);
    340             unitProcessor.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnit) { TestResult = ConfigurationTestResult.Positive };
    341 
    342             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    343 
    344             ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None);
    345             Assert.NotNull(result);
    346             Assert.Null(result.ResultCode);
    347             Assert.Equal(1, result.UnitResults.Count);
    348 
    349             ApplyConfigurationUnitResult unitResult = result.UnitResults.First();
    350             Assert.NotNull(unitResult);
    351             Assert.True(unitResult.PreviouslyInDesiredState);
    352             Assert.False(unitResult.RebootRequired);
    353             Assert.NotNull(unitResult.ResultInformation);
    354             Assert.Null(unitResult.ResultInformation.ResultCode);
    355             Assert.Equal(ConfigurationUnitResultSource.None, unitResult.ResultInformation.ResultSource);
    356 
    357             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.None);
    358         }
    359 
    360         /// <summary>
    361         /// Checks the progress reporting.
    362         /// </summary>
    363         [Fact]
    364         public void ApplySet_Progress()
    365         {
    366             ConfigurationSet configurationSet = this.ConfigurationSet();
    367             ConfigurationUnit assert1 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Assert, Identifier = "Assert1" });
    368             ConfigurationUnit assert2 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Assert, Identifier = "Assert2", Dependencies = new string[] { assert1.Identifier } });
    369             ConfigurationUnit inform1 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Inform, Identifier = "Inform1" });
    370             ConfigurationUnit apply1 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply, Identifier = "Apply1" });
    371             ConfigurationUnit apply2 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply, Identifier = "Apply2" });
    372             ConfigurationUnit apply3 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply, Identifier = "Apply3", Dependencies = new string[] { apply1.Identifier, apply2.Identifier } });
    373             ConfigurationUnit apply4 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply, Identifier = "Apply4", IsActive = false });
    374             ConfigurationUnit apply5 = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply, Identifier = "Apply5", Dependencies = new string[] { apply4.Identifier } });
    375             configurationSet.Units = new ConfigurationUnit[] { assert2, assert1, inform1, apply1, apply3, apply4,  apply2, apply5 };
    376 
    377             ManualResetEvent startProcessing = new ManualResetEvent(false);
    378 
    379             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    380             factory.CreateSetProcessorDelegate = (f, c) =>
    381             {
    382                 startProcessing.WaitOne();
    383                 return f.DefaultCreateSetProcessor(c);
    384             };
    385             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    386             List<ConfigurationSetChangeData> progressEvents = new List<ConfigurationSetChangeData>();
    387 
    388             var operation = processor.ApplySetAsync(configurationSet, ApplyConfigurationSetFlags.None);
    389             operation.Progress = (asyncInfo, progress) => progressEvents.Add(progress);
    390             startProcessing.Set();
    391             operation.AsTask().Wait();
    392             ApplyConfigurationSetResult result = operation.GetResults();
    393 
    394             Assert.NotNull(result);
    395             Assert.NotNull(result.ResultCode);
    396             Assert.Equal(Errors.WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED, result.ResultCode.HResult);
    397             Assert.NotNull(result.UnitResults);
    398             Assert.Equal(configurationSet.Units.Count, result.UnitResults.Count);
    399 
    400             // Verify that progress events match the expected
    401             ExpectedConfigurationChangeData[] expectedProgress = new ExpectedConfigurationChangeData[]
    402             {
    403                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.SetStateChanged, SetState = ConfigurationSetState.InProgress },
    404                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = assert1 },
    405                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = assert1 },
    406                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = assert2 },
    407                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = assert2 },
    408                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = inform1 },
    409                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = inform1 },
    410                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = apply1 },
    411                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = apply1 },
    412                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Skipped, Unit = apply4, HResult = Errors.WINGET_CONFIG_ERROR_MANUALLY_SKIPPED },
    413                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = apply2 },
    414                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = apply2 },
    415                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.InProgress, Unit = apply3 },
    416                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Completed, Unit = apply3 },
    417                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.UnitStateChanged, UnitState = ConfigurationUnitState.Skipped, Unit = apply5, HResult = Errors.WINGET_CONFIG_ERROR_DEPENDENCY_UNSATISFIED },
    418                 new ExpectedConfigurationChangeData() { Change = ConfigurationSetChangeEventType.SetStateChanged, SetState = ConfigurationSetState.Completed },
    419             };
    420 
    421             // Drop the pending event if it happens to be present
    422             if (progressEvents.Count > 0 && progressEvents[0].Change == ConfigurationSetChangeEventType.SetStateChanged && progressEvents[0].SetState == ConfigurationSetState.Pending)
    423             {
    424                 progressEvents.RemoveAt(0);
    425             }
    426 
    427             Assert.Equal(expectedProgress.Count(), progressEvents.Count);
    428 
    429             for (int i = 0; i < progressEvents.Count; ++i)
    430             {
    431                 this.Log.WriteLine($"Comparing event {i}");
    432                 Assert.Equal(expectedProgress[i].Change, progressEvents[i].Change);
    433                 switch (expectedProgress[i].Change)
    434                 {
    435                     case ConfigurationSetChangeEventType.SetStateChanged:
    436                         Assert.Equal(expectedProgress[i].SetState, progressEvents[i].SetState);
    437                         break;
    438                     case ConfigurationSetChangeEventType.UnitStateChanged:
    439                         Assert.Equal(expectedProgress[i].UnitState, progressEvents[i].UnitState);
    440                         Assert.Same(expectedProgress[i].Unit, progressEvents[i].Unit);
    441 
    442                         Assert.NotNull(progressEvents[i].ResultInformation);
    443                         if (expectedProgress[i].HResult == 0)
    444                         {
    445                             Assert.Null(progressEvents[i].ResultInformation.ResultCode);
    446                             Assert.Equal(ConfigurationUnitResultSource.None, progressEvents[i].ResultInformation.ResultSource);
    447                         }
    448                         else
    449                         {
    450                             Assert.NotNull(progressEvents[i].ResultInformation.ResultCode);
    451                             Assert.Equal(expectedProgress[i].HResult, progressEvents[i].ResultInformation.ResultCode.HResult);
    452                             Assert.Equal(ConfigurationUnitResultSource.Precondition, progressEvents[i].ResultInformation.ResultSource);
    453                         }
    454 
    455                         break;
    456                     default:
    457                         Assert.Fail("Unexpected ConfigurationSetChangeEventType value");
    458                         break;
    459                 }
    460             }
    461 
    462             this.VerifySummaryEvent(configurationSet, result, ConfigurationUnitResultSource.Precondition);
    463         }
    464 
    465         /// <summary>
    466         /// Ensures that multiple apply operations are sequenced.
    467         /// </summary>
    468         [Fact]
    469         public void ApplySet_Sequenced()
    470         {
    471             ConfigurationSet configurationSet = this.ConfigurationSet();
    472             ConfigurationUnit configurationUnitApply = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    473             configurationSet.Units = new ConfigurationUnit[] { configurationUnitApply };
    474 
    475             ManualResetEvent startProcessing = new ManualResetEvent(true);
    476             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    477             factory.CreateSetProcessorDelegate = (f, c) =>
    478             {
    479                 WaitOn(startProcessing);
    480                 return f.DefaultCreateSetProcessor(c);
    481             };
    482 
    483             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    484             TestConfigurationUnitProcessor unitProcessorApply = setProcessor.CreateTestProcessor(configurationUnitApply);
    485             unitProcessorApply.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    486 
    487             ManualResetEvent applyEventWaiting = new ManualResetEvent(false);
    488             ManualResetEvent completeApplyEvent = new ManualResetEvent(false);
    489             unitProcessorApply.ApplySettingsDelegate = () =>
    490             {
    491                 applyEventWaiting.Set();
    492                 WaitOn(completeApplyEvent);
    493                 return new ApplySettingsResultInstance(configurationUnitApply);
    494             };
    495 
    496             ConfigurationSet configurationSetThatWaits = this.ConfigurationSet();
    497             ConfigurationUnit configurationUnitThatWaits = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    498             configurationSetThatWaits.Units = new ConfigurationUnit[] { configurationUnitThatWaits };
    499 
    500             TestConfigurationSetProcessor setThatWaitsProcessor = factory.CreateTestProcessor(configurationSetThatWaits);
    501             TestConfigurationUnitProcessor unitThatWaitsProcessor = setProcessor.CreateTestProcessor(configurationUnitThatWaits);
    502             unitThatWaitsProcessor.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    503 
    504             ManualResetEvent waitingUnitApply = new ManualResetEvent(false);
    505             unitThatWaitsProcessor.ApplySettingsDelegate = () =>
    506             {
    507                 WaitOn(waitingUnitApply);
    508                 return new ApplySettingsResultInstance(configurationUnitThatWaits);
    509             };
    510 
    511             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    512 
    513             var applySetOperation = processor.ApplySetAsync(configurationSet, ApplyConfigurationSetFlags.None);
    514             WaitOn(applyEventWaiting);
    515 
    516             startProcessing.Reset();
    517             var waitingSetOperation = processor.ApplySetAsync(configurationSetThatWaits, ApplyConfigurationSetFlags.None);
    518             AutoResetEvent waitingProgress = new AutoResetEvent(false);
    519             ConfigurationSetState progressState = ConfigurationSetState.Unknown;
    520             waitingSetOperation.Progress += (result, changeData) =>
    521             {
    522                 if (changeData.Change == ConfigurationSetChangeEventType.SetStateChanged)
    523                 {
    524                     progressState = changeData.SetState;
    525                     waitingProgress.Set();
    526                 }
    527             };
    528 
    529             startProcessing.Set();
    530             WaitOn(waitingProgress);
    531             Assert.Equal(ConfigurationSetState.Pending, progressState);
    532 
    533             completeApplyEvent.Set();
    534             WaitOn(waitingProgress);
    535             Assert.Equal(ConfigurationSetState.InProgress, progressState);
    536 
    537             waitingUnitApply.Set();
    538             WaitOn(waitingProgress);
    539             Assert.Equal(ConfigurationSetState.Completed, progressState);
    540 
    541             waitingSetOperation.AsTask().Wait();
    542         }
    543 
    544         /// <summary>
    545         /// Ensures that a consistency check apply is not blocked.
    546         /// </summary>
    547         [Fact]
    548         public void ApplySet_ConsistencyCheckNotSequenced()
    549         {
    550             ConfigurationSet configurationSet = this.ConfigurationSet();
    551             ConfigurationUnit configurationUnitApply = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    552             configurationSet.Units = new ConfigurationUnit[] { configurationUnitApply };
    553 
    554             ManualResetEvent startProcessing = new ManualResetEvent(true);
    555             TestConfigurationProcessorFactory factory = new TestConfigurationProcessorFactory();
    556             factory.CreateSetProcessorDelegate = (f, c) =>
    557             {
    558                 WaitOn(startProcessing);
    559                 return f.DefaultCreateSetProcessor(c);
    560             };
    561 
    562             TestConfigurationSetProcessor setProcessor = factory.CreateTestProcessor(configurationSet);
    563             TestConfigurationUnitProcessor unitProcessorApply = setProcessor.CreateTestProcessor(configurationUnitApply);
    564             unitProcessorApply.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    565 
    566             ManualResetEvent applyEventWaiting = new ManualResetEvent(false);
    567             ManualResetEvent completeApplyEvent = new ManualResetEvent(false);
    568             unitProcessorApply.ApplySettingsDelegate = () =>
    569             {
    570                 applyEventWaiting.Set();
    571                 WaitOn(completeApplyEvent);
    572                 return new ApplySettingsResultInstance(configurationUnitApply);
    573             };
    574 
    575             ConfigurationSet configurationSetThatWaits = this.ConfigurationSet();
    576             ConfigurationUnit configurationUnitThatWaits = this.ConfigurationUnit().Assign(new { Intent = ConfigurationUnitIntent.Apply });
    577             configurationSetThatWaits.Units = new ConfigurationUnit[] { configurationUnitThatWaits };
    578 
    579             TestConfigurationSetProcessor setThatWaitsProcessor = factory.CreateTestProcessor(configurationSetThatWaits);
    580             TestConfigurationUnitProcessor unitThatWaitsProcessor = setProcessor.CreateTestProcessor(configurationUnitThatWaits);
    581             unitThatWaitsProcessor.TestSettingsDelegate = () => new TestSettingsResultInstance(configurationUnitApply) { TestResult = ConfigurationTestResult.Negative };
    582 
    583             ManualResetEvent waitingUnitApply = new ManualResetEvent(false);
    584             unitThatWaitsProcessor.ApplySettingsDelegate = () =>
    585             {
    586                 WaitOn(waitingUnitApply);
    587                 return new ApplySettingsResultInstance(configurationUnitThatWaits);
    588             };
    589 
    590             ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(factory);
    591 
    592             var applySetOperation = processor.ApplySetAsync(configurationSet, ApplyConfigurationSetFlags.None);
    593             WaitOn(applyEventWaiting);
    594 
    595             startProcessing.Reset();
    596             var waitingSetOperation = processor.ApplySetAsync(configurationSetThatWaits, ApplyConfigurationSetFlags.PerformConsistencyCheckOnly);
    597             Assert.True(waitingSetOperation.AsTask().Wait(10000));
    598 
    599             completeApplyEvent.Set();
    600         }
    601 
    602         private static void WaitOn(WaitHandle waitable)
    603         {
    604             if (!waitable.WaitOne(10000))
    605             {
    606                 throw new TimeoutException();
    607             }
    608         }
    609 
    610         private struct ExpectedConfigurationChangeData
    611         {
    612             public ConfigurationSetChangeEventType Change;
    613             public ConfigurationSetState SetState;
    614             public ConfigurationUnitState UnitState;
    615             public int HResult;
    616             public ConfigurationUnit Unit;
    617         }
    618     }
    619 }