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 }