ConfigurationProcessorTestBase.cs (11227B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ConfigurationProcessorTestBase.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 Microsoft.Management.Configuration.UnitTests.Fixtures; 11 using Windows.Storage.Streams; 12 using Xunit; 13 using Xunit.Abstractions; 14 15 /// <summary> 16 /// Test base that provides helpers for dealing with <see cref="ConfigurationProcessor"/>. 17 /// </summary> 18 public class ConfigurationProcessorTestBase 19 { 20 /// <summary> 21 /// Initializes a new instance of the <see cref="ConfigurationProcessorTestBase"/> class. 22 /// </summary> 23 /// <param name="fixture">Unit test fixture.</param> 24 /// <param name="log">Log helper.</param> 25 protected ConfigurationProcessorTestBase(UnitTestFixture fixture, ITestOutputHelper log) 26 { 27 this.Fixture = fixture; 28 this.Log = log; 29 this.EventSink = new DiagnosticsEventSink(fixture, log); 30 } 31 32 /// <summary> 33 /// Gets the event sink for this test base. 34 /// </summary> 35 protected DiagnosticsEventSink EventSink { get; private set; } 36 37 /// <summary> 38 /// Gets the test fixture. 39 /// </summary> 40 protected UnitTestFixture Fixture { get; private init; } 41 42 /// <summary> 43 /// Gets the output helper. 44 /// </summary> 45 protected ITestOutputHelper Log { get; private init; } 46 47 /// <summary> 48 /// Create a new <see cref="ConfigurationProcessor"/> with the diagnostics event hooked up. 49 /// </summary> 50 /// <param name="factory">The factory to use.</param> 51 /// <returns>The new <see cref="ConfigurationProcessor"/> object.</returns> 52 internal ConfigurationProcessor CreateConfigurationProcessorWithDiagnostics(IConfigurationSetProcessorFactory? factory = null) 53 { 54 ConfigurationProcessor result = this.Fixture.ConfigurationStatics.CreateConfigurationProcessor(factory); 55 result.Diagnostics += this.EventSink.DiagnosticsHandler; 56 result.MinimumLevel = DiagnosticLevel.Verbose; 57 return result; 58 } 59 60 /// <summary> 61 /// Creates an input stream from the given string. 62 /// </summary> 63 /// <param name="contents">The contents that the stream should contain.</param> 64 /// <returns>The created stream.</returns> 65 internal IInputStream CreateStream(string contents) 66 { 67 InMemoryRandomAccessStream result = new InMemoryRandomAccessStream(); 68 69 using (DataWriter writer = new DataWriter(result)) 70 { 71 writer.UnicodeEncoding = UnicodeEncoding.Utf8; 72 writer.WriteString(contents); 73 writer.StoreAsync().AsTask().Wait(); 74 writer.DetachStream(); 75 } 76 77 result.Seek(0); 78 return result; 79 } 80 81 /// <summary> 82 /// Creates an string from the given output stream. 83 /// </summary> 84 /// <param name="stream">The output stream.</param> 85 /// <returns>The created string.</returns> 86 internal string ReadStream(InMemoryRandomAccessStream stream) 87 { 88 string result = string.Empty; 89 using (DataReader reader = new DataReader(stream.GetInputStreamAt(0))) 90 { 91 reader.UnicodeEncoding = UnicodeEncoding.Utf8; 92 reader.LoadAsync((uint)stream.Size).AsTask().Wait(); 93 uint bytesToRead = reader.UnconsumedBufferLength; 94 95 if (bytesToRead > 0) 96 { 97 result = reader.ReadString(bytesToRead); 98 } 99 } 100 101 return result; 102 } 103 104 /// <summary> 105 /// Creates a configuration unit via the configuration statics object. 106 /// </summary> 107 /// <returns>A new configuration unit.</returns> 108 internal ConfigurationUnit ConfigurationUnit() 109 { 110 return this.Fixture.ConfigurationStatics.CreateConfigurationUnit(); 111 } 112 113 /// <summary> 114 /// Creates a configuration parameter via the configuration statics object. 115 /// </summary> 116 /// <returns>A new configuration parameter.</returns> 117 internal ConfigurationParameter ConfigurationParameter() 118 { 119 return this.Fixture.ConfigurationStatics.CreateConfigurationParameter(); 120 } 121 122 /// <summary> 123 /// Creates a configuration set via the configuration statics object. 124 /// </summary> 125 /// <returns>A new configuration set.</returns> 126 internal ConfigurationSet ConfigurationSet() 127 { 128 return this.Fixture.ConfigurationStatics.CreateConfigurationSet(); 129 } 130 131 /// <summary> 132 /// Verifies the summary event generated by a processing run. 133 /// </summary> 134 /// <param name="configurationSet">The configuration set.</param> 135 /// <param name="setResult">The set result.</param> 136 /// <param name="resultSource">The result source.</param> 137 internal void VerifySummaryEvent(ConfigurationSet configurationSet, ApplyConfigurationSetResult setResult, ConfigurationUnitResultSource resultSource) 138 { 139 TelemetryEvent summary = this.VerifySummaryEventShared(configurationSet, ConfigurationUnitIntent.Apply, resultSource == ConfigurationUnitResultSource.None ? 0 : setResult.ResultCode.HResult, resultSource); 140 141 int[] counts = new int[3]; 142 int[] runs = new int[3]; 143 int[] failures = new int[3]; 144 145 var unitResults = setResult.UnitResults; 146 for (int i = 0; i < unitResults.Count; ++i) 147 { 148 ApplyConfigurationUnitResult unitResult = unitResults[i]; 149 SummaryCountByIntent(counts, runs, failures, unitResult.Unit.Intent, unitResult.ResultInformation); 150 } 151 152 VerifySummaryCounts(summary, counts, runs, failures); 153 } 154 155 /// <summary> 156 /// Verifies the summary event generated by a processing run. 157 /// </summary> 158 /// <param name="configurationSet">The configuration set.</param> 159 /// <param name="setResult">The set result.</param> 160 /// <param name="resultCode">The result code.</param> 161 /// <param name="resultSource">The result source.</param> 162 internal void VerifySummaryEvent(ConfigurationSet configurationSet, TestConfigurationSetResult setResult, int resultCode, ConfigurationUnitResultSource resultSource) 163 { 164 TelemetryEvent summary = this.VerifySummaryEventShared(configurationSet, ConfigurationUnitIntent.Assert, resultCode, resultSource); 165 166 int[] counts = new int[3]; 167 int[] runs = new int[3]; 168 int[] failures = new int[3]; 169 170 foreach (TestConfigurationUnitResult unitResult in setResult.UnitResults) 171 { 172 SummaryCountByIntent(counts, runs, failures, unitResult.Unit.Intent, unitResult.ResultInformation); 173 } 174 175 VerifySummaryCounts(summary, counts, runs, failures); 176 } 177 178 private static void SummaryCountByIntent(int[] counts, int[] runs, int[] failures, ConfigurationUnitIntent intent, IConfigurationUnitResultInformation resultInformation) 179 { 180 if (intent == ConfigurationUnitIntent.Unknown) 181 { 182 intent = ConfigurationUnitIntent.Apply; 183 } 184 185 int index = (int)intent; 186 187 counts[index]++; 188 189 if (resultInformation.ResultSource != ConfigurationUnitResultSource.ConfigurationSet && resultInformation.ResultSource != ConfigurationUnitResultSource.Precondition) 190 { 191 runs[index]++; 192 } 193 194 if (resultInformation.ResultCode != null) 195 { 196 failures[index]++; 197 } 198 } 199 200 private static void VerifySummaryCounts(TelemetryEvent summary, int[] counts, int[] runs, int[] failures) 201 { 202 Assert.Equal(counts[(int)ConfigurationUnitIntent.Assert].ToString(), summary.Properties[TelemetryEvent.AssertCount]); 203 Assert.Equal(runs[(int)ConfigurationUnitIntent.Assert].ToString(), summary.Properties[TelemetryEvent.AssertsRun]); 204 Assert.Equal(failures[(int)ConfigurationUnitIntent.Assert].ToString(), summary.Properties[TelemetryEvent.AssertsFailed]); 205 206 Assert.Equal(counts[(int)ConfigurationUnitIntent.Inform].ToString(), summary.Properties[TelemetryEvent.InformCount]); 207 Assert.Equal(runs[(int)ConfigurationUnitIntent.Inform].ToString(), summary.Properties[TelemetryEvent.InformsRun]); 208 Assert.Equal(failures[(int)ConfigurationUnitIntent.Inform].ToString(), summary.Properties[TelemetryEvent.InformsFailed]); 209 210 Assert.Equal(counts[(int)ConfigurationUnitIntent.Apply].ToString(), summary.Properties[TelemetryEvent.ApplyCount]); 211 Assert.Equal(runs[(int)ConfigurationUnitIntent.Apply].ToString(), summary.Properties[TelemetryEvent.AppliesRun]); 212 Assert.Equal(failures[(int)ConfigurationUnitIntent.Apply].ToString(), summary.Properties[TelemetryEvent.AppliesFailed]); 213 } 214 215 /// <summary> 216 /// Verifies the summary event generated by a processing run. 217 /// </summary> 218 /// <param name="configurationSet">The configuration set.</param> 219 /// <param name="runIntent">The run intent.</param> 220 /// <param name="resultCode">The result code.</param> 221 /// <param name="resultSource">The result source.</param> 222 private TelemetryEvent VerifySummaryEventShared(ConfigurationSet configurationSet, ConfigurationUnitIntent runIntent, int resultCode, ConfigurationUnitResultSource resultSource) 223 { 224 Assert.Single(this.EventSink.Events); 225 TelemetryEvent summary = this.EventSink.Events[0]; 226 227 Assert.Equal(TelemetryEvent.ConfigProcessingSummaryName, summary.Name); 228 Assert.NotEqual(string.Empty, summary.CodeVersion); 229 Assert.NotEqual(Guid.Empty, summary.ActivityID); 230 Assert.Equal(string.Empty, summary.Caller); 231 Assert.Equal(configurationSet.InstanceIdentifier, Guid.Parse(summary.Properties[TelemetryEvent.SetID])); 232 Assert.False(int.Parse(summary.Properties[TelemetryEvent.FromHistory]) != 0); 233 Assert.Equal(((int)runIntent).ToString(), summary.Properties[TelemetryEvent.RunIntent]); 234 Assert.Equal(resultCode.ToString(), summary.Properties[TelemetryEvent.Result]); 235 Assert.Equal(((int)resultSource).ToString(), summary.Properties[TelemetryEvent.FailurePoint]); 236 237 return summary; 238 } 239 } 240 }