TestConfigurationUnitGroupProcessor.cs (8198B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="TestConfigurationUnitGroupProcessor.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.UnitTests.Helpers 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.Diagnostics; 12 using System.Runtime.InteropServices.WindowsRuntime; 13 using System.Threading; 14 using System.Threading.Tasks; 15 using Windows.Foundation; 16 using Windows.Foundation.Collections; 17 18 /// <summary> 19 /// A test implementation of IConfigurationGroupProcessor. 20 /// </summary> 21 internal partial class TestConfigurationUnitGroupProcessor : TestConfigurationUnitProcessor, IConfigurationGroupProcessor 22 { 23 /// <summary> 24 /// The Setting key that will be used to set the TestResult of the unit. 25 /// </summary> 26 internal const string TestResultSetting = "TestResult"; 27 28 /// <summary> 29 /// The event that is waited on before actually processing the async operations. 30 /// </summary> 31 private AutoResetEvent asyncWaitEvent = new AutoResetEvent(false); 32 33 /// <summary> 34 /// Initializes a new instance of the <see cref="TestConfigurationUnitGroupProcessor"/> class. 35 /// </summary> 36 /// <param name="unit">The unit that this processor is for.</param> 37 internal TestConfigurationUnitGroupProcessor(ConfigurationUnit unit) 38 : base(unit) 39 { 40 } 41 42 /// <summary> 43 /// Gets the group that this processor targets. 44 /// </summary> 45 public object Group 46 { 47 get { return this.Unit; } 48 } 49 50 /// <summary> 51 /// Gets or sets a value indicating whether the async methods should wait on an event before processing. 52 /// </summary> 53 internal bool ShouldWaitOnAsyncEvent { get; set; } = false; 54 55 /// <summary> 56 /// Apply settings for the group. 57 /// </summary> 58 /// <param name="progressHandler">The progress handler.</param> 59 /// <returns>The operation to apply settings.</returns> 60 public IAsyncOperation<IApplyGroupSettingsResult> ApplyGroupSettingsAsync(EventHandler<IApplyGroupMemberSettingsResult> progressHandler) 61 { 62 return AsyncInfo.Run((CancellationToken cancellationToken) => Task.Run<IApplyGroupSettingsResult>(() => 63 { 64 this.WaitOnAsyncEvent(cancellationToken); 65 66 ApplyGroupSettingsResultInstance result = new (this.Group); 67 result.UnitResults = new List<IApplyGroupMemberSettingsResult>(); 68 69 ApplyGroupSettings(this.Unit.Units, progressHandler, result); 70 71 return result; 72 })); 73 } 74 75 /// <summary> 76 /// Test settings for the group. 77 /// </summary> 78 /// <param name="progressHandler">The progress handler.</param> 79 /// <returns>The operation to test settings.</returns> 80 public IAsyncOperation<ITestGroupSettingsResult> TestGroupSettingsAsync(EventHandler<ITestSettingsResult> progressHandler) 81 { 82 return AsyncInfo.Run((CancellationToken cancellationToken) => Task.Run<ITestGroupSettingsResult>(() => 83 { 84 this.WaitOnAsyncEvent(cancellationToken); 85 86 TestGroupSettingsResultInstance result = new (this.Group); 87 result.UnitResults = new List<ITestSettingsResult>(); 88 89 result.TestResult = GetTestResult(this.Unit.Metadata); 90 TestGroupSettings(this.Unit.Units, progressHandler, result); 91 92 return result; 93 })); 94 } 95 96 /// <summary> 97 /// Gets the tests result for the given unit. 98 /// </summary> 99 /// <param name="unit">The unit.</param> 100 /// <returns>The test result for the unit.</returns> 101 internal static ConfigurationTestResult GetTestResult(ConfigurationUnit unit) 102 { 103 return GetTestResult(unit.Settings); 104 } 105 106 /// <summary> 107 /// Gets the tests result for the given values. 108 /// </summary> 109 /// <param name="values">The values.</param> 110 /// <returns>The test result for the values.</returns> 111 internal static ConfigurationTestResult GetTestResult(ValueSet values) 112 { 113 if (values.ContainsKey(TestResultSetting)) 114 { 115 string? valueString = values[TestResultSetting]?.ToString(); 116 if (valueString != null) 117 { 118 return Enum.Parse<ConfigurationTestResult>(valueString); 119 } 120 } 121 122 return ConfigurationTestResult.Positive; 123 } 124 125 /// <summary> 126 /// Applies group settings for the given group members. 127 /// </summary> 128 /// <param name="groupMembers">The group members.</param> 129 /// <param name="progress">The progress reporting object.</param> 130 /// <param name="result">The result object.</param> 131 internal static void ApplyGroupSettings(IList<ConfigurationUnit>? groupMembers, EventHandler<IApplyGroupMemberSettingsResult> progress, ApplyGroupSettingsResultInstance result) 132 { 133 if (groupMembers != null) 134 { 135 foreach (ConfigurationUnit unit in groupMembers) 136 { 137 ApplyGroupMemberSettingsResultInstance unitResult = new (unit); 138 result.UnitResults!.Add(unitResult); 139 140 unitResult.State = ConfigurationUnitState.InProgress; 141 progress.Invoke(null, unitResult); 142 143 unitResult.PreviouslyInDesiredState = GetTestResult(unit) == ConfigurationTestResult.Positive; 144 145 if (unit.IsGroup) 146 { 147 ApplyGroupSettings(unit.Units, progress, result); 148 } 149 150 unitResult.State = ConfigurationUnitState.Completed; 151 progress.Invoke(null, unitResult); 152 } 153 } 154 } 155 156 /// <summary> 157 /// Tests group settings for the given group members. 158 /// </summary> 159 /// <param name="groupMembers">The group members.</param> 160 /// <param name="progress">The progress reporting object.</param> 161 /// <param name="result">The result object.</param> 162 internal static void TestGroupSettings(IList<ConfigurationUnit>? groupMembers, EventHandler<ITestSettingsResult> progress, TestGroupSettingsResultInstance result) 163 { 164 if (groupMembers != null) 165 { 166 foreach (ConfigurationUnit unit in groupMembers) 167 { 168 TestSettingsResultInstance unitResult = new (unit); 169 170 if (unit.IsGroup) 171 { 172 TestGroupSettings(unit.Units, progress, result); 173 } 174 175 unitResult.TestResult = GetTestResult(unit); 176 result.UnitResults!.Add(unitResult); 177 progress.Invoke(null, unitResult); 178 } 179 } 180 } 181 182 /// <summary> 183 /// Signals the async event. 184 /// </summary> 185 internal void SignalAsyncEvent() 186 { 187 this.asyncWaitEvent.Set(); 188 } 189 190 /// <summary> 191 /// Waits on the async event. 192 /// </summary> 193 private void WaitOnAsyncEvent(CancellationToken cancellationToken) 194 { 195 if (this.ShouldWaitOnAsyncEvent) 196 { 197 cancellationToken.Register(() => this.asyncWaitEvent.Set()); 198 if (!this.asyncWaitEvent.WaitOne(10000)) 199 { 200 throw new TimeoutException(); 201 } 202 } 203 } 204 } 205 }